Skip to content

Commit 5f00d8b

Browse files
authored
Added mechanism of required password change of new user's first login (#272)
* Deprecate login scenarios that support pre-web era * refactor and simplify setup * Added user info to change password form * change isFistLogin column to shouldChangePassword * Implemented change user password * Implement the change password page for mobile * Change label * Added changes log and up minor version * Fixed typo in the release note * Up server version
1 parent 2e85e18 commit 5f00d8b

33 files changed

+742
-566
lines changed
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
* Fixed app does not resume back up when reopening a closed app
2+
* Fixed wrong asset count on the upload page
3+
* Added mechanism to change the password of new user on the first login (except Admin)

mobile/ios/fastlane/Fastfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ platform :ios do
1919
desc "iOS Beta"
2020
lane :beta do
2121
increment_version_number(
22-
version_number: "1.13.0"
22+
version_number: "1.14.0"
2323
)
2424
increment_build_number(
2525
build_number: latest_testflight_build_number + 1,

mobile/lib/modules/home/ui/profile_drawer.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -191,7 +191,7 @@ class ProfileDrawer extends HookConsumerWidget {
191191
),
192192
onTap: () async {
193193
bool res =
194-
await ref.read(authenticationProvider.notifier).logout();
194+
await ref.watch(authenticationProvider.notifier).logout();
195195

196196
if (res) {
197197
ref.watch(backupProvider.notifier).cancelBackup();

mobile/lib/modules/login/models/authentication_state.model.dart

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ class AuthenticationState {
1111
final String firstName;
1212
final String lastName;
1313
final bool isAdmin;
14-
final bool isFirstLogin;
14+
final bool shouldChangePassword;
1515
final String profileImagePath;
1616
final DeviceInfoRemote deviceInfo;
1717

@@ -24,7 +24,7 @@ class AuthenticationState {
2424
required this.firstName,
2525
required this.lastName,
2626
required this.isAdmin,
27-
required this.isFirstLogin,
27+
required this.shouldChangePassword,
2828
required this.profileImagePath,
2929
required this.deviceInfo,
3030
});
@@ -38,7 +38,7 @@ class AuthenticationState {
3838
String? firstName,
3939
String? lastName,
4040
bool? isAdmin,
41-
bool? isFirstLoggedIn,
41+
bool? shouldChangePassword,
4242
String? profileImagePath,
4343
DeviceInfoRemote? deviceInfo,
4444
}) {
@@ -51,17 +51,12 @@ class AuthenticationState {
5151
firstName: firstName ?? this.firstName,
5252
lastName: lastName ?? this.lastName,
5353
isAdmin: isAdmin ?? this.isAdmin,
54-
isFirstLogin: isFirstLoggedIn ?? isFirstLogin,
54+
shouldChangePassword: shouldChangePassword ?? this.shouldChangePassword,
5555
profileImagePath: profileImagePath ?? this.profileImagePath,
5656
deviceInfo: deviceInfo ?? this.deviceInfo,
5757
);
5858
}
5959

60-
@override
61-
String toString() {
62-
return 'AuthenticationState(deviceId: $deviceId, deviceType: $deviceType, userId: $userId, userEmail: $userEmail, isAuthenticated: $isAuthenticated, firstName: $firstName, lastName: $lastName, isAdmin: $isAdmin, isFirstLoggedIn: $isFirstLogin, profileImagePath: $profileImagePath, deviceInfo: $deviceInfo)';
63-
}
64-
6560
Map<String, dynamic> toMap() {
6661
final result = <String, dynamic>{};
6762

@@ -73,7 +68,7 @@ class AuthenticationState {
7368
result.addAll({'firstName': firstName});
7469
result.addAll({'lastName': lastName});
7570
result.addAll({'isAdmin': isAdmin});
76-
result.addAll({'isFirstLogin': isFirstLogin});
71+
result.addAll({'shouldChangePassword': shouldChangePassword});
7772
result.addAll({'profileImagePath': profileImagePath});
7873
result.addAll({'deviceInfo': deviceInfo.toMap()});
7974

@@ -90,7 +85,7 @@ class AuthenticationState {
9085
firstName: map['firstName'] ?? '',
9186
lastName: map['lastName'] ?? '',
9287
isAdmin: map['isAdmin'] ?? false,
93-
isFirstLogin: map['isFirstLogin'] ?? false,
88+
shouldChangePassword: map['shouldChangePassword'] ?? false,
9489
profileImagePath: map['profileImagePath'] ?? '',
9590
deviceInfo: DeviceInfoRemote.fromMap(map['deviceInfo']),
9691
);
@@ -101,6 +96,11 @@ class AuthenticationState {
10196
factory AuthenticationState.fromJson(String source) =>
10297
AuthenticationState.fromMap(json.decode(source));
10398

99+
@override
100+
String toString() {
101+
return 'AuthenticationState(deviceId: $deviceId, deviceType: $deviceType, userId: $userId, userEmail: $userEmail, isAuthenticated: $isAuthenticated, firstName: $firstName, lastName: $lastName, isAdmin: $isAdmin, shouldChangePassword: $shouldChangePassword, profileImagePath: $profileImagePath, deviceInfo: $deviceInfo)';
102+
}
103+
104104
@override
105105
bool operator ==(Object other) {
106106
if (identical(this, other)) return true;
@@ -114,7 +114,7 @@ class AuthenticationState {
114114
other.firstName == firstName &&
115115
other.lastName == lastName &&
116116
other.isAdmin == isAdmin &&
117-
other.isFirstLogin == isFirstLogin &&
117+
other.shouldChangePassword == shouldChangePassword &&
118118
other.profileImagePath == profileImagePath &&
119119
other.deviceInfo == deviceInfo;
120120
}
@@ -129,7 +129,7 @@ class AuthenticationState {
129129
firstName.hashCode ^
130130
lastName.hashCode ^
131131
isAdmin.hashCode ^
132-
isFirstLogin.hashCode ^
132+
shouldChangePassword.hashCode ^
133133
profileImagePath.hashCode ^
134134
deviceInfo.hashCode;
135135
}

mobile/lib/modules/login/models/login_response.model.dart

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ class LogInReponse {
88
final String lastName;
99
final String profileImagePath;
1010
final bool isAdmin;
11-
final bool isFirstLogin;
11+
final bool shouldChangePassword;
1212

1313
LogInReponse({
1414
required this.accessToken,
@@ -18,7 +18,7 @@ class LogInReponse {
1818
required this.lastName,
1919
required this.profileImagePath,
2020
required this.isAdmin,
21-
required this.isFirstLogin,
21+
required this.shouldChangePassword,
2222
});
2323

2424
LogInReponse copyWith({
@@ -29,7 +29,7 @@ class LogInReponse {
2929
String? lastName,
3030
String? profileImagePath,
3131
bool? isAdmin,
32-
bool? isFirstLogin,
32+
bool? shouldChangePassword,
3333
}) {
3434
return LogInReponse(
3535
accessToken: accessToken ?? this.accessToken,
@@ -39,7 +39,7 @@ class LogInReponse {
3939
lastName: lastName ?? this.lastName,
4040
profileImagePath: profileImagePath ?? this.profileImagePath,
4141
isAdmin: isAdmin ?? this.isAdmin,
42-
isFirstLogin: isFirstLogin ?? this.isFirstLogin,
42+
shouldChangePassword: shouldChangePassword ?? this.shouldChangePassword,
4343
);
4444
}
4545

@@ -53,7 +53,7 @@ class LogInReponse {
5353
result.addAll({'lastName': lastName});
5454
result.addAll({'profileImagePath': profileImagePath});
5555
result.addAll({'isAdmin': isAdmin});
56-
result.addAll({'isFirstLogin': isFirstLogin});
56+
result.addAll({'shouldChangePassword': shouldChangePassword});
5757

5858
return result;
5959
}
@@ -67,7 +67,7 @@ class LogInReponse {
6767
lastName: map['lastName'] ?? '',
6868
profileImagePath: map['profileImagePath'] ?? '',
6969
isAdmin: map['isAdmin'] ?? false,
70-
isFirstLogin: map['isFirstLogin'] ?? false,
70+
shouldChangePassword: map['shouldChangePassword'] ?? false,
7171
);
7272
}
7373

@@ -78,7 +78,7 @@ class LogInReponse {
7878

7979
@override
8080
String toString() {
81-
return 'LogInReponse(accessToken: $accessToken, userId: $userId, userEmail: $userEmail, firstName: $firstName, lastName: $lastName, profileImagePath: $profileImagePath, isAdmin: $isAdmin, isFirstLogin: $isFirstLogin)';
81+
return 'LogInReponse(accessToken: $accessToken, userId: $userId, userEmail: $userEmail, firstName: $firstName, lastName: $lastName, profileImagePath: $profileImagePath, isAdmin: $isAdmin, shouldChangePassword: $shouldChangePassword)';
8282
}
8383

8484
@override
@@ -93,7 +93,7 @@ class LogInReponse {
9393
other.lastName == lastName &&
9494
other.profileImagePath == profileImagePath &&
9595
other.isAdmin == isAdmin &&
96-
other.isFirstLogin == isFirstLogin;
96+
other.shouldChangePassword == shouldChangePassword;
9797
}
9898

9999
@override
@@ -105,6 +105,6 @@ class LogInReponse {
105105
lastName.hashCode ^
106106
profileImagePath.hashCode ^
107107
isAdmin.hashCode ^
108-
isFirstLogin.hashCode;
108+
shouldChangePassword.hashCode;
109109
}
110110
}

mobile/lib/modules/login/providers/authentication.provider.dart

Lines changed: 27 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ class AuthenticationNotifier extends StateNotifier<AuthenticationState> {
2424
lastName: '',
2525
profileImagePath: '',
2626
isAdmin: false,
27-
isFirstLogin: false,
27+
shouldChangePassword: false,
2828
isAuthenticated: false,
2929
deviceInfo: DeviceInfoRemote(
3030
id: 0,
@@ -87,7 +87,7 @@ class AuthenticationNotifier extends StateNotifier<AuthenticationState> {
8787
lastName: payload.lastName,
8888
profileImagePath: payload.profileImagePath,
8989
isAdmin: payload.isAdmin,
90-
isFirstLoggedIn: payload.isFirstLogin,
90+
shouldChangePassword: payload.shouldChangePassword,
9191
);
9292

9393
if (isSavedLoginInfo) {
@@ -111,8 +111,12 @@ class AuthenticationNotifier extends StateNotifier<AuthenticationState> {
111111
// Register device info
112112
try {
113113
Response res = await _networkService.postRequest(
114-
url: 'device-info',
115-
data: {'deviceId': state.deviceId, 'deviceType': state.deviceType});
114+
url: 'device-info',
115+
data: {
116+
'deviceId': state.deviceId,
117+
'deviceType': state.deviceType,
118+
},
119+
);
116120

117121
DeviceInfoRemote deviceInfo = DeviceInfoRemote.fromJson(res.toString());
118122
state = state.copyWith(deviceInfo: deviceInfo);
@@ -133,7 +137,7 @@ class AuthenticationNotifier extends StateNotifier<AuthenticationState> {
133137
firstName: '',
134138
lastName: '',
135139
profileImagePath: '',
136-
isFirstLogin: false,
140+
shouldChangePassword: false,
137141
isAuthenticated: false,
138142
isAdmin: false,
139143
deviceInfo: DeviceInfoRemote(
@@ -163,6 +167,24 @@ class AuthenticationNotifier extends StateNotifier<AuthenticationState> {
163167
updateUserProfileImagePath(String path) {
164168
state = state.copyWith(profileImagePath: path);
165169
}
170+
171+
Future<bool> changePassword(String newPassword) async {
172+
Response res = await _networkService.putRequest(
173+
url: 'user',
174+
data: {
175+
'id': state.userId,
176+
'password': newPassword,
177+
'shouldChangePassword': false,
178+
},
179+
);
180+
181+
if (res.statusCode == 200) {
182+
state = state.copyWith(shouldChangePassword: false);
183+
return true;
184+
} else {
185+
return false;
186+
}
187+
}
166188
}
167189

168190
final authenticationProvider =

0 commit comments

Comments
 (0)