refreshUser method
Refreshes login-level fields (avatar, name, email) via Portal login, and academic data (profile, registrations) via the student query service. The login call also establishes a fresh session for the subsequent SSO calls.
On missing or rejected credentials, destroys the session and returns a never-completing future (router guard handles redirect).
Implementation
Future<void> refreshUser() async {
final user = await _database.select(_database.users).getSingleOrNull();
if (user == null) {
throw StateError('Cannot fetch user profile when not logged in');
}
// Re-login to refresh login-level fields and establish a fresh session.
// This makes the subsequent withAuth call's inner SSO unlikely to need
// re-authentication, since the session was just established.
final UserDto userDto;
try {
userDto = await _reauthenticate();
} on _AuthFailedException {
return Completer<void>().future;
}
final (profile, records) = await withAuth(
() async {
final profileFuture = _studentQueryService.getStudentProfile();
final recordsFuture = _studentQueryService.getRegistrationRecords();
return (profileFuture, recordsFuture).wait;
},
sso: [.studentQueryService],
);
await _database.transaction(() async {
await (_database.update(
_database.users,
)..where((t) => t.id.equals(user.id))).write(
UsersCompanion(
avatarFilename: Value(userDto.avatarFilename ?? ''),
nameZh: Value(userDto.name ?? ''),
email: Value(userDto.email ?? ''),
nameEn: Value(profile.englishName),
dateOfBirth: Value(profile.dateOfBirth),
programZh: Value(profile.programZh),
programEn: Value(profile.programEn),
departmentZh: Value(profile.departmentZh),
departmentEn: Value(profile.departmentEn),
fetchedAt: Value(DateTime.now()),
),
);
for (final record in records) {
if (record.semester.year == null || record.semester.term == null) {
continue;
}
final semester = await _database.getOrCreateSemester(
record.semester.year!,
record.semester.term!,
);
await _database
.into(_database.userSemesterSummaries)
.insert(
UserSemesterSummariesCompanion.insert(
user: user.id,
semester: semester.id,
className: Value(record.className),
enrollmentStatus: Value(record.enrollmentStatus),
registered: Value(record.registered),
graduated: Value(record.graduated),
),
onConflict: DoUpdate(
(old) => UserSemesterSummariesCompanion(
className: Value(record.className),
enrollmentStatus: Value(record.enrollmentStatus),
registered: Value(record.registered),
graduated: Value(record.graduated),
),
target: [
_database.userSemesterSummaries.user,
_database.userSemesterSummaries.semester,
],
),
);
}
});
}