[client] process bootstrap response during login

This commit is contained in:
Abhishek Shroff
2025-05-28 01:55:43 +05:30
parent bf1b1986c9
commit 94c2cdf962
10 changed files with 161 additions and 61 deletions

View File

@@ -0,0 +1,48 @@
class LoggedInUser {
final int id;
final String email;
final String name;
final String home;
final int permissions;
LoggedInUser({
required this.id,
required this.email,
required this.name,
required this.home,
required this.permissions,
});
@override
bool operator ==(Object other) {
if (identical(this, other)) return true;
if (other is! LoggedInUser) return false;
return id == other.id &&
email == other.email &&
name == other.name &&
home == other.home &&
permissions == other.permissions;
}
@override
int get hashCode => id.hashCode ^ email.hashCode ^ name.hashCode ^ home.hashCode ^ permissions.hashCode;
Map<String, dynamic> toJson() => {
"id": id,
"email": email,
"name": name,
"home": home,
"permissions": permissions,
};
factory LoggedInUser.fromJson(Map<String, dynamic> map) {
return LoggedInUser(
id: map['id'],
email: map['email'],
name: map['name'],
home: map['home'],
permissions: map['permissions'],
);
}
}

View File

@@ -1,11 +0,0 @@
part of 'parsers.dart';
Bookmark parseBookmark(Map<String, dynamic> data) {
return Bookmark(
resourceId: data['resource_id'],
name: data['name'],
dir: data['dir'],
created: data['created'],
deleted: data.containsKey('deleted') ? data['deleted'] : false,
);
}

View File

@@ -1,4 +1,46 @@
import 'package:phylum/libphylum/db/db.dart';
import 'package:phylum/libphylum/logged_in_user.dart';
part 'bookmarks.dart';
part 'publinks.dart';
Bookmark parseBookmark(Map<String, dynamic> data) {
return Bookmark(
resourceId: data['resource_id'],
name: data['name'],
dir: data['dir'],
created: data['created'],
deleted: data.containsKey('deleted') ? data['deleted'] : false,
);
}
Iterable<Publink> parsePublinks(List data, String? root) {
return data.cast<Map>().map((e) => parsePublink(e, root: root));
}
Publink parsePublink(Map data, {String? root}) {
return Publink(
id: data['id'],
created: data['created'] == null ? null : DateTime.fromMillisecondsSinceEpoch(data['created']),
root: root ?? data['root'],
accessLimit: data['access_limit'],
protected: data['protected'],
accessed: data['accessed'],
expires: data['expires'] == null ? null : DateTime.fromMillisecondsSinceEpoch(data['expires']),
);
}
User parseUser(Map data) {
return User(
id: data['id'],
email: data['email'],
name: data['name'],
);
}
LoggedInUser parseLoggedInUser(Map data) {
return LoggedInUser(
id: data['id'],
email: data['email'],
name: data['name'],
home: data['home'],
permissions: data['permissions'],
);
}

View File

@@ -1,17 +0,0 @@
part of 'parsers.dart';
Iterable<Publink> parsePublinks(List data, String? root) {
return data.cast<Map>().map((e) => parsePublink(e, root: root));
}
Publink parsePublink(Map data, {String? root}) {
return Publink(
id: data['id'],
created: data['created'] == null ? null : DateTime.fromMillisecondsSinceEpoch(data['created']),
root: root ?? data['root'],
accessLimit: data['access_limit'],
protected: data['protected'],
accessed: data['accessed'],
expires: data['expires'] == null ? null : DateTime.fromMillisecondsSinceEpoch(data['expires']),
);
}

View File

@@ -122,21 +122,4 @@ class PhylumAccount extends Account<PhylumAccount> {
await db.dropDatabase();
}
}
static Future<PhylumAccount> createFromLoginResponse(
Uri serverUri,
Map<String, dynamic> response,
) async {
final account = PhylumAccount.create(serverUri: serverUri, accessToken: response['access_token']);
await account.initialized;
final userMap = response['user'];
account.userEmail = userMap['email'];
account.userName = userMap['name'];
account.userId = userMap['id'];
account.userHome = userMap['home'];
account.userPermissions = userMap['permissions'];
return account;
}
}

View File

