mirror of
https://github.com/immich-app/immich.git
synced 2025-01-01 08:31:59 +00:00
fix: replace first and last name with single field (#4915)
This commit is contained in:
parent
413ab2c538
commit
7fca0d8da5
98 changed files with 261 additions and 542 deletions
104
cli/src/api/open-api/api.ts
generated
104
cli/src/api/open-api/api.ts
generated
|
@ -1341,24 +1341,18 @@ export interface CreateUserDto {
|
||||||
* @memberof CreateUserDto
|
* @memberof CreateUserDto
|
||||||
*/
|
*/
|
||||||
'externalPath'?: string | null;
|
'externalPath'?: string | null;
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @type {string}
|
|
||||||
* @memberof CreateUserDto
|
|
||||||
*/
|
|
||||||
'firstName': string;
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @type {string}
|
|
||||||
* @memberof CreateUserDto
|
|
||||||
*/
|
|
||||||
'lastName': string;
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @type {boolean}
|
* @type {boolean}
|
||||||
* @memberof CreateUserDto
|
* @memberof CreateUserDto
|
||||||
*/
|
*/
|
||||||
'memoriesEnabled'?: boolean;
|
'memoriesEnabled'?: boolean;
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @type {string}
|
||||||
|
* @memberof CreateUserDto
|
||||||
|
*/
|
||||||
|
'name': string;
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @type {string}
|
* @type {string}
|
||||||
|
@ -2137,12 +2131,6 @@ export interface LoginResponseDto {
|
||||||
* @memberof LoginResponseDto
|
* @memberof LoginResponseDto
|
||||||
*/
|
*/
|
||||||
'accessToken': string;
|
'accessToken': string;
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @type {string}
|
|
||||||
* @memberof LoginResponseDto
|
|
||||||
*/
|
|
||||||
'firstName': string;
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @type {boolean}
|
* @type {boolean}
|
||||||
|
@ -2154,7 +2142,7 @@ export interface LoginResponseDto {
|
||||||
* @type {string}
|
* @type {string}
|
||||||
* @memberof LoginResponseDto
|
* @memberof LoginResponseDto
|
||||||
*/
|
*/
|
||||||
'lastName': string;
|
'name': string;
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @type {string}
|
* @type {string}
|
||||||
|
@ -2391,12 +2379,6 @@ export interface PartnerResponseDto {
|
||||||
* @memberof PartnerResponseDto
|
* @memberof PartnerResponseDto
|
||||||
*/
|
*/
|
||||||
'externalPath': string | null;
|
'externalPath': string | null;
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @type {string}
|
|
||||||
* @memberof PartnerResponseDto
|
|
||||||
*/
|
|
||||||
'firstName': string;
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @type {string}
|
* @type {string}
|
||||||
|
@ -2415,18 +2397,18 @@ export interface PartnerResponseDto {
|
||||||
* @memberof PartnerResponseDto
|
* @memberof PartnerResponseDto
|
||||||
*/
|
*/
|
||||||
'isAdmin': boolean;
|
'isAdmin': boolean;
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @type {string}
|
|
||||||
* @memberof PartnerResponseDto
|
|
||||||
*/
|
|
||||||
'lastName': string;
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @type {boolean}
|
* @type {boolean}
|
||||||
* @memberof PartnerResponseDto
|
* @memberof PartnerResponseDto
|
||||||
*/
|
*/
|
||||||
'memoriesEnabled'?: boolean;
|
'memoriesEnabled'?: boolean;
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @type {string}
|
||||||
|
* @memberof PartnerResponseDto
|
||||||
|
*/
|
||||||
|
'name': string;
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @type {string}
|
* @type {string}
|
||||||
|
@ -3431,13 +3413,7 @@ export interface SignUpDto {
|
||||||
* @type {string}
|
* @type {string}
|
||||||
* @memberof SignUpDto
|
* @memberof SignUpDto
|
||||||
*/
|
*/
|
||||||
'firstName': string;
|
'name': string;
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @type {string}
|
|
||||||
* @memberof SignUpDto
|
|
||||||
*/
|
|
||||||
'lastName': string;
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @type {string}
|
* @type {string}
|
||||||
|
@ -4380,12 +4356,6 @@ export interface UpdateUserDto {
|
||||||
* @memberof UpdateUserDto
|
* @memberof UpdateUserDto
|
||||||
*/
|
*/
|
||||||
'externalPath'?: string;
|
'externalPath'?: string;
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @type {string}
|
|
||||||
* @memberof UpdateUserDto
|
|
||||||
*/
|
|
||||||
'firstName'?: string;
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @type {string}
|
* @type {string}
|
||||||
|
@ -4398,18 +4368,18 @@ export interface UpdateUserDto {
|
||||||
* @memberof UpdateUserDto
|
* @memberof UpdateUserDto
|
||||||
*/
|
*/
|
||||||
'isAdmin'?: boolean;
|
'isAdmin'?: boolean;
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @type {string}
|
|
||||||
* @memberof UpdateUserDto
|
|
||||||
*/
|
|
||||||
'lastName'?: string;
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @type {boolean}
|
* @type {boolean}
|
||||||
* @memberof UpdateUserDto
|
* @memberof UpdateUserDto
|
||||||
*/
|
*/
|
||||||
'memoriesEnabled'?: boolean;
|
'memoriesEnabled'?: boolean;
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @type {string}
|
||||||
|
* @memberof UpdateUserDto
|
||||||
|
*/
|
||||||
|
'name'?: string;
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @type {string}
|
* @type {string}
|
||||||
|
@ -4447,12 +4417,6 @@ export interface UsageByUserDto {
|
||||||
* @memberof UsageByUserDto
|
* @memberof UsageByUserDto
|
||||||
*/
|
*/
|
||||||
'usage': number;
|
'usage': number;
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @type {string}
|
|
||||||
* @memberof UsageByUserDto
|
|
||||||
*/
|
|
||||||
'userFirstName': string;
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @type {string}
|
* @type {string}
|
||||||
|
@ -4464,7 +4428,7 @@ export interface UsageByUserDto {
|
||||||
* @type {string}
|
* @type {string}
|
||||||
* @memberof UsageByUserDto
|
* @memberof UsageByUserDto
|
||||||
*/
|
*/
|
||||||
'userLastName': string;
|
'userName': string;
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @type {number}
|
* @type {number}
|
||||||
|
@ -4484,12 +4448,6 @@ export interface UserDto {
|
||||||
* @memberof UserDto
|
* @memberof UserDto
|
||||||
*/
|
*/
|
||||||
'email': string;
|
'email': string;
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @type {string}
|
|
||||||
* @memberof UserDto
|
|
||||||
*/
|
|
||||||
'firstName': string;
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @type {string}
|
* @type {string}
|
||||||
|
@ -4501,7 +4459,7 @@ export interface UserDto {
|
||||||
* @type {string}
|
* @type {string}
|
||||||
* @memberof UserDto
|
* @memberof UserDto
|
||||||
*/
|
*/
|
||||||
'lastName': string;
|
'name': string;
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @type {string}
|
* @type {string}
|
||||||
|
@ -4539,12 +4497,6 @@ export interface UserResponseDto {
|
||||||
* @memberof UserResponseDto
|
* @memberof UserResponseDto
|
||||||
*/
|
*/
|
||||||
'externalPath': string | null;
|
'externalPath': string | null;
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @type {string}
|
|
||||||
* @memberof UserResponseDto
|
|
||||||
*/
|
|
||||||
'firstName': string;
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @type {string}
|
* @type {string}
|
||||||
|
@ -4557,18 +4509,18 @@ export interface UserResponseDto {
|
||||||
* @memberof UserResponseDto
|
* @memberof UserResponseDto
|
||||||
*/
|
*/
|
||||||
'isAdmin': boolean;
|
'isAdmin': boolean;
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @type {string}
|
|
||||||
* @memberof UserResponseDto
|
|
||||||
*/
|
|
||||||
'lastName': string;
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @type {boolean}
|
* @type {boolean}
|
||||||
* @memberof UserResponseDto
|
* @memberof UserResponseDto
|
||||||
*/
|
*/
|
||||||
'memoriesEnabled'?: boolean;
|
'memoriesEnabled'?: boolean;
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @type {string}
|
||||||
|
* @memberof UserResponseDto
|
||||||
|
*/
|
||||||
|
'name': string;
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @type {string}
|
* @type {string}
|
||||||
|
|
|
@ -51,8 +51,7 @@ immich-admin list-users
|
||||||
{
|
{
|
||||||
id: 'e65e6f88-2a30-4dbe-8dd9-1885f4889b53',
|
id: 'e65e6f88-2a30-4dbe-8dd9-1885f4889b53',
|
||||||
email: 'immich@example.com.com',
|
email: 'immich@example.com.com',
|
||||||
firstName: 'Immich',
|
name: 'Immich Admin',
|
||||||
lastName: 'Admin',
|
|
||||||
storageLabel: 'admin',
|
storageLabel: 'admin',
|
||||||
externalPath: null,
|
externalPath: null,
|
||||||
profileImagePath: 'upload/profile/e65e6f88-2a30-4dbe-8dd9-1885f4889b53/e65e6f88-2a30-4dbe-8dd9-1885f4889b53.jpg',
|
profileImagePath: 'upload/profile/e65e6f88-2a30-4dbe-8dd9-1885f4889b53/e65e6f88-2a30-4dbe-8dd9-1885f4889b53.jpg',
|
||||||
|
|
|
@ -114,7 +114,7 @@
|
||||||
"cache_settings_thumbnail_size": "Thumbnail cache size ({} assets)",
|
"cache_settings_thumbnail_size": "Thumbnail cache size ({} assets)",
|
||||||
"cache_settings_title": "Caching Settings",
|
"cache_settings_title": "Caching Settings",
|
||||||
"change_password_form_confirm_password": "Confirm Password",
|
"change_password_form_confirm_password": "Confirm Password",
|
||||||
"change_password_form_description": "Hi {firstName} {lastName},\n\nThis is either the first time you are signing into the system or a request has been made to change your password. Please enter the new password below.",
|
"change_password_form_description": "Hi {name},\n\nThis is either the first time you are signing into the system or a request has been made to change your password. Please enter the new password below.",
|
||||||
"change_password_form_new_password": "New Password",
|
"change_password_form_new_password": "New Password",
|
||||||
"change_password_form_password_mismatch": "Passwords do not match",
|
"change_password_form_password_mismatch": "Passwords do not match",
|
||||||
"change_password_form_reenter_new_password": "Re-enter New Password",
|
"change_password_form_reenter_new_password": "Re-enter New Password",
|
||||||
|
|
|
@ -48,8 +48,7 @@ class Activity {
|
||||||
: ActivityType.like,
|
: ActivityType.like,
|
||||||
user = User(
|
user = User(
|
||||||
email: dto.user.email,
|
email: dto.user.email,
|
||||||
firstName: dto.user.firstName,
|
name: dto.user.name,
|
||||||
lastName: dto.user.lastName,
|
|
||||||
profileImagePath: dto.user.profileImagePath,
|
profileImagePath: dto.user.profileImagePath,
|
||||||
id: dto.user.id,
|
id: dto.user.id,
|
||||||
// Placeholder values
|
// Placeholder values
|
||||||
|
|
|
@ -61,7 +61,7 @@ class ActivitiesPage extends HookConsumerWidget {
|
||||||
mainAxisSize: leftAlign ? MainAxisSize.min : MainAxisSize.max,
|
mainAxisSize: leftAlign ? MainAxisSize.min : MainAxisSize.max,
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
"${activity.user.firstName} ${activity.user.lastName}",
|
activity.user.name,
|
||||||
style: textStyle,
|
style: textStyle,
|
||||||
overflow: TextOverflow.ellipsis,
|
overflow: TextOverflow.ellipsis,
|
||||||
),
|
),
|
||||||
|
|
|
@ -124,7 +124,7 @@ class AlbumOptionsPage extends HookConsumerWidget {
|
||||||
)
|
)
|
||||||
: const SizedBox(),
|
: const SizedBox(),
|
||||||
title: Text(
|
title: Text(
|
||||||
album.owner.value?.firstName ?? "",
|
album.owner.value?.name ?? "",
|
||||||
style: const TextStyle(
|
style: const TextStyle(
|
||||||
fontWeight: FontWeight.bold,
|
fontWeight: FontWeight.bold,
|
||||||
),
|
),
|
||||||
|
@ -155,7 +155,7 @@ class AlbumOptionsPage extends HookConsumerWidget {
|
||||||
radius: 22,
|
radius: 22,
|
||||||
),
|
),
|
||||||
title: Text(
|
title: Text(
|
||||||
user.firstName,
|
user.name,
|
||||||
style: const TextStyle(
|
style: const TextStyle(
|
||||||
fontWeight: FontWeight.bold,
|
fontWeight: FontWeight.bold,
|
||||||
),
|
),
|
||||||
|
|
|
@ -3,8 +3,7 @@ class AuthenticationState {
|
||||||
final String userId;
|
final String userId;
|
||||||
final String userEmail;
|
final String userEmail;
|
||||||
final bool isAuthenticated;
|
final bool isAuthenticated;
|
||||||
final String firstName;
|
final String name;
|
||||||
final String lastName;
|
|
||||||
final bool isAdmin;
|
final bool isAdmin;
|
||||||
final bool shouldChangePassword;
|
final bool shouldChangePassword;
|
||||||
final String profileImagePath;
|
final String profileImagePath;
|
||||||
|
@ -13,8 +12,7 @@ class AuthenticationState {
|
||||||
required this.userId,
|
required this.userId,
|
||||||
required this.userEmail,
|
required this.userEmail,
|
||||||
required this.isAuthenticated,
|
required this.isAuthenticated,
|
||||||
required this.firstName,
|
required this.name,
|
||||||
required this.lastName,
|
|
||||||
required this.isAdmin,
|
required this.isAdmin,
|
||||||
required this.shouldChangePassword,
|
required this.shouldChangePassword,
|
||||||
required this.profileImagePath,
|
required this.profileImagePath,
|
||||||
|
@ -25,8 +23,7 @@ class AuthenticationState {
|
||||||
String? userId,
|
String? userId,
|
||||||
String? userEmail,
|
String? userEmail,
|
||||||
bool? isAuthenticated,
|
bool? isAuthenticated,
|
||||||
String? firstName,
|
String? name,
|
||||||
String? lastName,
|
|
||||||
bool? isAdmin,
|
bool? isAdmin,
|
||||||
bool? shouldChangePassword,
|
bool? shouldChangePassword,
|
||||||
String? profileImagePath,
|
String? profileImagePath,
|
||||||
|
@ -36,8 +33,7 @@ class AuthenticationState {
|
||||||
userId: userId ?? this.userId,
|
userId: userId ?? this.userId,
|
||||||
userEmail: userEmail ?? this.userEmail,
|
userEmail: userEmail ?? this.userEmail,
|
||||||
isAuthenticated: isAuthenticated ?? this.isAuthenticated,
|
isAuthenticated: isAuthenticated ?? this.isAuthenticated,
|
||||||
firstName: firstName ?? this.firstName,
|
name: name ?? this.name,
|
||||||
lastName: lastName ?? this.lastName,
|
|
||||||
isAdmin: isAdmin ?? this.isAdmin,
|
isAdmin: isAdmin ?? this.isAdmin,
|
||||||
shouldChangePassword: shouldChangePassword ?? this.shouldChangePassword,
|
shouldChangePassword: shouldChangePassword ?? this.shouldChangePassword,
|
||||||
profileImagePath: profileImagePath ?? this.profileImagePath,
|
profileImagePath: profileImagePath ?? this.profileImagePath,
|
||||||
|
@ -46,7 +42,7 @@ class AuthenticationState {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String toString() {
|
String toString() {
|
||||||
return 'AuthenticationState(deviceId: $deviceId, userId: $userId, userEmail: $userEmail, isAuthenticated: $isAuthenticated, firstName: $firstName, lastName: $lastName, isAdmin: $isAdmin, shouldChangePassword: $shouldChangePassword, profileImagePath: $profileImagePath)';
|
return 'AuthenticationState(deviceId: $deviceId, userId: $userId, userEmail: $userEmail, isAuthenticated: $isAuthenticated, name: $name, isAdmin: $isAdmin, shouldChangePassword: $shouldChangePassword, profileImagePath: $profileImagePath)';
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
@ -58,8 +54,7 @@ class AuthenticationState {
|
||||||
other.userId == userId &&
|
other.userId == userId &&
|
||||||
other.userEmail == userEmail &&
|
other.userEmail == userEmail &&
|
||||||
other.isAuthenticated == isAuthenticated &&
|
other.isAuthenticated == isAuthenticated &&
|
||||||
other.firstName == firstName &&
|
other.name == name &&
|
||||||
other.lastName == lastName &&
|
|
||||||
other.isAdmin == isAdmin &&
|
other.isAdmin == isAdmin &&
|
||||||
other.shouldChangePassword == shouldChangePassword &&
|
other.shouldChangePassword == shouldChangePassword &&
|
||||||
other.profileImagePath == profileImagePath;
|
other.profileImagePath == profileImagePath;
|
||||||
|
@ -71,8 +66,7 @@ class AuthenticationState {
|
||||||
userId.hashCode ^
|
userId.hashCode ^
|
||||||
userEmail.hashCode ^
|
userEmail.hashCode ^
|
||||||
isAuthenticated.hashCode ^
|
isAuthenticated.hashCode ^
|
||||||
firstName.hashCode ^
|
name.hashCode ^
|
||||||
lastName.hashCode ^
|
|
||||||
isAdmin.hashCode ^
|
isAdmin.hashCode ^
|
||||||
shouldChangePassword.hashCode ^
|
shouldChangePassword.hashCode ^
|
||||||
profileImagePath.hashCode;
|
profileImagePath.hashCode;
|
||||||
|
|
|
@ -26,8 +26,7 @@ class AuthenticationNotifier extends StateNotifier<AuthenticationState> {
|
||||||
deviceId: "",
|
deviceId: "",
|
||||||
userId: "",
|
userId: "",
|
||||||
userEmail: "",
|
userEmail: "",
|
||||||
firstName: '',
|
name: '',
|
||||||
lastName: '',
|
|
||||||
profileImagePath: '',
|
profileImagePath: '',
|
||||||
isAdmin: false,
|
isAdmin: false,
|
||||||
shouldChangePassword: false,
|
shouldChangePassword: false,
|
||||||
|
@ -117,8 +116,7 @@ class AuthenticationNotifier extends StateNotifier<AuthenticationState> {
|
||||||
deviceId: "",
|
deviceId: "",
|
||||||
userId: "",
|
userId: "",
|
||||||
userEmail: "",
|
userEmail: "",
|
||||||
firstName: '',
|
name: '',
|
||||||
lastName: '',
|
|
||||||
profileImagePath: '',
|
profileImagePath: '',
|
||||||
isAdmin: false,
|
isAdmin: false,
|
||||||
shouldChangePassword: false,
|
shouldChangePassword: false,
|
||||||
|
@ -208,8 +206,7 @@ class AuthenticationNotifier extends StateNotifier<AuthenticationState> {
|
||||||
isAuthenticated: true,
|
isAuthenticated: true,
|
||||||
userId: user.id,
|
userId: user.id,
|
||||||
userEmail: user.email,
|
userEmail: user.email,
|
||||||
firstName: user.firstName,
|
name: user.name,
|
||||||
lastName: user.lastName,
|
|
||||||
profileImagePath: user.profileImagePath,
|
profileImagePath: user.profileImagePath,
|
||||||
isAdmin: user.isAdmin,
|
isAdmin: user.isAdmin,
|
||||||
shouldChangePassword: shouldChangePassword,
|
shouldChangePassword: shouldChangePassword,
|
||||||
|
|
|
@ -46,8 +46,7 @@ class ChangePasswordForm extends HookConsumerWidget {
|
||||||
child: Text(
|
child: Text(
|
||||||
'change_password_form_description'.tr(
|
'change_password_form_description'.tr(
|
||||||
namedArgs: {
|
namedArgs: {
|
||||||
'firstName': authState.firstName,
|
'name': authState.name,
|
||||||
'lastName': authState.lastName,
|
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
|
|
|
@ -24,7 +24,7 @@ class PartnerList extends HookConsumerWidget {
|
||||||
contentPadding: const EdgeInsets.symmetric(horizontal: 12.0),
|
contentPadding: const EdgeInsets.symmetric(horizontal: 12.0),
|
||||||
leading: userAvatar(context, p, radius: 30),
|
leading: userAvatar(context, p, radius: 30),
|
||||||
title: Text(
|
title: Text(
|
||||||
"${p.firstName} ${p.lastName}'s photos",
|
"${p.name}'s photos",
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontWeight: FontWeight.bold,
|
fontWeight: FontWeight.bold,
|
||||||
fontSize: 14,
|
fontSize: 14,
|
||||||
|
|
|
@ -25,7 +25,7 @@ class PartnerDetailPage extends HookConsumerWidget {
|
||||||
|
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
title: Text("${partner.firstName} ${partner.lastName}"),
|
title: Text(partner.name),
|
||||||
elevation: 0,
|
elevation: 0,
|
||||||
centerTitle: false,
|
centerTitle: false,
|
||||||
),
|
),
|
||||||
|
@ -34,7 +34,7 @@ class PartnerDetailPage extends HookConsumerWidget {
|
||||||
? Padding(
|
? Padding(
|
||||||
padding: const EdgeInsets.all(16),
|
padding: const EdgeInsets.all(16),
|
||||||
child: Text(
|
child: Text(
|
||||||
"It seems ${partner.firstName} does not have any photos...\n"
|
"It seems ${partner.name} does not have any photos...\n"
|
||||||
"Or your server version does not match the app version."),
|
"Or your server version does not match the app version."),
|
||||||
)
|
)
|
||||||
: ImmichAssetGrid(
|
: ImmichAssetGrid(
|
||||||
|
|
|
@ -41,7 +41,7 @@ class PartnerPage extends HookConsumerWidget {
|
||||||
padding: const EdgeInsets.only(right: 8),
|
padding: const EdgeInsets.only(right: 8),
|
||||||
child: userAvatar(context, u),
|
child: userAvatar(context, u),
|
||||||
),
|
),
|
||||||
Text("${u.firstName} ${u.lastName}"),
|
Text(u.name),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
@ -71,7 +71,7 @@ class PartnerPage extends HookConsumerWidget {
|
||||||
return ConfirmDialog(
|
return ConfirmDialog(
|
||||||
title: "partner_page_stop_sharing_title",
|
title: "partner_page_stop_sharing_title",
|
||||||
content:
|
content:
|
||||||
"partner_page_stop_sharing_content".tr(args: [u.firstName]),
|
"partner_page_stop_sharing_content".tr(args: [u.name]),
|
||||||
onOk: () => ref.read(partnerServiceProvider).removePartner(u),
|
onOk: () => ref.read(partnerServiceProvider).removePartner(u),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
|
|
@ -68,11 +68,8 @@ class Album {
|
||||||
}
|
}
|
||||||
|
|
||||||
final name = <String>[];
|
final name = <String>[];
|
||||||
if (owner.value?.firstName != null) {
|
if (owner.value?.name != null) {
|
||||||
name.add(owner.value!.firstName);
|
name.add(owner.value!.name);
|
||||||
}
|
|
||||||
if (owner.value?.lastName != null) {
|
|
||||||
name.add(owner.value!.lastName);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return name.join(' ');
|
return name.join(' ');
|
||||||
|
|
|
@ -11,8 +11,7 @@ class User {
|
||||||
required this.id,
|
required this.id,
|
||||||
required this.updatedAt,
|
required this.updatedAt,
|
||||||
required this.email,
|
required this.email,
|
||||||
required this.firstName,
|
required this.name,
|
||||||
required this.lastName,
|
|
||||||
required this.isAdmin,
|
required this.isAdmin,
|
||||||
this.isPartnerSharedBy = false,
|
this.isPartnerSharedBy = false,
|
||||||
this.isPartnerSharedWith = false,
|
this.isPartnerSharedWith = false,
|
||||||
|
@ -27,8 +26,7 @@ class User {
|
||||||
: id = dto.id,
|
: id = dto.id,
|
||||||
updatedAt = dto.updatedAt,
|
updatedAt = dto.updatedAt,
|
||||||
email = dto.email,
|
email = dto.email,
|
||||||
firstName = dto.firstName,
|
name = dto.name,
|
||||||
lastName = dto.lastName,
|
|
||||||
isPartnerSharedBy = false,
|
isPartnerSharedBy = false,
|
||||||
isPartnerSharedWith = false,
|
isPartnerSharedWith = false,
|
||||||
profileImagePath = dto.profileImagePath,
|
profileImagePath = dto.profileImagePath,
|
||||||
|
@ -39,8 +37,7 @@ class User {
|
||||||
: id = dto.id,
|
: id = dto.id,
|
||||||
updatedAt = dto.updatedAt,
|
updatedAt = dto.updatedAt,
|
||||||
email = dto.email,
|
email = dto.email,
|
||||||
firstName = dto.firstName,
|
name = dto.name,
|
||||||
lastName = dto.lastName,
|
|
||||||
isPartnerSharedBy = false,
|
isPartnerSharedBy = false,
|
||||||
isPartnerSharedWith = false,
|
isPartnerSharedWith = false,
|
||||||
profileImagePath = dto.profileImagePath,
|
profileImagePath = dto.profileImagePath,
|
||||||
|
@ -52,8 +49,7 @@ class User {
|
||||||
String id;
|
String id;
|
||||||
DateTime updatedAt;
|
DateTime updatedAt;
|
||||||
String email;
|
String email;
|
||||||
String firstName;
|
String name;
|
||||||
String lastName;
|
|
||||||
bool isPartnerSharedBy;
|
bool isPartnerSharedBy;
|
||||||
bool isPartnerSharedWith;
|
bool isPartnerSharedWith;
|
||||||
bool isAdmin;
|
bool isAdmin;
|
||||||
|
@ -72,8 +68,7 @@ class User {
|
||||||
return id == other.id &&
|
return id == other.id &&
|
||||||
updatedAt.isAtSameMomentAs(other.updatedAt) &&
|
updatedAt.isAtSameMomentAs(other.updatedAt) &&
|
||||||
email == other.email &&
|
email == other.email &&
|
||||||
firstName == other.firstName &&
|
name == other.name &&
|
||||||
lastName == other.lastName &&
|
|
||||||
isPartnerSharedBy == other.isPartnerSharedBy &&
|
isPartnerSharedBy == other.isPartnerSharedBy &&
|
||||||
isPartnerSharedWith == other.isPartnerSharedWith &&
|
isPartnerSharedWith == other.isPartnerSharedWith &&
|
||||||
profileImagePath == other.profileImagePath &&
|
profileImagePath == other.profileImagePath &&
|
||||||
|
@ -88,8 +83,7 @@ class User {
|
||||||
id.hashCode ^
|
id.hashCode ^
|
||||||
updatedAt.hashCode ^
|
updatedAt.hashCode ^
|
||||||
email.hashCode ^
|
email.hashCode ^
|
||||||
firstName.hashCode ^
|
name.hashCode ^
|
||||||
lastName.hashCode ^
|
|
||||||
isPartnerSharedBy.hashCode ^
|
isPartnerSharedBy.hashCode ^
|
||||||
isPartnerSharedWith.hashCode ^
|
isPartnerSharedWith.hashCode ^
|
||||||
profileImagePath.hashCode ^
|
profileImagePath.hashCode ^
|
||||||
|
|
Binary file not shown.
|
@ -132,7 +132,7 @@ class AppBarProfileInfoBox extends HookConsumerWidget {
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
title: Text(
|
title: Text(
|
||||||
"${authState.firstName} ${authState.lastName}",
|
authState.name,
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
color: context.primaryColor,
|
color: context.primaryColor,
|
||||||
fontWeight: FontWeight.bold,
|
fontWeight: FontWeight.bold,
|
||||||
|
|
|
@ -7,8 +7,7 @@ import 'package:immich_mobile/shared/models/user.dart';
|
||||||
Widget userAvatar(BuildContext context, User u, {double? radius}) {
|
Widget userAvatar(BuildContext context, User u, {double? radius}) {
|
||||||
final url =
|
final url =
|
||||||
"${Store.get(StoreKey.serverEndpoint)}/user/profile-image/${u.id}";
|
"${Store.get(StoreKey.serverEndpoint)}/user/profile-image/${u.id}";
|
||||||
final firstNameFirstLetter = u.firstName.isNotEmpty ? u.firstName[0] : "";
|
final nameFirstLetter = u.name.isNotEmpty ? u.name[0] : "";
|
||||||
final lastNameFirstLetter = u.lastName.isNotEmpty ? u.lastName[0] : "";
|
|
||||||
return CircleAvatar(
|
return CircleAvatar(
|
||||||
radius: radius,
|
radius: radius,
|
||||||
backgroundColor: context.primaryColor.withAlpha(50),
|
backgroundColor: context.primaryColor.withAlpha(50),
|
||||||
|
@ -19,6 +18,6 @@ Widget userAvatar(BuildContext context, User u, {double? radius}) {
|
||||||
),
|
),
|
||||||
// silence errors if user has no profile image, use initials as fallback
|
// silence errors if user has no profile image, use initials as fallback
|
||||||
onForegroundImageError: (exception, stackTrace) {},
|
onForegroundImageError: (exception, stackTrace) {},
|
||||||
child: Text((firstNameFirstLetter + lastNameFirstLetter).toUpperCase()),
|
child: Text(nameFirstLetter.toUpperCase()),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,7 +43,7 @@ class UserCircleAvatar extends ConsumerWidget {
|
||||||
'${Store.get(StoreKey.serverEndpoint)}/user/profile-image/${user.id}?d=${Random().nextInt(1024)}';
|
'${Store.get(StoreKey.serverEndpoint)}/user/profile-image/${user.id}?d=${Random().nextInt(1024)}';
|
||||||
|
|
||||||
final textIcon = Text(
|
final textIcon = Text(
|
||||||
user.firstName[0].toUpperCase(),
|
user.name[0].toUpperCase(),
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontWeight: FontWeight.bold,
|
fontWeight: FontWeight.bold,
|
||||||
color: context.isDarkTheme ? Colors.black : Colors.white,
|
color: context.isDarkTheme ? Colors.black : Colors.white,
|
||||||
|
|
BIN
mobile/openapi/doc/CreateUserDto.md
generated
BIN
mobile/openapi/doc/CreateUserDto.md
generated
Binary file not shown.
BIN
mobile/openapi/doc/LoginResponseDto.md
generated
BIN
mobile/openapi/doc/LoginResponseDto.md
generated
Binary file not shown.
BIN
mobile/openapi/doc/PartnerResponseDto.md
generated
BIN
mobile/openapi/doc/PartnerResponseDto.md
generated
Binary file not shown.
BIN
mobile/openapi/doc/SignUpDto.md
generated
BIN
mobile/openapi/doc/SignUpDto.md
generated
Binary file not shown.
BIN
mobile/openapi/doc/UpdateUserDto.md
generated
BIN
mobile/openapi/doc/UpdateUserDto.md
generated
Binary file not shown.
BIN
mobile/openapi/doc/UsageByUserDto.md
generated
BIN
mobile/openapi/doc/UsageByUserDto.md
generated
Binary file not shown.
BIN
mobile/openapi/doc/UserDto.md
generated
BIN
mobile/openapi/doc/UserDto.md
generated
Binary file not shown.
BIN
mobile/openapi/doc/UserResponseDto.md
generated
BIN
mobile/openapi/doc/UserResponseDto.md
generated
Binary file not shown.
BIN
mobile/openapi/lib/model/create_user_dto.dart
generated
BIN
mobile/openapi/lib/model/create_user_dto.dart
generated
Binary file not shown.
BIN
mobile/openapi/lib/model/login_response_dto.dart
generated
BIN
mobile/openapi/lib/model/login_response_dto.dart
generated
Binary file not shown.
BIN
mobile/openapi/lib/model/partner_response_dto.dart
generated
BIN
mobile/openapi/lib/model/partner_response_dto.dart
generated
Binary file not shown.
BIN
mobile/openapi/lib/model/sign_up_dto.dart
generated
BIN
mobile/openapi/lib/model/sign_up_dto.dart
generated
Binary file not shown.
BIN
mobile/openapi/lib/model/update_user_dto.dart
generated
BIN
mobile/openapi/lib/model/update_user_dto.dart
generated
Binary file not shown.
BIN
mobile/openapi/lib/model/usage_by_user_dto.dart
generated
BIN
mobile/openapi/lib/model/usage_by_user_dto.dart
generated
Binary file not shown.
BIN
mobile/openapi/lib/model/user_dto.dart
generated
BIN
mobile/openapi/lib/model/user_dto.dart
generated
Binary file not shown.
BIN
mobile/openapi/lib/model/user_response_dto.dart
generated
BIN
mobile/openapi/lib/model/user_response_dto.dart
generated
Binary file not shown.
BIN
mobile/openapi/test/create_user_dto_test.dart
generated
BIN
mobile/openapi/test/create_user_dto_test.dart
generated
Binary file not shown.
BIN
mobile/openapi/test/login_response_dto_test.dart
generated
BIN
mobile/openapi/test/login_response_dto_test.dart
generated
Binary file not shown.
BIN
mobile/openapi/test/partner_response_dto_test.dart
generated
BIN
mobile/openapi/test/partner_response_dto_test.dart
generated
Binary file not shown.
BIN
mobile/openapi/test/sign_up_dto_test.dart
generated
BIN
mobile/openapi/test/sign_up_dto_test.dart
generated
Binary file not shown.
BIN
mobile/openapi/test/update_user_dto_test.dart
generated
BIN
mobile/openapi/test/update_user_dto_test.dart
generated
Binary file not shown.
BIN
mobile/openapi/test/usage_by_user_dto_test.dart
generated
BIN
mobile/openapi/test/usage_by_user_dto_test.dart
generated
Binary file not shown.
BIN
mobile/openapi/test/user_dto_test.dart
generated
BIN
mobile/openapi/test/user_dto_test.dart
generated
Binary file not shown.
BIN
mobile/openapi/test/user_response_dto_test.dart
generated
BIN
mobile/openapi/test/user_response_dto_test.dart
generated
Binary file not shown.
|
@ -62,8 +62,7 @@ void main() {
|
||||||
id: "1",
|
id: "1",
|
||||||
updatedAt: DateTime.now(),
|
updatedAt: DateTime.now(),
|
||||||
email: "a@b.c",
|
email: "a@b.c",
|
||||||
firstName: "first",
|
name: "first last",
|
||||||
lastName: "last",
|
|
||||||
isAdmin: false,
|
isAdmin: false,
|
||||||
);
|
);
|
||||||
setUpAll(() async {
|
setUpAll(() async {
|
||||||
|
|
|
@ -6844,15 +6844,12 @@
|
||||||
"nullable": true,
|
"nullable": true,
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
"firstName": {
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"lastName": {
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"memoriesEnabled": {
|
"memoriesEnabled": {
|
||||||
"type": "boolean"
|
"type": "boolean"
|
||||||
},
|
},
|
||||||
|
"name": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
"password": {
|
"password": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
|
@ -6864,8 +6861,7 @@
|
||||||
"required": [
|
"required": [
|
||||||
"email",
|
"email",
|
||||||
"password",
|
"password",
|
||||||
"firstName",
|
"name"
|
||||||
"lastName"
|
|
||||||
],
|
],
|
||||||
"type": "object"
|
"type": "object"
|
||||||
},
|
},
|
||||||
|
@ -7463,13 +7459,10 @@
|
||||||
"accessToken": {
|
"accessToken": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
"firstName": {
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"isAdmin": {
|
"isAdmin": {
|
||||||
"type": "boolean"
|
"type": "boolean"
|
||||||
},
|
},
|
||||||
"lastName": {
|
"name": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
"profileImagePath": {
|
"profileImagePath": {
|
||||||
|
@ -7489,8 +7482,7 @@
|
||||||
"accessToken",
|
"accessToken",
|
||||||
"userId",
|
"userId",
|
||||||
"userEmail",
|
"userEmail",
|
||||||
"firstName",
|
"name",
|
||||||
"lastName",
|
|
||||||
"profileImagePath",
|
"profileImagePath",
|
||||||
"isAdmin",
|
"isAdmin",
|
||||||
"shouldChangePassword"
|
"shouldChangePassword"
|
||||||
|
@ -7656,9 +7648,6 @@
|
||||||
"nullable": true,
|
"nullable": true,
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
"firstName": {
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"id": {
|
"id": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
|
@ -7668,12 +7657,12 @@
|
||||||
"isAdmin": {
|
"isAdmin": {
|
||||||
"type": "boolean"
|
"type": "boolean"
|
||||||
},
|
},
|
||||||
"lastName": {
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"memoriesEnabled": {
|
"memoriesEnabled": {
|
||||||
"type": "boolean"
|
"type": "boolean"
|
||||||
},
|
},
|
||||||
|
"name": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
"oauthId": {
|
"oauthId": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
|
@ -7694,8 +7683,7 @@
|
||||||
},
|
},
|
||||||
"required": [
|
"required": [
|
||||||
"id",
|
"id",
|
||||||
"firstName",
|
"name",
|
||||||
"lastName",
|
|
||||||
"email",
|
"email",
|
||||||
"profileImagePath",
|
"profileImagePath",
|
||||||
"storageLabel",
|
"storageLabel",
|
||||||
|
@ -8464,14 +8452,10 @@
|
||||||
"example": "testuser@email.com",
|
"example": "testuser@email.com",
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
"firstName": {
|
"name": {
|
||||||
"example": "Admin",
|
"example": "Admin",
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
"lastName": {
|
|
||||||
"example": "Doe",
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"password": {
|
"password": {
|
||||||
"example": "password",
|
"example": "password",
|
||||||
"type": "string"
|
"type": "string"
|
||||||
|
@ -8480,8 +8464,7 @@
|
||||||
"required": [
|
"required": [
|
||||||
"email",
|
"email",
|
||||||
"password",
|
"password",
|
||||||
"firstName",
|
"name"
|
||||||
"lastName"
|
|
||||||
],
|
],
|
||||||
"type": "object"
|
"type": "object"
|
||||||
},
|
},
|
||||||
|
@ -9163,9 +9146,6 @@
|
||||||
"externalPath": {
|
"externalPath": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
"firstName": {
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"id": {
|
"id": {
|
||||||
"format": "uuid",
|
"format": "uuid",
|
||||||
"type": "string"
|
"type": "string"
|
||||||
|
@ -9173,12 +9153,12 @@
|
||||||
"isAdmin": {
|
"isAdmin": {
|
||||||
"type": "boolean"
|
"type": "boolean"
|
||||||
},
|
},
|
||||||
"lastName": {
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"memoriesEnabled": {
|
"memoriesEnabled": {
|
||||||
"type": "boolean"
|
"type": "boolean"
|
||||||
},
|
},
|
||||||
|
"name": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
"password": {
|
"password": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
|
@ -9203,13 +9183,10 @@
|
||||||
"format": "int64",
|
"format": "int64",
|
||||||
"type": "integer"
|
"type": "integer"
|
||||||
},
|
},
|
||||||
"userFirstName": {
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"userId": {
|
"userId": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
"userLastName": {
|
"userName": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
"videos": {
|
"videos": {
|
||||||
|
@ -9218,8 +9195,7 @@
|
||||||
},
|
},
|
||||||
"required": [
|
"required": [
|
||||||
"userId",
|
"userId",
|
||||||
"userFirstName",
|
"userName",
|
||||||
"userLastName",
|
|
||||||
"photos",
|
"photos",
|
||||||
"videos",
|
"videos",
|
||||||
"usage"
|
"usage"
|
||||||
|
@ -9231,13 +9207,10 @@
|
||||||
"email": {
|
"email": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
"firstName": {
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"id": {
|
"id": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
"lastName": {
|
"name": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
"profileImagePath": {
|
"profileImagePath": {
|
||||||
|
@ -9246,8 +9219,7 @@
|
||||||
},
|
},
|
||||||
"required": [
|
"required": [
|
||||||
"id",
|
"id",
|
||||||
"firstName",
|
"name",
|
||||||
"lastName",
|
|
||||||
"email",
|
"email",
|
||||||
"profileImagePath"
|
"profileImagePath"
|
||||||
],
|
],
|
||||||
|
@ -9271,21 +9243,18 @@
|
||||||
"nullable": true,
|
"nullable": true,
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
"firstName": {
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"id": {
|
"id": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
"isAdmin": {
|
"isAdmin": {
|
||||||
"type": "boolean"
|
"type": "boolean"
|
||||||
},
|
},
|
||||||
"lastName": {
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"memoriesEnabled": {
|
"memoriesEnabled": {
|
||||||
"type": "boolean"
|
"type": "boolean"
|
||||||
},
|
},
|
||||||
|
"name": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
"oauthId": {
|
"oauthId": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
|
@ -9306,8 +9275,7 @@
|
||||||
},
|
},
|
||||||
"required": [
|
"required": [
|
||||||
"id",
|
"id",
|
||||||
"firstName",
|
"name",
|
||||||
"lastName",
|
|
||||||
"email",
|
"email",
|
||||||
"profileImagePath",
|
"profileImagePath",
|
||||||
"storageLabel",
|
"storageLabel",
|
||||||
|
|
5
server/package-lock.json
generated
5
server/package-lock.json
generated
|
@ -16845,11 +16845,6 @@
|
||||||
"luxon": "^3.2.1"
|
"luxon": "^3.2.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"cron-validator": {
|
|
||||||
"version": "1.3.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/cron-validator/-/cron-validator-1.3.1.tgz",
|
|
||||||
"integrity": "sha512-C1HsxuPCY/5opR55G5/WNzyEGDWFVG+6GLrA+fW/sCTcP6A6NTjUP2AK7B8n2PyFs90kDG2qzwm8LMheADku6A=="
|
|
||||||
},
|
|
||||||
"cross-spawn": {
|
"cross-spawn": {
|
||||||
"version": "7.0.3",
|
"version": "7.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
|
||||||
|
|
|
@ -15,12 +15,12 @@ export class ResetAdminPasswordCommand extends CommandRunner {
|
||||||
|
|
||||||
async run(): Promise<void> {
|
async run(): Promise<void> {
|
||||||
const ask = (admin: UserResponseDto) => {
|
const ask = (admin: UserResponseDto) => {
|
||||||
const { id, oauthId, email, firstName, lastName } = admin;
|
const { id, oauthId, email, name } = admin;
|
||||||
console.log(`Found Admin:
|
console.log(`Found Admin:
|
||||||
- ID=${id}
|
- ID=${id}
|
||||||
- OAuth ID=${oauthId}
|
- OAuth ID=${oauthId}
|
||||||
- Email=${email}
|
- Email=${email}
|
||||||
- Name=${firstName} ${lastName}`);
|
- Name=${name}`);
|
||||||
|
|
||||||
return this.inquirer.ask<{ password: string }>('prompt-password', undefined).then(({ password }) => password);
|
return this.inquirer.ask<{ password: string }>('prompt-password', undefined).then(({ password }) => password);
|
||||||
};
|
};
|
||||||
|
|
|
@ -33,8 +33,7 @@ export class LoginResponseDto {
|
||||||
accessToken!: string;
|
accessToken!: string;
|
||||||
userId!: string;
|
userId!: string;
|
||||||
userEmail!: string;
|
userEmail!: string;
|
||||||
firstName!: string;
|
name!: string;
|
||||||
lastName!: string;
|
|
||||||
profileImagePath!: string;
|
profileImagePath!: string;
|
||||||
isAdmin!: boolean;
|
isAdmin!: boolean;
|
||||||
shouldChangePassword!: boolean;
|
shouldChangePassword!: boolean;
|
||||||
|
@ -45,8 +44,7 @@ export function mapLoginResponse(entity: UserEntity, accessToken: string): Login
|
||||||
accessToken: accessToken,
|
accessToken: accessToken,
|
||||||
userId: entity.id,
|
userId: entity.id,
|
||||||
userEmail: entity.email,
|
userEmail: entity.email,
|
||||||
firstName: entity.firstName,
|
name: entity.name,
|
||||||
lastName: entity.lastName,
|
|
||||||
isAdmin: entity.isAdmin,
|
isAdmin: entity.isAdmin,
|
||||||
profileImagePath: entity.profileImagePath,
|
profileImagePath: entity.profileImagePath,
|
||||||
shouldChangePassword: entity.shouldChangePassword,
|
shouldChangePassword: entity.shouldChangePassword,
|
||||||
|
@ -62,12 +60,7 @@ export class SignUpDto extends LoginCredentialDto {
|
||||||
@IsString()
|
@IsString()
|
||||||
@IsNotEmpty()
|
@IsNotEmpty()
|
||||||
@ApiProperty({ example: 'Admin' })
|
@ApiProperty({ example: 'Admin' })
|
||||||
firstName!: string;
|
name!: string;
|
||||||
|
|
||||||
@IsString()
|
|
||||||
@IsNotEmpty()
|
|
||||||
@ApiProperty({ example: 'Doe' })
|
|
||||||
lastName!: string;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export class ChangePasswordDto {
|
export class ChangePasswordDto {
|
||||||
|
|
|
@ -236,7 +236,7 @@ describe('AuthService', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('adminSignUp', () => {
|
describe('adminSignUp', () => {
|
||||||
const dto: SignUpDto = { email: 'test@immich.com', password: 'password', firstName: 'immich', lastName: 'admin' };
|
const dto: SignUpDto = { email: 'test@immich.com', password: 'password', name: 'immich admin' };
|
||||||
|
|
||||||
it('should only allow one admin', async () => {
|
it('should only allow one admin', async () => {
|
||||||
userMock.getAdmin.mockResolvedValue({} as UserEntity);
|
userMock.getAdmin.mockResolvedValue({} as UserEntity);
|
||||||
|
@ -251,8 +251,7 @@ describe('AuthService', () => {
|
||||||
id: 'admin',
|
id: 'admin',
|
||||||
createdAt: new Date('2021-01-01'),
|
createdAt: new Date('2021-01-01'),
|
||||||
email: 'test@immich.com',
|
email: 'test@immich.com',
|
||||||
firstName: 'immich',
|
name: 'immich admin',
|
||||||
lastName: 'admin',
|
|
||||||
});
|
});
|
||||||
expect(userMock.getAdmin).toHaveBeenCalled();
|
expect(userMock.getAdmin).toHaveBeenCalled();
|
||||||
expect(userMock.create).toHaveBeenCalled();
|
expect(userMock.create).toHaveBeenCalled();
|
||||||
|
|
|
@ -146,8 +146,7 @@ export class AuthService {
|
||||||
const admin = await this.userCore.createUser({
|
const admin = await this.userCore.createUser({
|
||||||
isAdmin: true,
|
isAdmin: true,
|
||||||
email: dto.email,
|
email: dto.email,
|
||||||
firstName: dto.firstName,
|
name: dto.name,
|
||||||
lastName: dto.lastName,
|
|
||||||
password: dto.password,
|
password: dto.password,
|
||||||
storageLabel: 'admin',
|
storageLabel: 'admin',
|
||||||
});
|
});
|
||||||
|
@ -273,9 +272,9 @@ export class AuthService {
|
||||||
storageLabel = null;
|
storageLabel = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const userName = profile.name ?? `${profile.given_name || ''} ${profile.family_name || ''}`;
|
||||||
user = await this.userCore.createUser({
|
user = await this.userCore.createUser({
|
||||||
firstName: profile.given_name || '',
|
name: userName,
|
||||||
lastName: profile.family_name || '',
|
|
||||||
email: profile.email,
|
email: profile.email,
|
||||||
oauthId: profile.sub,
|
oauthId: profile.sub,
|
||||||
storageLabel,
|
storageLabel,
|
||||||
|
|
|
@ -7,10 +7,9 @@ import { PartnerService } from './partner.service';
|
||||||
const responseDto = {
|
const responseDto = {
|
||||||
admin: <PartnerResponseDto>{
|
admin: <PartnerResponseDto>{
|
||||||
email: 'admin@test.com',
|
email: 'admin@test.com',
|
||||||
firstName: 'admin_first_name',
|
name: 'admin_name',
|
||||||
id: 'admin_id',
|
id: 'admin_id',
|
||||||
isAdmin: true,
|
isAdmin: true,
|
||||||
lastName: 'admin_last_name',
|
|
||||||
oauthId: '',
|
oauthId: '',
|
||||||
profileImagePath: '',
|
profileImagePath: '',
|
||||||
shouldChangePassword: false,
|
shouldChangePassword: false,
|
||||||
|
@ -24,10 +23,9 @@ const responseDto = {
|
||||||
},
|
},
|
||||||
user1: <PartnerResponseDto>{
|
user1: <PartnerResponseDto>{
|
||||||
email: 'immich@test.com',
|
email: 'immich@test.com',
|
||||||
firstName: 'immich_first_name',
|
name: 'immich_name',
|
||||||
id: 'user-id',
|
id: 'user-id',
|
||||||
isAdmin: false,
|
isAdmin: false,
|
||||||
lastName: 'immich_last_name',
|
|
||||||
oauthId: '',
|
oauthId: '',
|
||||||
profileImagePath: '',
|
profileImagePath: '',
|
||||||
shouldChangePassword: false,
|
shouldChangePassword: false,
|
||||||
|
|
|
@ -6,8 +6,7 @@ export interface UserListFilter {
|
||||||
|
|
||||||
export interface UserStatsQueryResponse {
|
export interface UserStatsQueryResponse {
|
||||||
userId: string;
|
userId: string;
|
||||||
userFirstName: string;
|
userName: string;
|
||||||
userLastName: string;
|
|
||||||
photos: number;
|
photos: number;
|
||||||
videos: number;
|
videos: number;
|
||||||
usage: number;
|
usage: number;
|
||||||
|
|
|
@ -38,9 +38,7 @@ export class UsageByUserDto {
|
||||||
@ApiProperty({ type: 'string' })
|
@ApiProperty({ type: 'string' })
|
||||||
userId!: string;
|
userId!: string;
|
||||||
@ApiProperty({ type: 'string' })
|
@ApiProperty({ type: 'string' })
|
||||||
userFirstName!: string;
|
userName!: string;
|
||||||
@ApiProperty({ type: 'string' })
|
|
||||||
userLastName!: string;
|
|
||||||
@ApiProperty({ type: 'integer' })
|
@ApiProperty({ type: 'integer' })
|
||||||
photos!: number;
|
photos!: number;
|
||||||
@ApiProperty({ type: 'integer' })
|
@ApiProperty({ type: 'integer' })
|
||||||
|
|
|
@ -195,24 +195,21 @@ describe(ServerInfoService.name, () => {
|
||||||
userMock.getUserStats.mockResolvedValue([
|
userMock.getUserStats.mockResolvedValue([
|
||||||
{
|
{
|
||||||
userId: 'user1',
|
userId: 'user1',
|
||||||
userFirstName: '1',
|
userName: '1 User',
|
||||||
userLastName: 'User',
|
|
||||||
photos: 10,
|
photos: 10,
|
||||||
videos: 11,
|
videos: 11,
|
||||||
usage: 12345,
|
usage: 12345,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
userId: 'user2',
|
userId: 'user2',
|
||||||
userFirstName: '2',
|
userName: '2 User',
|
||||||
userLastName: 'User',
|
|
||||||
photos: 10,
|
photos: 10,
|
||||||
videos: 20,
|
videos: 20,
|
||||||
usage: 123456,
|
usage: 123456,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
userId: 'user3',
|
userId: 'user3',
|
||||||
userFirstName: '3',
|
userName: '3 User',
|
||||||
userLastName: 'User',
|
|
||||||
photos: 100,
|
photos: 100,
|
||||||
videos: 0,
|
videos: 0,
|
||||||
usage: 987654,
|
usage: 987654,
|
||||||
|
@ -227,25 +224,22 @@ describe(ServerInfoService.name, () => {
|
||||||
{
|
{
|
||||||
photos: 10,
|
photos: 10,
|
||||||
usage: 12345,
|
usage: 12345,
|
||||||
userFirstName: '1',
|
userName: '1 User',
|
||||||
userId: 'user1',
|
userId: 'user1',
|
||||||
userLastName: 'User',
|
|
||||||
videos: 11,
|
videos: 11,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
photos: 10,
|
photos: 10,
|
||||||
usage: 123456,
|
usage: 123456,
|
||||||
userFirstName: '2',
|
userName: '2 User',
|
||||||
userId: 'user2',
|
userId: 'user2',
|
||||||
userLastName: 'User',
|
|
||||||
videos: 20,
|
videos: 20,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
photos: 100,
|
photos: 100,
|
||||||
usage: 987654,
|
usage: 987654,
|
||||||
userFirstName: '3',
|
userName: '3 User',
|
||||||
userId: 'user3',
|
userId: 'user3',
|
||||||
userLastName: 'User',
|
|
||||||
videos: 0,
|
videos: 0,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
|
|
@ -98,8 +98,7 @@ export class ServerInfoService {
|
||||||
for (const user of userStats) {
|
for (const user of userStats) {
|
||||||
const usage = new UsageByUserDto();
|
const usage = new UsageByUserDto();
|
||||||
usage.userId = user.userId;
|
usage.userId = user.userId;
|
||||||
usage.userFirstName = user.userFirstName;
|
usage.userName = user.userName;
|
||||||
usage.userLastName = user.userLastName;
|
|
||||||
usage.photos = user.photos;
|
usage.photos = user.photos;
|
||||||
usage.videos = user.videos;
|
usage.videos = user.videos;
|
||||||
usage.usage = user.usage;
|
usage.usage = user.usage;
|
||||||
|
|
|
@ -7,8 +7,7 @@ describe('create user DTO', () => {
|
||||||
const params: Partial<CreateUserDto> = {
|
const params: Partial<CreateUserDto> = {
|
||||||
email: undefined,
|
email: undefined,
|
||||||
password: 'password',
|
password: 'password',
|
||||||
firstName: 'first name',
|
name: 'name',
|
||||||
lastName: 'last name',
|
|
||||||
};
|
};
|
||||||
let dto: CreateUserDto = plainToInstance(CreateUserDto, params);
|
let dto: CreateUserDto = plainToInstance(CreateUserDto, params);
|
||||||
let errors = await validate(dto);
|
let errors = await validate(dto);
|
||||||
|
@ -31,8 +30,7 @@ describe('create user DTO', () => {
|
||||||
const dto = plainToInstance(CreateUserDto, {
|
const dto = plainToInstance(CreateUserDto, {
|
||||||
email: someEmail,
|
email: someEmail,
|
||||||
password: 'some password',
|
password: 'some password',
|
||||||
firstName: 'some first name',
|
name: 'some name',
|
||||||
lastName: 'some last name',
|
|
||||||
});
|
});
|
||||||
const errors = await validate(dto);
|
const errors = await validate(dto);
|
||||||
expect(errors).toHaveLength(0);
|
expect(errors).toHaveLength(0);
|
||||||
|
@ -48,8 +46,7 @@ describe('create admin DTO', () => {
|
||||||
isAdmin: true,
|
isAdmin: true,
|
||||||
email: someEmail,
|
email: someEmail,
|
||||||
password: 'some password',
|
password: 'some password',
|
||||||
firstName: 'some first name',
|
name: 'some name',
|
||||||
lastName: 'some last name',
|
|
||||||
});
|
});
|
||||||
const errors = await validate(dto);
|
const errors = await validate(dto);
|
||||||
expect(errors).toHaveLength(0);
|
expect(errors).toHaveLength(0);
|
||||||
|
@ -64,8 +61,7 @@ describe('create user oauth DTO', () => {
|
||||||
const dto = plainToInstance(CreateUserOAuthDto, {
|
const dto = plainToInstance(CreateUserOAuthDto, {
|
||||||
email: someEmail,
|
email: someEmail,
|
||||||
oauthId: 'some oauth id',
|
oauthId: 'some oauth id',
|
||||||
firstName: 'some first name',
|
name: 'some name',
|
||||||
lastName: 'some last name',
|
|
||||||
});
|
});
|
||||||
const errors = await validate(dto);
|
const errors = await validate(dto);
|
||||||
expect(errors).toHaveLength(0);
|
expect(errors).toHaveLength(0);
|
||||||
|
|
|
@ -13,11 +13,7 @@ export class CreateUserDto {
|
||||||
|
|
||||||
@IsNotEmpty()
|
@IsNotEmpty()
|
||||||
@IsString()
|
@IsString()
|
||||||
firstName!: string;
|
name!: string;
|
||||||
|
|
||||||
@IsNotEmpty()
|
|
||||||
@IsString()
|
|
||||||
lastName!: string;
|
|
||||||
|
|
||||||
@Optional({ nullable: true })
|
@Optional({ nullable: true })
|
||||||
@IsString()
|
@IsString()
|
||||||
|
@ -45,10 +41,7 @@ export class CreateAdminDto {
|
||||||
password!: string;
|
password!: string;
|
||||||
|
|
||||||
@IsNotEmpty()
|
@IsNotEmpty()
|
||||||
firstName!: string;
|
name!: string;
|
||||||
|
|
||||||
@IsNotEmpty()
|
|
||||||
lastName!: string;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export class CreateUserOAuthDto {
|
export class CreateUserOAuthDto {
|
||||||
|
@ -59,7 +52,5 @@ export class CreateUserOAuthDto {
|
||||||
@IsNotEmpty()
|
@IsNotEmpty()
|
||||||
oauthId!: string;
|
oauthId!: string;
|
||||||
|
|
||||||
firstName?: string;
|
name?: string;
|
||||||
|
|
||||||
lastName?: string;
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,12 +17,7 @@ export class UpdateUserDto {
|
||||||
@Optional()
|
@Optional()
|
||||||
@IsString()
|
@IsString()
|
||||||
@IsNotEmpty()
|
@IsNotEmpty()
|
||||||
firstName?: string;
|
name?: string;
|
||||||
|
|
||||||
@Optional()
|
|
||||||
@IsString()
|
|
||||||
@IsNotEmpty()
|
|
||||||
lastName?: string;
|
|
||||||
|
|
||||||
@Optional()
|
@Optional()
|
||||||
@IsString()
|
@IsString()
|
||||||
|
|
|
@ -2,8 +2,7 @@ import { UserEntity } from '@app/infra/entities';
|
||||||
|
|
||||||
export class UserDto {
|
export class UserDto {
|
||||||
id!: string;
|
id!: string;
|
||||||
firstName!: string;
|
name!: string;
|
||||||
lastName!: string;
|
|
||||||
email!: string;
|
email!: string;
|
||||||
profileImagePath!: string;
|
profileImagePath!: string;
|
||||||
}
|
}
|
||||||
|
@ -24,8 +23,7 @@ export const mapSimpleUser = (entity: UserEntity): UserDto => {
|
||||||
return {
|
return {
|
||||||
id: entity.id,
|
id: entity.id,
|
||||||
email: entity.email,
|
email: entity.email,
|
||||||
firstName: entity.firstName,
|
name: entity.name,
|
||||||
lastName: entity.lastName,
|
|
||||||
profileImagePath: entity.profileImagePath,
|
profileImagePath: entity.profileImagePath,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
@ -289,8 +289,7 @@ describe(UserService.name, () => {
|
||||||
await expect(
|
await expect(
|
||||||
sut.create({
|
sut.create({
|
||||||
email: 'john_smith@email.com',
|
email: 'john_smith@email.com',
|
||||||
firstName: 'John',
|
name: 'John Smith',
|
||||||
lastName: 'Smith',
|
|
||||||
password: 'password',
|
password: 'password',
|
||||||
}),
|
}),
|
||||||
).rejects.toBeInstanceOf(BadRequestException);
|
).rejects.toBeInstanceOf(BadRequestException);
|
||||||
|
@ -303,8 +302,7 @@ describe(UserService.name, () => {
|
||||||
await expect(
|
await expect(
|
||||||
sut.create({
|
sut.create({
|
||||||
email: userStub.user1.email,
|
email: userStub.user1.email,
|
||||||
firstName: userStub.user1.firstName,
|
name: userStub.user1.name,
|
||||||
lastName: userStub.user1.lastName,
|
|
||||||
password: 'password',
|
password: 'password',
|
||||||
storageLabel: 'label',
|
storageLabel: 'label',
|
||||||
}),
|
}),
|
||||||
|
@ -313,8 +311,7 @@ describe(UserService.name, () => {
|
||||||
expect(userMock.getAdmin).toBeCalled();
|
expect(userMock.getAdmin).toBeCalled();
|
||||||
expect(userMock.create).toBeCalledWith({
|
expect(userMock.create).toBeCalledWith({
|
||||||
email: userStub.user1.email,
|
email: userStub.user1.email,
|
||||||
firstName: userStub.user1.firstName,
|
name: userStub.user1.name,
|
||||||
lastName: userStub.user1.lastName,
|
|
||||||
storageLabel: 'label',
|
storageLabel: 'label',
|
||||||
password: expect.anything(),
|
password: expect.anything(),
|
||||||
});
|
});
|
||||||
|
|
|
@ -16,10 +16,7 @@ export class UserEntity {
|
||||||
id!: string;
|
id!: string;
|
||||||
|
|
||||||
@Column({ default: '' })
|
@Column({ default: '' })
|
||||||
firstName!: string;
|
name!: string;
|
||||||
|
|
||||||
@Column({ default: '' })
|
|
||||||
lastName!: string;
|
|
||||||
|
|
||||||
@Column({ default: false })
|
@Column({ default: false })
|
||||||
isAdmin!: boolean;
|
isAdmin!: boolean;
|
||||||
|
|
|
@ -0,0 +1,21 @@
|
||||||
|
import { MigrationInterface, QueryRunner } from "typeorm";
|
||||||
|
|
||||||
|
export class AddUsername1699322864544 implements MigrationInterface {
|
||||||
|
name = 'AddUsername1699322864544'
|
||||||
|
|
||||||
|
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
await queryRunner.query(`ALTER TABLE "users" ADD "name" character varying NOT NULL DEFAULT ''`);
|
||||||
|
await queryRunner.query(`UPDATE "users" SET "name" = CONCAT(COALESCE("firstName", ''), ' ', COALESCE("lastName", ''))`);
|
||||||
|
await queryRunner.query(`ALTER TABLE "users" DROP COLUMN "firstName"`);
|
||||||
|
await queryRunner.query(`ALTER TABLE "users" DROP COLUMN "lastName"`);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
await queryRunner.query(`ALTER TABLE "users" DROP COLUMN "name"`);
|
||||||
|
await queryRunner.query(`ALTER TABLE "users" ADD "lastName" character varying NOT NULL DEFAULT ''`);
|
||||||
|
await queryRunner.query(`ALTER TABLE "users" ADD "firstName" character varying NOT NULL DEFAULT ''`);
|
||||||
|
await queryRunner.query(`UPDATE "users" SET "lastName" = COALESCE("email", '')`);
|
||||||
|
await queryRunner.query(`UPDATE "users" SET "firstName" = COALESCE("email", '')`);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -80,8 +80,7 @@ export class UserRepository implements IUserRepository {
|
||||||
const stats = await this.userRepository
|
const stats = await this.userRepository
|
||||||
.createQueryBuilder('users')
|
.createQueryBuilder('users')
|
||||||
.select('users.id', 'userId')
|
.select('users.id', 'userId')
|
||||||
.addSelect('users.firstName', 'userFirstName')
|
.addSelect('users.name', 'userName')
|
||||||
.addSelect('users.lastName', 'userLastName')
|
|
||||||
.addSelect(`COUNT(assets.id) FILTER (WHERE assets.type = 'IMAGE' AND assets.isVisible)`, 'photos')
|
.addSelect(`COUNT(assets.id) FILTER (WHERE assets.type = 'IMAGE' AND assets.isVisible)`, 'photos')
|
||||||
.addSelect(`COUNT(assets.id) FILTER (WHERE assets.type = 'VIDEO' AND assets.isVisible)`, 'videos')
|
.addSelect(`COUNT(assets.id) FILTER (WHERE assets.type = 'VIDEO' AND assets.isVisible)`, 'videos')
|
||||||
.addSelect('COALESCE(SUM(exif.fileSizeInByte), 0)', 'usage')
|
.addSelect('COALESCE(SUM(exif.fileSizeInByte), 0)', 'usage')
|
||||||
|
|
|
@ -350,8 +350,7 @@ describe(`${ActivityController.name} (e2e)`, () => {
|
||||||
const { id: userId } = await api.userApi.create(server, admin.accessToken, {
|
const { id: userId } = await api.userApi.create(server, admin.accessToken, {
|
||||||
email: 'user1@immich.app',
|
email: 'user1@immich.app',
|
||||||
password: 'Password123',
|
password: 'Password123',
|
||||||
firstName: 'User 1',
|
name: 'User 1',
|
||||||
lastName: 'Test',
|
|
||||||
});
|
});
|
||||||
await api.albumApi.addUsers(server, admin.accessToken, album.id, { sharedUserIds: [userId] });
|
await api.albumApi.addUsers(server, admin.accessToken, album.id, { sharedUserIds: [userId] });
|
||||||
const nonOwner = await api.authApi.login(server, { email: 'user1@immich.app', password: 'Password123' });
|
const nonOwner = await api.authApi.login(server, { email: 'user1@immich.app', password: 'Password123' });
|
||||||
|
@ -371,8 +370,7 @@ describe(`${ActivityController.name} (e2e)`, () => {
|
||||||
const { id: userId } = await api.userApi.create(server, admin.accessToken, {
|
const { id: userId } = await api.userApi.create(server, admin.accessToken, {
|
||||||
email: 'user1@immich.app',
|
email: 'user1@immich.app',
|
||||||
password: 'Password123',
|
password: 'Password123',
|
||||||
firstName: 'User 1',
|
name: 'User 1',
|
||||||
lastName: 'Test',
|
|
||||||
});
|
});
|
||||||
await api.albumApi.addUsers(server, admin.accessToken, album.id, { sharedUserIds: [userId] });
|
await api.albumApi.addUsers(server, admin.accessToken, album.id, { sharedUserIds: [userId] });
|
||||||
const nonOwner = await api.authApi.login(server, { email: 'user1@immich.app', password: 'Password123' });
|
const nonOwner = await api.authApi.login(server, { email: 'user1@immich.app', password: 'Password123' });
|
||||||
|
@ -393,8 +391,7 @@ describe(`${ActivityController.name} (e2e)`, () => {
|
||||||
const { id: userId } = await api.userApi.create(server, admin.accessToken, {
|
const { id: userId } = await api.userApi.create(server, admin.accessToken, {
|
||||||
email: 'user1@immich.app',
|
email: 'user1@immich.app',
|
||||||
password: 'Password123',
|
password: 'Password123',
|
||||||
firstName: 'User 1',
|
name: 'User 1',
|
||||||
lastName: 'Test',
|
|
||||||
});
|
});
|
||||||
await api.albumApi.addUsers(server, admin.accessToken, album.id, { sharedUserIds: [userId] });
|
await api.albumApi.addUsers(server, admin.accessToken, album.id, { sharedUserIds: [userId] });
|
||||||
const nonOwner = await api.authApi.login(server, { email: 'user1@immich.app', password: 'Password123' });
|
const nonOwner = await api.authApi.login(server, { email: 'user1@immich.app', password: 'Password123' });
|
||||||
|
|
|
@ -41,14 +41,12 @@ describe(`${AlbumController.name} (e2e)`, () => {
|
||||||
api.userApi.create(server, admin.accessToken, {
|
api.userApi.create(server, admin.accessToken, {
|
||||||
email: 'user1@immich.app',
|
email: 'user1@immich.app',
|
||||||
password: 'Password123',
|
password: 'Password123',
|
||||||
firstName: 'User 1',
|
name: 'User 1',
|
||||||
lastName: 'Test',
|
|
||||||
}),
|
}),
|
||||||
api.userApi.create(server, admin.accessToken, {
|
api.userApi.create(server, admin.accessToken, {
|
||||||
email: 'user2@immich.app',
|
email: 'user2@immich.app',
|
||||||
password: 'Password123',
|
password: 'Password123',
|
||||||
firstName: 'User 2',
|
name: 'User 2',
|
||||||
lastName: 'Test',
|
|
||||||
}),
|
}),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
|
|
@ -22,15 +22,13 @@ import request from 'supertest';
|
||||||
const user1Dto = {
|
const user1Dto = {
|
||||||
email: 'user1@immich.app',
|
email: 'user1@immich.app',
|
||||||
password: 'Password123',
|
password: 'Password123',
|
||||||
firstName: 'User 1',
|
name: 'User 1',
|
||||||
lastName: 'Test',
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const user2Dto = {
|
const user2Dto = {
|
||||||
email: 'user2@immich.app',
|
email: 'user2@immich.app',
|
||||||
password: 'Password123',
|
password: 'Password123',
|
||||||
firstName: 'User 2',
|
name: 'User 2',
|
||||||
lastName: 'Test',
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const makeUploadDto = (options?: { omit: string }): Record<string, any> => {
|
const makeUploadDto = (options?: { omit: string }): Record<string, any> => {
|
||||||
|
|
|
@ -13,15 +13,13 @@ import {
|
||||||
import { testApp } from '@test/test-utils';
|
import { testApp } from '@test/test-utils';
|
||||||
import request from 'supertest';
|
import request from 'supertest';
|
||||||
|
|
||||||
const firstName = 'Immich';
|
const name = 'Immich Admin';
|
||||||
const lastName = 'Admin';
|
|
||||||
const password = 'Password123';
|
const password = 'Password123';
|
||||||
const email = 'admin@immich.app';
|
const email = 'admin@immich.app';
|
||||||
|
|
||||||
const adminSignupResponse = {
|
const adminSignupResponse = {
|
||||||
id: expect.any(String),
|
id: expect.any(String),
|
||||||
firstName: 'Immich',
|
name: 'Immich Admin',
|
||||||
lastName: 'Admin',
|
|
||||||
email: 'admin@immich.app',
|
email: 'admin@immich.app',
|
||||||
storageLabel: 'admin',
|
storageLabel: 'admin',
|
||||||
externalPath: null,
|
externalPath: null,
|
||||||
|
@ -64,23 +62,19 @@ describe(`${AuthController.name} (e2e)`, () => {
|
||||||
const invalid = [
|
const invalid = [
|
||||||
{
|
{
|
||||||
should: 'require an email address',
|
should: 'require an email address',
|
||||||
data: { firstName, lastName, password },
|
data: { name, password },
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
should: 'require a password',
|
should: 'require a password',
|
||||||
data: { firstName, lastName, email },
|
data: { name, email },
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
should: 'require a first name ',
|
should: 'require a name',
|
||||||
data: { lastName, email, password },
|
data: { email, password },
|
||||||
},
|
|
||||||
{
|
|
||||||
should: 'require a last name ',
|
|
||||||
data: { firstName, email, password },
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
should: 'require a valid email',
|
should: 'require a valid email',
|
||||||
data: { firstName, lastName, email: 'immich', password },
|
data: { name, email: 'immich', password },
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
|
@ -15,15 +15,13 @@ describe(`${LibraryController.name} (e2e)`, () => {
|
||||||
const user1Dto = {
|
const user1Dto = {
|
||||||
email: 'user1@immich.app',
|
email: 'user1@immich.app',
|
||||||
password: 'Password123',
|
password: 'Password123',
|
||||||
firstName: 'User 1',
|
name: 'User 1',
|
||||||
lastName: 'Test',
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const user2Dto = {
|
const user2Dto = {
|
||||||
email: 'user2@immich.app',
|
email: 'user2@immich.app',
|
||||||
password: 'Password123',
|
password: 'Password123',
|
||||||
firstName: 'User 2',
|
name: 'User 2',
|
||||||
lastName: 'Test',
|
|
||||||
};
|
};
|
||||||
|
|
||||||
beforeAll(async () => {
|
beforeAll(async () => {
|
||||||
|
|
|
@ -10,15 +10,13 @@ import request from 'supertest';
|
||||||
const user1Dto = {
|
const user1Dto = {
|
||||||
email: 'user1@immich.app',
|
email: 'user1@immich.app',
|
||||||
password: 'Password123',
|
password: 'Password123',
|
||||||
firstName: 'User 1',
|
name: 'User 1',
|
||||||
lastName: 'Test',
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const user2Dto = {
|
const user2Dto = {
|
||||||
email: 'user2@immich.app',
|
email: 'user2@immich.app',
|
||||||
password: 'Password123',
|
password: 'Password123',
|
||||||
firstName: 'User 2',
|
name: 'User 2',
|
||||||
lastName: 'Test',
|
|
||||||
};
|
};
|
||||||
|
|
||||||
describe(`${PartnerController.name} (e2e)`, () => {
|
describe(`${PartnerController.name} (e2e)`, () => {
|
||||||
|
|
|
@ -111,7 +111,7 @@ describe(`${ServerInfoController.name} (e2e)`, () => {
|
||||||
|
|
||||||
it('should only work for admins', async () => {
|
it('should only work for admins', async () => {
|
||||||
const loginDto = { email: 'test@immich.app', password: 'Immich123' };
|
const loginDto = { email: 'test@immich.app', password: 'Immich123' };
|
||||||
await api.userApi.create(server, accessToken, { ...loginDto, firstName: 'test', lastName: 'test' });
|
await api.userApi.create(server, accessToken, { ...loginDto, name: 'test' });
|
||||||
const { accessToken: userAccessToken } = await api.authApi.login(server, loginDto);
|
const { accessToken: userAccessToken } = await api.authApi.login(server, loginDto);
|
||||||
const { status, body } = await request(server)
|
const { status, body } = await request(server)
|
||||||
.get('/server-info/statistics')
|
.get('/server-info/statistics')
|
||||||
|
@ -132,9 +132,8 @@ describe(`${ServerInfoController.name} (e2e)`, () => {
|
||||||
{
|
{
|
||||||
photos: 0,
|
photos: 0,
|
||||||
usage: 0,
|
usage: 0,
|
||||||
userFirstName: 'Immich',
|
userName: 'Immich Admin',
|
||||||
userId: loginResponse.userId,
|
userId: loginResponse.userId,
|
||||||
userLastName: 'Admin',
|
|
||||||
videos: 0,
|
videos: 0,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
|
|
@ -11,8 +11,7 @@ import request from 'supertest';
|
||||||
const user1Dto = {
|
const user1Dto = {
|
||||||
email: 'user1@immich.app',
|
email: 'user1@immich.app',
|
||||||
password: 'Password123',
|
password: 'Password123',
|
||||||
firstName: 'User 1',
|
name: 'User 1',
|
||||||
lastName: 'Test',
|
|
||||||
};
|
};
|
||||||
|
|
||||||
describe(`${PartnerController.name} (e2e)`, () => {
|
describe(`${PartnerController.name} (e2e)`, () => {
|
||||||
|
|
|
@ -64,8 +64,7 @@ describe(`${SystemConfigController.name} (e2e)`, () => {
|
||||||
const credentials = { email: 'user1@immich.app', password: 'Password123' };
|
const credentials = { email: 'user1@immich.app', password: 'Password123' };
|
||||||
await api.userApi.create(server, admin.accessToken, {
|
await api.userApi.create(server, admin.accessToken, {
|
||||||
...credentials,
|
...credentials,
|
||||||
firstName: 'User 1',
|
name: 'User 1',
|
||||||
lastName: 'Test',
|
|
||||||
});
|
});
|
||||||
const { accessToken } = await api.authApi.login(server, credentials);
|
const { accessToken } = await api.authApi.login(server, credentials);
|
||||||
const { status, body } = await request(server)
|
const { status, body } = await request(server)
|
||||||
|
|
|
@ -59,8 +59,7 @@ describe(`${UserController.name}`, () => {
|
||||||
const user1 = await api.userApi.create(server, accessToken, {
|
const user1 = await api.userApi.create(server, accessToken, {
|
||||||
email: `user1@immich.app`,
|
email: `user1@immich.app`,
|
||||||
password: 'Password123',
|
password: 'Password123',
|
||||||
firstName: `User 1`,
|
name: `User 1`,
|
||||||
lastName: 'Test',
|
|
||||||
});
|
});
|
||||||
|
|
||||||
await api.userApi.delete(server, accessToken, user1.id);
|
await api.userApi.delete(server, accessToken, user1.id);
|
||||||
|
@ -78,8 +77,7 @@ describe(`${UserController.name}`, () => {
|
||||||
const user1 = await api.userApi.create(server, accessToken, {
|
const user1 = await api.userApi.create(server, accessToken, {
|
||||||
email: `user1@immich.app`,
|
email: `user1@immich.app`,
|
||||||
password: 'Password123',
|
password: 'Password123',
|
||||||
firstName: `User 1`,
|
name: `User 1`,
|
||||||
lastName: 'Test',
|
|
||||||
});
|
});
|
||||||
|
|
||||||
await api.userApi.delete(server, accessToken, user1.id);
|
await api.userApi.delete(server, accessToken, user1.id);
|
||||||
|
@ -149,8 +147,7 @@ describe(`${UserController.name}`, () => {
|
||||||
isAdmin: true,
|
isAdmin: true,
|
||||||
email: 'user1@immich.app',
|
email: 'user1@immich.app',
|
||||||
password: 'Password123',
|
password: 'Password123',
|
||||||
firstName: 'Immich',
|
name: 'Immich',
|
||||||
lastName: 'User',
|
|
||||||
})
|
})
|
||||||
.set('Authorization', `Bearer ${accessToken}`);
|
.set('Authorization', `Bearer ${accessToken}`);
|
||||||
expect(body).toMatchObject({
|
expect(body).toMatchObject({
|
||||||
|
@ -167,8 +164,7 @@ describe(`${UserController.name}`, () => {
|
||||||
.send({
|
.send({
|
||||||
email: 'no-memories@immich.app',
|
email: 'no-memories@immich.app',
|
||||||
password: 'Password123',
|
password: 'Password123',
|
||||||
firstName: 'No Memories',
|
name: 'No Memories',
|
||||||
lastName: 'User',
|
|
||||||
memoriesEnabled: false,
|
memoriesEnabled: false,
|
||||||
})
|
})
|
||||||
.set('Authorization', `Bearer ${accessToken}`);
|
.set('Authorization', `Bearer ${accessToken}`);
|
||||||
|
@ -186,8 +182,7 @@ describe(`${UserController.name}`, () => {
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
userToDelete = await api.userApi.create(server, accessToken, {
|
userToDelete = await api.userApi.create(server, accessToken, {
|
||||||
email: userStub.user1.email,
|
email: userStub.user1.email,
|
||||||
firstName: userStub.user1.firstName,
|
name: userStub.user1.name,
|
||||||
lastName: userStub.user1.lastName,
|
|
||||||
password: 'superSecurePassword',
|
password: 'superSecurePassword',
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -246,8 +241,7 @@ describe(`${UserController.name}`, () => {
|
||||||
const user = await api.userApi.create(server, accessToken, {
|
const user = await api.userApi.create(server, accessToken, {
|
||||||
email: 'user1@immich.app',
|
email: 'user1@immich.app',
|
||||||
password: 'Password123',
|
password: 'Password123',
|
||||||
firstName: 'Immich',
|
name: 'Immich User',
|
||||||
lastName: 'User',
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const { status, body } = await request(server)
|
const { status, body } = await request(server)
|
||||||
|
@ -284,15 +278,13 @@ describe(`${UserController.name}`, () => {
|
||||||
const before = await api.userApi.get(server, accessToken, loginResponse.userId);
|
const before = await api.userApi.get(server, accessToken, loginResponse.userId);
|
||||||
const after = await api.userApi.update(server, accessToken, {
|
const after = await api.userApi.update(server, accessToken, {
|
||||||
id: before.id,
|
id: before.id,
|
||||||
firstName: 'First Name',
|
name: 'Name',
|
||||||
lastName: 'Last Name',
|
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(after).toEqual({
|
expect(after).toEqual({
|
||||||
...before,
|
...before,
|
||||||
updatedAt: expect.any(String),
|
updatedAt: expect.any(String),
|
||||||
firstName: 'First Name',
|
name: 'Name',
|
||||||
lastName: 'Last Name',
|
|
||||||
});
|
});
|
||||||
expect(before.updatedAt).not.toEqual(after.updatedAt);
|
expect(before.updatedAt).not.toEqual(after.updatedAt);
|
||||||
});
|
});
|
||||||
|
|
15
server/test/fixtures/auth.stub.ts
vendored
15
server/test/fixtures/auth.stub.ts
vendored
|
@ -1,8 +1,7 @@
|
||||||
import { AuthUserDto } from '@app/domain';
|
import { AuthUserDto } from '@app/domain';
|
||||||
|
|
||||||
export const adminSignupStub = {
|
export const adminSignupStub = {
|
||||||
firstName: 'Immich',
|
name: 'Immich Admin',
|
||||||
lastName: 'Admin',
|
|
||||||
email: 'admin@immich.app',
|
email: 'admin@immich.app',
|
||||||
password: 'Password123',
|
password: 'Password123',
|
||||||
};
|
};
|
||||||
|
@ -103,9 +102,8 @@ export const loginResponseStub = {
|
||||||
admin: {
|
admin: {
|
||||||
response: {
|
response: {
|
||||||
accessToken: expect.any(String),
|
accessToken: expect.any(String),
|
||||||
firstName: 'Immich',
|
name: 'Immich Admin',
|
||||||
isAdmin: true,
|
isAdmin: true,
|
||||||
lastName: 'Admin',
|
|
||||||
profileImagePath: '',
|
profileImagePath: '',
|
||||||
shouldChangePassword: true,
|
shouldChangePassword: true,
|
||||||
userEmail: 'admin@immich.app',
|
userEmail: 'admin@immich.app',
|
||||||
|
@ -117,8 +115,7 @@ export const loginResponseStub = {
|
||||||
accessToken: 'cmFuZG9tLWJ5dGVz',
|
accessToken: 'cmFuZG9tLWJ5dGVz',
|
||||||
userId: 'user-id',
|
userId: 'user-id',
|
||||||
userEmail: 'immich@test.com',
|
userEmail: 'immich@test.com',
|
||||||
firstName: 'immich_first_name',
|
name: 'immich_name',
|
||||||
lastName: 'immich_last_name',
|
|
||||||
profileImagePath: '',
|
profileImagePath: '',
|
||||||
isAdmin: false,
|
isAdmin: false,
|
||||||
shouldChangePassword: false,
|
shouldChangePassword: false,
|
||||||
|
@ -133,8 +130,7 @@ export const loginResponseStub = {
|
||||||
accessToken: 'cmFuZG9tLWJ5dGVz',
|
accessToken: 'cmFuZG9tLWJ5dGVz',
|
||||||
userId: 'user-id',
|
userId: 'user-id',
|
||||||
userEmail: 'immich@test.com',
|
userEmail: 'immich@test.com',
|
||||||
firstName: 'immich_first_name',
|
name: 'immich_name',
|
||||||
lastName: 'immich_last_name',
|
|
||||||
profileImagePath: '',
|
profileImagePath: '',
|
||||||
isAdmin: false,
|
isAdmin: false,
|
||||||
shouldChangePassword: false,
|
shouldChangePassword: false,
|
||||||
|
@ -149,8 +145,7 @@ export const loginResponseStub = {
|
||||||
accessToken: 'cmFuZG9tLWJ5dGVz',
|
accessToken: 'cmFuZG9tLWJ5dGVz',
|
||||||
userId: 'user-id',
|
userId: 'user-id',
|
||||||
userEmail: 'immich@test.com',
|
userEmail: 'immich@test.com',
|
||||||
firstName: 'immich_first_name',
|
name: 'immich_name',
|
||||||
lastName: 'immich_last_name',
|
|
||||||
profileImagePath: '',
|
profileImagePath: '',
|
||||||
isAdmin: false,
|
isAdmin: false,
|
||||||
shouldChangePassword: false,
|
shouldChangePassword: false,
|
||||||
|
|
21
server/test/fixtures/user.stub.ts
vendored
21
server/test/fixtures/user.stub.ts
vendored
|
@ -5,8 +5,7 @@ export const userStub = {
|
||||||
admin: Object.freeze<UserEntity>({
|
admin: Object.freeze<UserEntity>({
|
||||||
...authStub.admin,
|
...authStub.admin,
|
||||||
password: 'admin_password',
|
password: 'admin_password',
|
||||||
firstName: 'admin_first_name',
|
name: 'admin_name',
|
||||||
lastName: 'admin_last_name',
|
|
||||||
storageLabel: 'admin',
|
storageLabel: 'admin',
|
||||||
externalPath: null,
|
externalPath: null,
|
||||||
oauthId: '',
|
oauthId: '',
|
||||||
|
@ -22,8 +21,7 @@ export const userStub = {
|
||||||
user1: Object.freeze<UserEntity>({
|
user1: Object.freeze<UserEntity>({
|
||||||
...authStub.user1,
|
...authStub.user1,
|
||||||
password: 'immich_password',
|
password: 'immich_password',
|
||||||
firstName: 'immich_first_name',
|
name: 'immich_name',
|
||||||
lastName: 'immich_last_name',
|
|
||||||
storageLabel: null,
|
storageLabel: null,
|
||||||
externalPath: null,
|
externalPath: null,
|
||||||
oauthId: '',
|
oauthId: '',
|
||||||
|
@ -39,8 +37,7 @@ export const userStub = {
|
||||||
user2: Object.freeze<UserEntity>({
|
user2: Object.freeze<UserEntity>({
|
||||||
...authStub.user2,
|
...authStub.user2,
|
||||||
password: 'immich_password',
|
password: 'immich_password',
|
||||||
firstName: 'immich_first_name',
|
name: 'immich_name',
|
||||||
lastName: 'immich_last_name',
|
|
||||||
storageLabel: null,
|
storageLabel: null,
|
||||||
externalPath: null,
|
externalPath: null,
|
||||||
oauthId: '',
|
oauthId: '',
|
||||||
|
@ -56,8 +53,7 @@ export const userStub = {
|
||||||
storageLabel: Object.freeze<UserEntity>({
|
storageLabel: Object.freeze<UserEntity>({
|
||||||
...authStub.user1,
|
...authStub.user1,
|
||||||
password: 'immich_password',
|
password: 'immich_password',
|
||||||
firstName: 'immich_first_name',
|
name: 'immich_name',
|
||||||
lastName: 'immich_last_name',
|
|
||||||
storageLabel: 'label-1',
|
storageLabel: 'label-1',
|
||||||
externalPath: null,
|
externalPath: null,
|
||||||
oauthId: '',
|
oauthId: '',
|
||||||
|
@ -73,8 +69,7 @@ export const userStub = {
|
||||||
externalPath1: Object.freeze<UserEntity>({
|
externalPath1: Object.freeze<UserEntity>({
|
||||||
...authStub.user1,
|
...authStub.user1,
|
||||||
password: 'immich_password',
|
password: 'immich_password',
|
||||||
firstName: 'immich_first_name',
|
name: 'immich_name',
|
||||||
lastName: 'immich_last_name',
|
|
||||||
storageLabel: 'label-1',
|
storageLabel: 'label-1',
|
||||||
externalPath: '/data/user1',
|
externalPath: '/data/user1',
|
||||||
oauthId: '',
|
oauthId: '',
|
||||||
|
@ -90,8 +85,7 @@ export const userStub = {
|
||||||
externalPath2: Object.freeze<UserEntity>({
|
externalPath2: Object.freeze<UserEntity>({
|
||||||
...authStub.user1,
|
...authStub.user1,
|
||||||
password: 'immich_password',
|
password: 'immich_password',
|
||||||
firstName: 'immich_first_name',
|
name: 'immich_name',
|
||||||
lastName: 'immich_last_name',
|
|
||||||
storageLabel: 'label-1',
|
storageLabel: 'label-1',
|
||||||
externalPath: '/data/user2',
|
externalPath: '/data/user2',
|
||||||
oauthId: '',
|
oauthId: '',
|
||||||
|
@ -107,8 +101,7 @@ export const userStub = {
|
||||||
profilePath: Object.freeze<UserEntity>({
|
profilePath: Object.freeze<UserEntity>({
|
||||||
...authStub.user1,
|
...authStub.user1,
|
||||||
password: 'immich_password',
|
password: 'immich_password',
|
||||||
firstName: 'immich_first_name',
|
name: 'immich_name',
|
||||||
lastName: 'immich_last_name',
|
|
||||||
storageLabel: 'label-1',
|
storageLabel: 'label-1',
|
||||||
externalPath: null,
|
externalPath: null,
|
||||||
oauthId: '',
|
oauthId: '',
|
||||||
|
|
104
web/src/api/open-api/api.ts
generated
104
web/src/api/open-api/api.ts
generated
|
@ -1341,24 +1341,18 @@ export interface CreateUserDto {
|
||||||
* @memberof CreateUserDto
|
* @memberof CreateUserDto
|
||||||
*/
|
*/
|
||||||
'externalPath'?: string | null;
|
'externalPath'?: string | null;
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @type {string}
|
|
||||||
* @memberof CreateUserDto
|
|
||||||
*/
|
|
||||||
'firstName': string;
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @type {string}
|
|
||||||
* @memberof CreateUserDto
|
|
||||||
*/
|
|
||||||
'lastName': string;
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @type {boolean}
|
* @type {boolean}
|
||||||
* @memberof CreateUserDto
|
* @memberof CreateUserDto
|
||||||
*/
|
*/
|
||||||
'memoriesEnabled'?: boolean;
|
'memoriesEnabled'?: boolean;
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @type {string}
|
||||||
|
* @memberof CreateUserDto
|
||||||
|
*/
|
||||||
|
'name': string;
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @type {string}
|
* @type {string}
|
||||||
|
@ -2137,12 +2131,6 @@ export interface LoginResponseDto {
|
||||||
* @memberof LoginResponseDto
|
* @memberof LoginResponseDto
|
||||||
*/
|
*/
|
||||||
'accessToken': string;
|
'accessToken': string;
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @type {string}
|
|
||||||
* @memberof LoginResponseDto
|
|
||||||
*/
|
|
||||||
'firstName': string;
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @type {boolean}
|
* @type {boolean}
|
||||||
|
@ -2154,7 +2142,7 @@ export interface LoginResponseDto {
|
||||||
* @type {string}
|
* @type {string}
|
||||||
* @memberof LoginResponseDto
|
* @memberof LoginResponseDto
|
||||||
*/
|
*/
|
||||||
'lastName': string;
|
'name': string;
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @type {string}
|
* @type {string}
|
||||||
|
@ -2391,12 +2379,6 @@ export interface PartnerResponseDto {
|
||||||
* @memberof PartnerResponseDto
|
* @memberof PartnerResponseDto
|
||||||
*/
|
*/
|
||||||
'externalPath': string | null;
|
'externalPath': string | null;
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @type {string}
|
|
||||||
* @memberof PartnerResponseDto
|
|
||||||
*/
|
|
||||||
'firstName': string;
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @type {string}
|
* @type {string}
|
||||||
|
@ -2415,18 +2397,18 @@ export interface PartnerResponseDto {
|
||||||
* @memberof PartnerResponseDto
|
* @memberof PartnerResponseDto
|
||||||
*/
|
*/
|
||||||
'isAdmin': boolean;
|
'isAdmin': boolean;
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @type {string}
|
|
||||||
* @memberof PartnerResponseDto
|
|
||||||
*/
|
|
||||||
'lastName': string;
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @type {boolean}
|
* @type {boolean}
|
||||||
* @memberof PartnerResponseDto
|
* @memberof PartnerResponseDto
|
||||||
*/
|
*/
|
||||||
'memoriesEnabled'?: boolean;
|
'memoriesEnabled'?: boolean;
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @type {string}
|
||||||
|
* @memberof PartnerResponseDto
|
||||||
|
*/
|
||||||
|
'name': string;
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @type {string}
|
* @type {string}
|
||||||
|
@ -3431,13 +3413,7 @@ export interface SignUpDto {
|
||||||
* @type {string}
|
* @type {string}
|
||||||
* @memberof SignUpDto
|
* @memberof SignUpDto
|
||||||
*/
|
*/
|
||||||
'firstName': string;
|
'name': string;
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @type {string}
|
|
||||||
* @memberof SignUpDto
|
|
||||||
*/
|
|
||||||
'lastName': string;
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @type {string}
|
* @type {string}
|
||||||
|
@ -4380,12 +4356,6 @@ export interface UpdateUserDto {
|
||||||
* @memberof UpdateUserDto
|
* @memberof UpdateUserDto
|
||||||
*/
|
*/
|
||||||
'externalPath'?: string;
|
'externalPath'?: string;
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @type {string}
|
|
||||||
* @memberof UpdateUserDto
|
|
||||||
*/
|
|
||||||
'firstName'?: string;
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @type {string}
|
* @type {string}
|
||||||
|
@ -4398,18 +4368,18 @@ export interface UpdateUserDto {
|
||||||
* @memberof UpdateUserDto
|
* @memberof UpdateUserDto
|
||||||
*/
|
*/
|
||||||
'isAdmin'?: boolean;
|
'isAdmin'?: boolean;
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @type {string}
|
|
||||||
* @memberof UpdateUserDto
|
|
||||||
*/
|
|
||||||
'lastName'?: string;
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @type {boolean}
|
* @type {boolean}
|
||||||
* @memberof UpdateUserDto
|
* @memberof UpdateUserDto
|
||||||
*/
|
*/
|
||||||
'memoriesEnabled'?: boolean;
|
'memoriesEnabled'?: boolean;
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @type {string}
|
||||||
|
* @memberof UpdateUserDto
|
||||||
|
*/
|
||||||
|
'name'?: string;
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @type {string}
|
* @type {string}
|
||||||
|
@ -4447,12 +4417,6 @@ export interface UsageByUserDto {
|
||||||
* @memberof UsageByUserDto
|
* @memberof UsageByUserDto
|
||||||
*/
|
*/
|
||||||
'usage': number;
|
'usage': number;
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @type {string}
|
|
||||||
* @memberof UsageByUserDto
|
|
||||||
*/
|
|
||||||
'userFirstName': string;
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @type {string}
|
* @type {string}
|
||||||
|
@ -4464,7 +4428,7 @@ export interface UsageByUserDto {
|
||||||
* @type {string}
|
* @type {string}
|
||||||
* @memberof UsageByUserDto
|
* @memberof UsageByUserDto
|
||||||
*/
|
*/
|
||||||
'userLastName': string;
|
'userName': string;
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @type {number}
|
* @type {number}
|
||||||
|
@ -4484,12 +4448,6 @@ export interface UserDto {
|
||||||
* @memberof UserDto
|
* @memberof UserDto
|
||||||
*/
|
*/
|
||||||
'email': string;
|
'email': string;
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @type {string}
|
|
||||||
* @memberof UserDto
|
|
||||||
*/
|
|
||||||
'firstName': string;
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @type {string}
|
* @type {string}
|
||||||
|
@ -4501,7 +4459,7 @@ export interface UserDto {
|
||||||
* @type {string}
|
* @type {string}
|
||||||
* @memberof UserDto
|
* @memberof UserDto
|
||||||
*/
|
*/
|
||||||
'lastName': string;
|
'name': string;
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @type {string}
|
* @type {string}
|
||||||
|
@ -4539,12 +4497,6 @@ export interface UserResponseDto {
|
||||||
* @memberof UserResponseDto
|
* @memberof UserResponseDto
|
||||||
*/
|
*/
|
||||||
'externalPath': string | null;
|
'externalPath': string | null;
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @type {string}
|
|
||||||
* @memberof UserResponseDto
|
|
||||||
*/
|
|
||||||
'firstName': string;
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @type {string}
|
* @type {string}
|
||||||
|
@ -4557,18 +4509,18 @@ export interface UserResponseDto {
|
||||||
* @memberof UserResponseDto
|
* @memberof UserResponseDto
|
||||||
*/
|
*/
|
||||||
'isAdmin': boolean;
|
'isAdmin': boolean;
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @type {string}
|
|
||||||
* @memberof UserResponseDto
|
|
||||||
*/
|
|
||||||
'lastName': string;
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @type {boolean}
|
* @type {boolean}
|
||||||
* @memberof UserResponseDto
|
* @memberof UserResponseDto
|
||||||
*/
|
*/
|
||||||
'memoriesEnabled'?: boolean;
|
'memoriesEnabled'?: boolean;
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @type {string}
|
||||||
|
* @memberof UserResponseDto
|
||||||
|
*/
|
||||||
|
'name': string;
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @type {string}
|
* @type {string}
|
||||||
|
|
|
@ -27,7 +27,7 @@
|
||||||
<svelte:fragment slot="prompt">
|
<svelte:fragment slot="prompt">
|
||||||
<div class="flex flex-col gap-4">
|
<div class="flex flex-col gap-4">
|
||||||
<p>
|
<p>
|
||||||
<b>{user.firstName} {user.lastName}</b>'s account and assets will be permanently deleted after 7 days.
|
<b>{user.name}</b>'s account and assets will be permanently deleted after 7 days.
|
||||||
</p>
|
</p>
|
||||||
<p>Are you sure you want to continue?</p>
|
<p>Are you sure you want to continue?</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -16,6 +16,6 @@
|
||||||
|
|
||||||
<ConfirmDialogue title="Restore User" confirmText="Continue" confirmColor="green" on:confirm={restoreUser} on:cancel>
|
<ConfirmDialogue title="Restore User" confirmText="Continue" confirmColor="green" on:confirm={restoreUser} on:cancel>
|
||||||
<svelte:fragment slot="prompt">
|
<svelte:fragment slot="prompt">
|
||||||
<p><b>{user.firstName} {user.lastName}</b>'s account will be restored.</p>
|
<p><b>{user.name}</b>'s account will be restored.</p>
|
||||||
</svelte:fragment>
|
</svelte:fragment>
|
||||||
</ConfirmDialogue>
|
</ConfirmDialogue>
|
||||||
|
|
|
@ -96,7 +96,7 @@
|
||||||
<tr
|
<tr
|
||||||
class="flex h-[50px] w-full place-items-center text-center odd:bg-immich-gray even:bg-immich-bg odd:dark:bg-immich-dark-gray/75 even:dark:bg-immich-dark-gray/50"
|
class="flex h-[50px] w-full place-items-center text-center odd:bg-immich-gray even:bg-immich-bg odd:dark:bg-immich-dark-gray/75 even:dark:bg-immich-dark-gray/50"
|
||||||
>
|
>
|
||||||
<td class="w-1/4 text-ellipsis px-2 text-sm">{user.userFirstName} {user.userLastName}</td>
|
<td class="w-1/4 text-ellipsis px-2 text-sm">{user.userName}</td>
|
||||||
<td class="w-1/4 text-ellipsis px-2 text-sm">{user.photos.toLocaleString($locale)}</td>
|
<td class="w-1/4 text-ellipsis px-2 text-sm">{user.photos.toLocaleString($locale)}</td>
|
||||||
<td class="w-1/4 text-ellipsis px-2 text-sm">{user.videos.toLocaleString($locale)}</td>
|
<td class="w-1/4 text-ellipsis px-2 text-sm">{user.videos.toLocaleString($locale)}</td>
|
||||||
<td class="w-1/4 text-ellipsis px-2 text-sm">{asByteUnitString(user.usage, $locale)}</td>
|
<td class="w-1/4 text-ellipsis px-2 text-sm">{asByteUnitString(user.usage, $locale)}</td>
|
||||||
|
|
|
@ -123,8 +123,7 @@
|
||||||
<p>Owned</p>
|
<p>Owned</p>
|
||||||
{:else}
|
{:else}
|
||||||
<p>
|
<p>
|
||||||
Shared by {albumOwner.firstName}
|
Shared by {albumOwner.name}
|
||||||
{albumOwner.lastName}
|
|
||||||
</p>
|
</p>
|
||||||
{/if}
|
{/if}
|
||||||
{/await}
|
{/await}
|
||||||
|
|
|
@ -56,7 +56,7 @@
|
||||||
<div>
|
<div>
|
||||||
<UserAvatar {user} size="md" />
|
<UserAvatar {user} size="md" />
|
||||||
</div>
|
</div>
|
||||||
<div class="w-full">{`${user.firstName} ${user.lastName}`}</div>
|
<div class="w-full">{user.name}</div>
|
||||||
<div>Owner</div>
|
<div>Owner</div>
|
||||||
</div>
|
</div>
|
||||||
{#each album.sharedUsers as user (user.id)}
|
{#each album.sharedUsers as user (user.id)}
|
||||||
|
@ -64,7 +64,7 @@
|
||||||
<div>
|
<div>
|
||||||
<UserAvatar {user} size="md" />
|
<UserAvatar {user} size="md" />
|
||||||
</div>
|
</div>
|
||||||
<div class="w-full">{`${user.firstName} ${user.lastName}`}</div>
|
<div class="w-full">{user.name}</div>
|
||||||
</div>
|
</div>
|
||||||
{/each}
|
{/each}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -56,7 +56,7 @@
|
||||||
try {
|
try {
|
||||||
await api.albumApi.removeUserFromAlbum({ id: album.id, userId });
|
await api.albumApi.removeUserFromAlbum({ id: album.id, userId });
|
||||||
dispatch('remove', userId);
|
dispatch('remove', userId);
|
||||||
const message = userId === 'me' ? `Left ${album.albumName}` : `Removed ${selectedRemoveUser.firstName}`;
|
const message = userId === 'me' ? `Left ${album.albumName}` : `Removed ${selectedRemoveUser.name}`;
|
||||||
notificationController.show({ type: NotificationType.Info, message });
|
notificationController.show({ type: NotificationType.Info, message });
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
handleError(e, 'Unable to remove user');
|
handleError(e, 'Unable to remove user');
|
||||||
|
@ -78,7 +78,7 @@
|
||||||
<div class="flex w-full place-items-center justify-between gap-4 p-5">
|
<div class="flex w-full place-items-center justify-between gap-4 p-5">
|
||||||
<div class="flex place-items-center gap-4">
|
<div class="flex place-items-center gap-4">
|
||||||
<UserAvatar user={album.owner} size="md" autoColor />
|
<UserAvatar user={album.owner} size="md" autoColor />
|
||||||
<p class="text-sm font-medium">{album.owner.firstName} {album.owner.lastName}</p>
|
<p class="text-sm font-medium">{album.owner.name}</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="icon-{album.owner.id}" class="flex place-items-center">
|
<div id="icon-{album.owner.id}" class="flex place-items-center">
|
||||||
|
@ -91,7 +91,7 @@
|
||||||
>
|
>
|
||||||
<div class="flex place-items-center gap-4">
|
<div class="flex place-items-center gap-4">
|
||||||
<UserAvatar {user} size="md" autoColor />
|
<UserAvatar {user} size="md" autoColor />
|
||||||
<p class="text-sm font-medium">{user.firstName} {user.lastName}</p>
|
<p class="text-sm font-medium">{user.name}</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="icon-{user.id}" class="flex place-items-center">
|
<div id="icon-{user.id}" class="flex place-items-center">
|
||||||
|
@ -138,7 +138,7 @@
|
||||||
{#if selectedRemoveUser && selectedRemoveUser?.id !== currentUser?.id}
|
{#if selectedRemoveUser && selectedRemoveUser?.id !== currentUser?.id}
|
||||||
<ConfirmDialogue
|
<ConfirmDialogue
|
||||||
title="Remove User?"
|
title="Remove User?"
|
||||||
prompt="Are you sure you want to remove {selectedRemoveUser.firstName} {selectedRemoveUser.lastName}"
|
prompt="Are you sure you want to remove {selectedRemoveUser.name}"
|
||||||
confirmText="Remove"
|
confirmText="Remove"
|
||||||
on:confirm={handleRemoveUser}
|
on:confirm={handleRemoveUser}
|
||||||
on:cancel={() => (selectedRemoveUser = null)}
|
on:cancel={() => (selectedRemoveUser = null)}
|
||||||
|
|
|
@ -72,7 +72,7 @@
|
||||||
class="flex place-items-center gap-1 rounded-full border border-gray-400 p-1 transition-colors hover:bg-gray-200 dark:hover:bg-gray-700"
|
class="flex place-items-center gap-1 rounded-full border border-gray-400 p-1 transition-colors hover:bg-gray-200 dark:hover:bg-gray-700"
|
||||||
>
|
>
|
||||||
<UserAvatar {user} size="sm" autoColor />
|
<UserAvatar {user} size="sm" autoColor />
|
||||||
<p class="text-xs font-medium">{user.firstName} {user.lastName}</p>
|
<p class="text-xs font-medium">{user.name}</p>
|
||||||
</button>
|
</button>
|
||||||
{/key}
|
{/key}
|
||||||
{/each}
|
{/each}
|
||||||
|
@ -99,8 +99,7 @@
|
||||||
|
|
||||||
<div class="text-left">
|
<div class="text-left">
|
||||||
<p class="text-immich-fg dark:text-immich-dark-fg">
|
<p class="text-immich-fg dark:text-immich-dark-fg">
|
||||||
{user.firstName}
|
{user.name}
|
||||||
{user.lastName}
|
|
||||||
</p>
|
</p>
|
||||||
<p class="text-xs">
|
<p class="text-xs">
|
||||||
{user.email}
|
{user.email}
|
||||||
|
|
|
@ -221,13 +221,8 @@
|
||||||
<div class="flex p-3 mx-2 mt-3 rounded-full gap-4 items-center text-sm">
|
<div class="flex p-3 mx-2 mt-3 rounded-full gap-4 items-center text-sm">
|
||||||
<div class="text-red-600"><Icon path={mdiHeart} size={20} /></div>
|
<div class="text-red-600"><Icon path={mdiHeart} size={20} /></div>
|
||||||
|
|
||||||
<div
|
<div class="w-full" title={`${reaction.user.name} (${reaction.user.email})`}>
|
||||||
class="w-full"
|
{`${reaction.user.name} liked ${assetType ? `this ${getAssetType(assetType).toLowerCase()}` : 'it'}`}
|
||||||
title={`${reaction.user.firstName} ${reaction.user.lastName} (${reaction.user.email})`}
|
|
||||||
>
|
|
||||||
{`${reaction.user.firstName} ${reaction.user.lastName} liked ${
|
|
||||||
assetType ? `this ${getAssetType(assetType).toLowerCase()}` : 'it'
|
|
||||||
}`}
|
|
||||||
</div>
|
</div>
|
||||||
{#if assetId === undefined && reaction.assetId}
|
{#if assetId === undefined && reaction.assetId}
|
||||||
<div class="aspect-square w-[75px] h-[75px]">
|
<div class="aspect-square w-[75px] h-[75px]">
|
||||||
|
|
|
@ -315,8 +315,7 @@
|
||||||
|
|
||||||
<div class="mb-auto mt-auto">
|
<div class="mb-auto mt-auto">
|
||||||
<p>
|
<p>
|
||||||
{asset.owner.firstName}
|
{asset.owner.name}
|
||||||
{asset.owner.lastName}
|
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -27,15 +27,13 @@
|
||||||
|
|
||||||
const email = form.get('email');
|
const email = form.get('email');
|
||||||
const password = form.get('password');
|
const password = form.get('password');
|
||||||
const firstName = form.get('firstName');
|
const name = form.get('name');
|
||||||
const lastName = form.get('lastName');
|
|
||||||
|
|
||||||
const { status } = await api.authenticationApi.signUpAdmin({
|
const { status } = await api.authenticationApi.signUpAdmin({
|
||||||
signUpDto: {
|
signUpDto: {
|
||||||
email: String(email),
|
email: String(email),
|
||||||
password: String(password),
|
password: String(password),
|
||||||
firstName: String(firstName),
|
name: String(name),
|
||||||
lastName: String(lastName),
|
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -83,13 +81,8 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="flex flex-col gap-2">
|
<div class="flex flex-col gap-2">
|
||||||
<label class="immich-form-label" for="firstName">First Name</label>
|
<label class="immich-form-label" for="name">Name</label>
|
||||||
<input class="immich-form-input" id="firstName" name="firstName" type="text" autocomplete="given-name" required />
|
<input class="immich-form-input" id="name" name="name" type="text" autocomplete="name" required />
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="flex flex-col gap-2">
|
|
||||||
<label class="immich-form-label" for="lastName">Last Name</label>
|
|
||||||
<input class="immich-form-input" id="lastName" name="lastName" type="text" autocomplete="family-name" required />
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{#if error}
|
{#if error}
|
||||||
|
|
|
@ -38,16 +38,14 @@
|
||||||
|
|
||||||
const email = form.get('email');
|
const email = form.get('email');
|
||||||
const password = form.get('password');
|
const password = form.get('password');
|
||||||
const firstName = form.get('firstName');
|
const name = form.get('name');
|
||||||
const lastName = form.get('lastName');
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const { status } = await api.userApi.createUser({
|
const { status } = await api.userApi.createUser({
|
||||||
createUserDto: {
|
createUserDto: {
|
||||||
email: String(email),
|
email: String(email),
|
||||||
password: String(password),
|
password: String(password),
|
||||||
firstName: String(firstName),
|
name: String(name),
|
||||||
lastName: String(lastName),
|
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -112,13 +110,8 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="m-4 flex flex-col gap-2">
|
<div class="m-4 flex flex-col gap-2">
|
||||||
<label class="immich-form-label" for="firstName">First Name</label>
|
<label class="immich-form-label" for="name">Name</label>
|
||||||
<input class="immich-form-input" id="firstName" name="firstName" type="text" required />
|
<input class="immich-form-input" id="name" name="name" type="text" required />
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="m-4 flex flex-col gap-2">
|
|
||||||
<label class="immich-form-label" for="lastName">Last Name</label>
|
|
||||||
<input class="immich-form-input" id="lastName" name="lastName" type="text" required />
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{#if error}
|
{#if error}
|
||||||
|
|
|
@ -20,13 +20,12 @@
|
||||||
|
|
||||||
const editUser = async () => {
|
const editUser = async () => {
|
||||||
try {
|
try {
|
||||||
const { id, email, firstName, lastName, storageLabel, externalPath } = user;
|
const { id, email, name, storageLabel, externalPath } = user;
|
||||||
const { status } = await api.userApi.updateUser({
|
const { status } = await api.userApi.updateUser({
|
||||||
updateUserDto: {
|
updateUserDto: {
|
||||||
id,
|
id,
|
||||||
email,
|
email,
|
||||||
firstName,
|
name,
|
||||||
lastName,
|
|
||||||
storageLabel: storageLabel || '',
|
storageLabel: storageLabel || '',
|
||||||
externalPath: externalPath || '',
|
externalPath: externalPath || '',
|
||||||
},
|
},
|
||||||
|
@ -84,20 +83,8 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="m-4 flex flex-col gap-2">
|
<div class="m-4 flex flex-col gap-2">
|
||||||
<label class="immich-form-label" for="firstName">First Name</label>
|
<label class="immich-form-label" for="name">Name</label>
|
||||||
<input
|
<input class="immich-form-input" id="name" name="name" type="text" required bind:value={user.name} />
|
||||||
class="immich-form-input"
|
|
||||||
id="firstName"
|
|
||||||
name="firstName"
|
|
||||||
type="text"
|
|
||||||
required
|
|
||||||
bind:value={user.firstName}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="m-4 flex flex-col gap-2">
|
|
||||||
<label class="immich-form-label" for="lastName">Last Name</label>
|
|
||||||
<input class="immich-form-input" id="lastName" name="lastName" type="text" required bind:value={user.lastName} />
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="m-4 flex flex-col gap-2">
|
<div class="m-4 flex flex-col gap-2">
|
||||||
|
@ -161,7 +148,7 @@
|
||||||
>
|
>
|
||||||
<svelte:fragment slot="prompt">
|
<svelte:fragment slot="prompt">
|
||||||
<p>
|
<p>
|
||||||
Are you sure you want to reset <b>{user.firstName} {user.lastName}</b>'s password?
|
Are you sure you want to reset <b>{user.name}</b>'s password?
|
||||||
</p>
|
</p>
|
||||||
</svelte:fragment>
|
</svelte:fragment>
|
||||||
</ConfirmDialogue>
|
</ConfirmDialogue>
|
||||||
|
|
|
@ -26,8 +26,7 @@
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<p class="text-center text-lg font-medium text-immich-primary dark:text-immich-dark-primary">
|
<p class="text-center text-lg font-medium text-immich-primary dark:text-immich-dark-primary">
|
||||||
{user.firstName}
|
{user.name}
|
||||||
{user.lastName}
|
|
||||||
</p>
|
</p>
|
||||||
<p class="text-sm text-gray-500 dark:text-immich-dark-fg">{user.email}</p>
|
<p class="text-sm text-gray-500 dark:text-immich-dark-fg">{user.email}</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -133,7 +133,7 @@
|
||||||
out:fade={{ delay: 200, duration: 150 }}
|
out:fade={{ delay: 200, duration: 150 }}
|
||||||
class="absolute -bottom-12 right-5 rounded-md border bg-gray-500 p-2 text-[12px] text-gray-100 shadow-md dark:border-immich-dark-gray dark:bg-immich-dark-gray"
|
class="absolute -bottom-12 right-5 rounded-md border bg-gray-500 p-2 text-[12px] text-gray-100 shadow-md dark:border-immich-dark-gray dark:bg-immich-dark-gray"
|
||||||
>
|
>
|
||||||
<p>{user.firstName} {user.lastName}</p>
|
<p>{user.name}</p>
|
||||||
<p>{user.email}</p>
|
<p>{user.email}</p>
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
|
@ -9,8 +9,7 @@
|
||||||
|
|
||||||
interface User {
|
interface User {
|
||||||
id: string;
|
id: string;
|
||||||
firstName: string;
|
name: string;
|
||||||
lastName: string;
|
|
||||||
email: string;
|
email: string;
|
||||||
profileImagePath: string;
|
profileImagePath: string;
|
||||||
}
|
}
|
||||||
|
@ -51,7 +50,7 @@
|
||||||
|
|
||||||
$: colorClass = colorClasses[autoColor ? getUserColor() : color];
|
$: colorClass = colorClasses[autoColor ? getUserColor() : color];
|
||||||
$: sizeClass = sizeClasses[size];
|
$: sizeClass = sizeClasses[size];
|
||||||
$: title = `${user.firstName} ${user.lastName} (${user.email})`;
|
$: title = `${user.name} (${user.email})`;
|
||||||
$: interactiveClass = interactive
|
$: interactiveClass = interactive
|
||||||
? 'border-2 border-immich-primary hover:border-immich-dark-primary dark:hover:border-immich-primary dark:border-immich-dark-primary transition-colors'
|
? 'border-2 border-immich-primary hover:border-immich-dark-primary dark:hover:border-immich-primary dark:border-immich-dark-primary transition-colors'
|
||||||
: '';
|
: '';
|
||||||
|
@ -82,7 +81,7 @@
|
||||||
class:font-medium={!autoColor}
|
class:font-medium={!autoColor}
|
||||||
class:font-semibold={autoColor}
|
class:font-semibold={autoColor}
|
||||||
>
|
>
|
||||||
{((user.firstName[0] || '') + (user.lastName[0] || '')).toUpperCase()}
|
{(user.name[0] || '').toUpperCase()}
|
||||||
</span>
|
</span>
|
||||||
{/if}
|
{/if}
|
||||||
</figure>
|
</figure>
|
||||||
|
|
|
@ -61,8 +61,7 @@
|
||||||
|
|
||||||
<div class="text-left">
|
<div class="text-left">
|
||||||
<p class="text-immich-fg dark:text-immich-dark-fg">
|
<p class="text-immich-fg dark:text-immich-dark-fg">
|
||||||
{user.firstName}
|
{user.name}
|
||||||
{user.lastName}
|
|
||||||
</p>
|
</p>
|
||||||
<p class="text-xs">
|
<p class="text-xs">
|
||||||
{user.email}
|
{user.email}
|
||||||
|
|
|
@ -116,8 +116,7 @@
|
||||||
<UserAvatar user={partner.user} size="md" autoColor />
|
<UserAvatar user={partner.user} size="md" autoColor />
|
||||||
<div class="text-left">
|
<div class="text-left">
|
||||||
<p class="text-immich-fg dark:text-immich-dark-fg">
|
<p class="text-immich-fg dark:text-immich-dark-fg">
|
||||||
{partner.user.firstName}
|
{partner.user.name}
|
||||||
{partner.user.lastName}
|
|
||||||
</p>
|
</p>
|
||||||
<p class="text-xs text-immich-fg/75 dark:text-immich-dark-fg/75">
|
<p class="text-xs text-immich-fg/75 dark:text-immich-dark-fg/75">
|
||||||
{partner.user.email}
|
{partner.user.email}
|
||||||
|
@ -139,8 +138,8 @@
|
||||||
<!-- I am sharing my assets with this user -->
|
<!-- I am sharing my assets with this user -->
|
||||||
{#if partner.sharedByMe}
|
{#if partner.sharedByMe}
|
||||||
<hr class="my-4 border border-gray-200 dark:border-gray-700" />
|
<hr class="my-4 border border-gray-200 dark:border-gray-700" />
|
||||||
<p class="text-xs font-medium my-4">SHARED WITH {partner.user.firstName.toUpperCase()}</p>
|
<p class="text-xs font-medium my-4">SHARED WITH {partner.user.name.toUpperCase()}</p>
|
||||||
<p class="text-md">{partner.user.firstName} can access</p>
|
<p class="text-md">{partner.user.name} can access</p>
|
||||||
<ul class="text-sm">
|
<ul class="text-sm">
|
||||||
<li class="flex gap-2 place-items-center py-1 mt-2">
|
<li class="flex gap-2 place-items-center py-1 mt-2">
|
||||||
<Icon path={mdiCheck} /> All your photos and videos except those in Archived and Deleted
|
<Icon path={mdiCheck} /> All your photos and videos except those in Archived and Deleted
|
||||||
|
@ -154,7 +153,7 @@
|
||||||
<!-- this user is sharing assets with me -->
|
<!-- this user is sharing assets with me -->
|
||||||
{#if partner.sharedWithMe}
|
{#if partner.sharedWithMe}
|
||||||
<hr class="my-4 border border-gray-200 dark:border-gray-700" />
|
<hr class="my-4 border border-gray-200 dark:border-gray-700" />
|
||||||
<p class="text-xs font-medium my-4">PHOTOS FROM {partner.user.firstName.toUpperCase()}</p>
|
<p class="text-xs font-medium my-4">PHOTOS FROM {partner.user.name.toUpperCase()}</p>
|
||||||
<SettingSwitch
|
<SettingSwitch
|
||||||
title="Show in timeline"
|
title="Show in timeline"
|
||||||
subtitle="Show photos and videos from this user in your timeline"
|
subtitle="Show photos and videos from this user in your timeline"
|
||||||
|
@ -183,7 +182,7 @@
|
||||||
{#if removePartner}
|
{#if removePartner}
|
||||||
<ConfirmDialogue
|
<ConfirmDialogue
|
||||||
title="Stop sharing your photos?"
|
title="Stop sharing your photos?"
|
||||||
prompt="{removePartner.firstName} will no longer be able to access your photos."
|
prompt="{removePartner.name} will no longer be able to access your photos."
|
||||||
on:cancel={() => (removePartner = null)}
|
on:cancel={() => (removePartner = null)}
|
||||||
on:confirm={() => handleRemovePartner()}
|
on:confirm={() => handleRemovePartner()}
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -17,8 +17,7 @@
|
||||||
updateUserDto: {
|
updateUserDto: {
|
||||||
id: user.id,
|
id: user.id,
|
||||||
email: user.email,
|
email: user.email,
|
||||||
firstName: user.firstName,
|
name: user.name,
|
||||||
lastName: user.lastName,
|
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -47,19 +46,7 @@
|
||||||
|
|
||||||
<SettingInputField inputType={SettingInputFieldType.EMAIL} label="EMAIL" bind:value={user.email} />
|
<SettingInputField inputType={SettingInputFieldType.EMAIL} label="EMAIL" bind:value={user.email} />
|
||||||
|
|
||||||
<SettingInputField
|
<SettingInputField inputType={SettingInputFieldType.TEXT} label="NAME" bind:value={user.name} required={true} />
|
||||||
inputType={SettingInputFieldType.TEXT}
|
|
||||||
label="FIRST NAME"
|
|
||||||
bind:value={user.firstName}
|
|
||||||
required={true}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<SettingInputField
|
|
||||||
inputType={SettingInputFieldType.TEXT}
|
|
||||||
label="LAST NAME"
|
|
||||||
bind:value={user.lastName}
|
|
||||||
required={true}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<SettingInputField
|
<SettingInputField
|
||||||
inputType={SettingInputFieldType.TEXT}
|
inputType={SettingInputFieldType.TEXT}
|
||||||
|
|
|
@ -39,8 +39,7 @@
|
||||||
<ControlAppBar showBackButton backIcon={mdiArrowLeft} on:close-button-click={() => goto(AppRoute.SHARING)}>
|
<ControlAppBar showBackButton backIcon={mdiArrowLeft} on:close-button-click={() => goto(AppRoute.SHARING)}>
|
||||||
<svelte:fragment slot="leading">
|
<svelte:fragment slot="leading">
|
||||||
<p class="whitespace-nowrap text-immich-fg dark:text-immich-dark-fg">
|
<p class="whitespace-nowrap text-immich-fg dark:text-immich-dark-fg">
|
||||||
{data.partner.firstName}
|
{data.partner.name}'s photos
|
||||||
{data.partner.lastName}'s photos
|
|
||||||
</p>
|
</p>
|
||||||
</svelte:fragment>
|
</svelte:fragment>
|
||||||
</ControlAppBar>
|
</ControlAppBar>
|
||||||
|
|
|
@ -72,8 +72,7 @@
|
||||||
<UserAvatar user={partner} size="lg" autoColor />
|
<UserAvatar user={partner} size="lg" autoColor />
|
||||||
<div class="text-left">
|
<div class="text-left">
|
||||||
<p class="text-immich-fg dark:text-immich-dark-fg">
|
<p class="text-immich-fg dark:text-immich-dark-fg">
|
||||||
{partner.firstName}
|
{partner.name}
|
||||||
{partner.lastName}
|
|
||||||
</p>
|
</p>
|
||||||
<p class="text-xs text-immich-fg/75 dark:text-immich-dark-fg/75">
|
<p class="text-xs text-immich-fg/75 dark:text-immich-dark-fg/75">
|
||||||
{partner.email}
|
{partner.email}
|
||||||
|
|
|
@ -168,8 +168,7 @@
|
||||||
>
|
>
|
||||||
<tr class="flex w-full place-items-center">
|
<tr class="flex w-full place-items-center">
|
||||||
<th class="w-4/12 text-center text-sm font-medium">Email</th>
|
<th class="w-4/12 text-center text-sm font-medium">Email</th>
|
||||||
<th class="w-2/12 text-center text-sm font-medium">First name</th>
|
<th class="w-2/12 text-center text-sm font-medium">Name</th>
|
||||||
<th class="w-2/12 text-center text-sm font-medium">Last name</th>
|
|
||||||
<th class="w-2/12 text-center text-sm font-medium">Can import</th>
|
<th class="w-2/12 text-center text-sm font-medium">Can import</th>
|
||||||
<th class="w-2/12 text-center text-sm font-medium">Action</th>
|
<th class="w-2/12 text-center text-sm font-medium">Action</th>
|
||||||
</tr>
|
</tr>
|
||||||
|
@ -187,8 +186,7 @@
|
||||||
}`}
|
}`}
|
||||||
>
|
>
|
||||||
<td class="w-4/12 text-ellipsis break-all px-2 text-sm">{user.email}</td>
|
<td class="w-4/12 text-ellipsis break-all px-2 text-sm">{user.email}</td>
|
||||||
<td class="w-2/12 text-ellipsis break-all px-2 text-sm">{user.firstName}</td>
|
<td class="w-2/12 text-ellipsis break-all px-2 text-sm">{user.name}</td>
|
||||||
<td class="w-2/12 text-ellipsis break-all px-2 text-sm">{user.lastName}</td>
|
|
||||||
<td class="w-2/12 text-ellipsis break-all px-2 text-sm">
|
<td class="w-2/12 text-ellipsis break-all px-2 text-sm">
|
||||||
<div class="container mx-auto flex flex-wrap justify-center">
|
<div class="container mx-auto flex flex-wrap justify-center">
|
||||||
{#if user.externalPath}
|
{#if user.externalPath}
|
||||||
|
@ -253,7 +251,7 @@
|
||||||
: 'bg-immich-bg dark:bg-immich-dark-gray/50'
|
: 'bg-immich-bg dark:bg-immich-dark-gray/50'
|
||||||
}`}
|
}`}
|
||||||
>
|
>
|
||||||
<td class="w-1/4 text-ellipsis break-words px-2 text-sm">{user.firstName} {user.lastName}</td>
|
<td class="w-1/4 text-ellipsis break-words px-2 text-sm">{user.name}</td>
|
||||||
<td class="w-1/2 text-ellipsis break-all px-2 text-sm">{user.email}</td>
|
<td class="w-1/2 text-ellipsis break-all px-2 text-sm">{user.email}</td>
|
||||||
<td class="w-1/4 text-ellipsis px-2 text-sm">
|
<td class="w-1/4 text-ellipsis px-2 text-sm">
|
||||||
{#if !isDeleted(user)}
|
{#if !isDeleted(user)}
|
||||||
|
|
|
@ -16,8 +16,7 @@
|
||||||
|
|
||||||
<FullscreenContainer title={data.meta.title}>
|
<FullscreenContainer title={data.meta.title}>
|
||||||
<p slot="message">
|
<p slot="message">
|
||||||
Hi {data.user.firstName}
|
Hi {data.user.name} ({data.user.email}),
|
||||||
{data.user.lastName} ({data.user.email}),
|
|
||||||
<br />
|
<br />
|
||||||
<br />
|
<br />
|
||||||
This is either the first time you are signing into the system or a request has been made to change your password. Please
|
This is either the first time you are signing into the system or a request has been made to change your password. Please
|
||||||
|
|
|
@ -5,8 +5,7 @@ import { Sync } from 'factory.ts';
|
||||||
export const userFactory = Sync.makeFactory<UserResponseDto>({
|
export const userFactory = Sync.makeFactory<UserResponseDto>({
|
||||||
id: Sync.each(() => faker.datatype.uuid()),
|
id: Sync.each(() => faker.datatype.uuid()),
|
||||||
email: Sync.each(() => faker.internet.email()),
|
email: Sync.each(() => faker.internet.email()),
|
||||||
firstName: Sync.each(() => faker.name.firstName()),
|
name: Sync.each(() => faker.name.fullName()),
|
||||||
lastName: Sync.each(() => faker.name.lastName()),
|
|
||||||
storageLabel: Sync.each(() => faker.random.alphaNumeric()),
|
storageLabel: Sync.each(() => faker.random.alphaNumeric()),
|
||||||
externalPath: Sync.each(() => faker.random.alphaNumeric()),
|
externalPath: Sync.each(() => faker.random.alphaNumeric()),
|
||||||
profileImagePath: '',
|
profileImagePath: '',
|
||||||
|
|
Loading…
Reference in a new issue