@@ -0,0 +1,57 @@
part of 'responses.dart';
class BootstrapLoginResponse extends PhylumApiSuccessResponse {
final String? accessToken;
final LoggedInUser user;
final Iterable<Bookmark> bookmarks;
final Iterable<User> users;
final bool clear;
final int until;
BootstrapLoginResponse._({
required this.accessToken,
required this.user,
required this.bookmarks,
required this.users,
required this.until,
required this.clear,
});
factory BootstrapLoginResponse.fromResponse(Map<String, dynamic> data) {
final bookmarks = (data["bookmarks"] as List).cast<Map>().map((u) => parseBookmark(u.cast<String, dynamic>()));
final users = (data["users"] as List).cast<Map>().map((u) => parseUser(u.cast<String, dynamic>()));
return BootstrapLoginResponse._(
accessToken: data['access_token'],
user: parseLoggedInUser(data['user']),
bookmarks: bookmarks,
users: users,
until: data['until'],
clear: data['clear']);
}
@override
Future process(PhylumAccount account) async {
await account.db.batch((batch) {
if (clear) {
batch.deleteAll(account.db.bookmarks);
batch.deleteAll(account.db.users);
}
batch.insertAll(account.db.bookmarks, bookmarks, mode: InsertMode.replace);
batch.insertAll(account.db.users, users, mode: InsertMode.replace);
});
account.userEmail = user.email;
account.userName = user.name;
account.userId = user.id;
account.userHome = user.home;
account.userPermissions = user.permissions;
for (final b in bookmarks) {
await account.datastore.get<Bookmark>().replaceRemoteData(b.resourceId, b);
}
for (final u in users) {
await account.datastore.get<User>().replaceRemoteData(u.id.toString(), u);
}
}
}

View File

@@ -4,12 +4,14 @@ import 'package:drift/drift.dart';
import 'package:http/http.dart';
import 'package:offtheline/offtheline.dart';
import 'package:phylum/libphylum/db/db.dart';
import 'package:phylum/libphylum/logged_in_user.dart';
import 'package:phylum/libphylum/parsers/parsers.dart';
import 'package:phylum/libphylum/phylum_account.dart';
import 'package:phylum/util/permissions.dart';
part 'bookmark_list_response.dart';
part 'bookmark_response.dart';
part 'bootstrap_login_response.dart';
part 'empty_response.dart';
part 'resource_info_response.dart';
part 'resource_response.dart';

View File

@@ -13,11 +13,7 @@ class UserListResponse extends PhylumApiSuccessResponse {
UserListResponse({required this.users});
factory UserListResponse.fromResponse(Map<String, dynamic> data) {
final users = (data["users"] as List).cast<Map>().map((u) => User(
id: u['id'],
email: u['email'],
name: u['name'],
));
final users = (data["users"] as List).cast<Map>().map((u) => parseUser(u));
return UserListResponse(users: users);
}
}

View File

@@ -12,11 +12,6 @@ class UserResponse extends PhylumApiSuccessResponse {
UserResponse({required this.user});
factory UserResponse.fromResponse(Map<String, dynamic> data) {
final user = User(
id: data['id'],
email: data['email'],
name: data['name'],
);
return UserResponse(user: user);
return UserResponse(user: parseUser(data));
}
}

View File

@@ -5,6 +5,7 @@ import 'package:flutter/material.dart';
import 'package:http/http.dart';
import 'package:offtheline/offtheline.dart';
import 'package:phylum/libphylum/phylum_account.dart';
import 'package:phylum/libphylum/responses/responses.dart';
import 'package:phylum/ui/app/router.dart';
import 'package:phylum/ui/app/routes.dart';
import 'package:phylum/ui/common/logo_row.dart';
@@ -133,9 +134,13 @@ class _LoginPageState extends State<LoginPage> {
final navigator = Navigator.of(context);
showProgressDialog(context, barrierDismissible: false, title: 'Processing Login Response');
try {
final response = jsonDecode(responseString) as Map;
final account = await PhylumAccount.createFromLoginResponse(instanceUri, response.cast<String, dynamic>());
accountManager.addAccount(account);
final response =
BootstrapLoginResponse.fromResponse((jsonDecode(responseString) as Map).cast<String, dynamic>());
final account = PhylumAccount.create(serverUri: instanceUri, accessToken: response.accessToken!);
await account.initialized;
await response.process(account);
await accountManager.addAccount(account);
navigator.pop();
} catch (e) {
navigator.pop();