Skip to content

Commit

Permalink
Add ApiToken grant type
Browse files Browse the repository at this point in the history
  • Loading branch information
BaharaJr committed Oct 14, 2024
1 parent 89bf0f2 commit 2c18479
Show file tree
Hide file tree
Showing 4 changed files with 45 additions and 40 deletions.
9 changes: 3 additions & 6 deletions lib/modules/auth/auth.module.dart
Original file line number Diff line number Diff line change
Expand Up @@ -102,10 +102,6 @@ class AuthModule {

AuthToken token = AuthToken.fromJson(tokenObject);

DateTime now = DateTime.now();

DateTime tokenCreatedAt = now.subtract(Duration(minutes: 2));

userObject['token'] = token.accessToken;
userObject['tokenType'] = token.tokenType;
userObject['tokenExpiry'] = token.expiresIn;
Expand All @@ -114,8 +110,9 @@ class AuthModule {
userObject['dirty'] = true;
userObject['baseUrl'] = instanceUrl;
userObject['authType'] = "token";
userObject['tokenCreatedAt'] = tokenCreatedAt.toIso8601String();

userObject['tokenExpiresAt'] = DateTime.now()
.add(Duration(seconds: token.expiresIn))
.toIso8601String();
User user = User.fromApi(userObject);

await d2Instance.userModule.user.setData(user).save();
Expand Down
18 changes: 11 additions & 7 deletions lib/modules/auth/entities/user.entity.dart
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ class User extends IdentifiableEntity {
final String? refreshToken;

@Column(nullable: true)
final String? tokenCreatedAt;
final String? tokenExpiresAt;

@Column(nullable: true)
final int? tokenExpiry;
Expand Down Expand Up @@ -109,7 +109,7 @@ class User extends IdentifiableEntity {
this.authType,
this.phoneNumber,
this.userGroups,
this.tokenCreatedAt,
this.tokenExpiresAt,
required this.isLoggedIn,
required bool dirty})
: super(
Expand Down Expand Up @@ -167,8 +167,10 @@ class User extends IdentifiableEntity {
userGroups: (jsonData['userGroups'] ?? [])
.map<UserGroup>((group) => UserGroup.fromJson(group))
.toList(),
tokenCreatedAt:
jsonData['tokenCreatedAt'] ?? DateTime.now().toIso8601String(),
tokenExpiresAt: jsonData['tokenExpiresAt'] ??
DateTime.now()
.add(Duration(seconds: jsonData['tokenExpiry'] ?? 3600))
.toIso8601String(),
dirty: jsonData['dirty']);
}

Expand Down Expand Up @@ -221,8 +223,10 @@ class User extends IdentifiableEntity {
? jsonData['datasets'].toString()
: null,
isLoggedIn: jsonData['isLoggedIn'] ?? false,
tokenCreatedAt:
jsonData['tokenCreatedAt'] ?? DateTime.now().toIso8601String(),
tokenExpiresAt: jsonData['tokenExpiresAt'] ??
DateTime.now()
.add(Duration(seconds: jsonData['tokenExpiry'] ?? 3600))
.toIso8601String(),
dirty: jsonData['dirty'] ?? false);
}

Expand Down Expand Up @@ -284,7 +288,7 @@ class User extends IdentifiableEntity {
data['baseUrl'] = this.baseUrl;
data['dirty'] = this.dirty;
data['userGroups'] = this.userGroups;
data['tokenCreatedAt'] = this.tokenCreatedAt;
data['tokenExpiresAt'] = this.tokenExpiresAt;

return data;
}
Expand Down
33 changes: 19 additions & 14 deletions lib/shared/queries/base.query.dart
Original file line number Diff line number Diff line change
Expand Up @@ -270,24 +270,29 @@ class BaseQuery<T extends BaseEntity> {
}

Future<List<T>> fetchOnline({Dio? dioTestClient}) async {
final dhisUrl = await this.dhisUrl();
final response = await HttpClient.get(dhisUrl,
database: this.database, dioTestClient: dioTestClient);
try {
final dhisUrl = await this.dhisUrl();
final response = await HttpClient.get(dhisUrl,
database: this.database, dioTestClient: dioTestClient);

List data = response.body != null
? response.body[this.apiResourceName]?.toList() ?? []
: [];
List data = response.body != null
? response.body[this.apiResourceName]?.toList() ?? []
: [];

return data.map((dataItem) {
dataItem['dirty'] = false;
dataItem['synced'] = true;
ClassMirror classMirror =
AnnotationReflectable.reflectType(T) as ClassMirror;
return data.map((dataItem) {
dataItem['dirty'] = false;
dataItem['synced'] = true;
ClassMirror classMirror =
AnnotationReflectable.reflectType(T) as ClassMirror;

var x = classMirror.newInstance('fromJson', [dataItem]) as T;
var x = classMirror.newInstance('fromJson', [dataItem]) as T;

return x;
}).toList();
return x;
}).toList();
} catch (e) {
print(e);
return [];
}
}

Future<Map<String, dynamic>> deleteOnline({Dio? dioTestClient}) async {
Expand Down
25 changes: 12 additions & 13 deletions lib/shared/utilities/http-details.util.dart
Original file line number Diff line number Diff line change
Expand Up @@ -9,20 +9,19 @@ import 'package:sqflite/sqflite.dart';
class OAuthToken {
String token;
int expiresIn;
DateTime tokenCreatedAt;
DateTime tokenExpiresAt;
String refreshToken;
String url;

OAuthToken(
{required this.token,
required this.expiresIn,
required this.tokenCreatedAt,
required this.tokenExpiresAt,
required this.url,
required this.refreshToken});

bool isTokenExpired() {
final expirationTime = tokenCreatedAt.add(Duration(seconds: expiresIn));
return DateTime.now().isAfter(expirationTime);
return DateTime.now().isAfter(tokenExpiresAt);
}

Future<dynamic> renew() async {
Expand All @@ -37,12 +36,10 @@ class OAuthToken {
final dio = Dio(options);

final response = await dio.get(
'/oauth/token/refresh?token=${this.refreshToken}',
'/oauth/token/refresh?token=${this.refreshToken}&isNew=true',
);
return response.data;
} on DioException catch (e) {
print(e.toString());
print(e.response?.data);
return e.response?.data ?? {};
}
}
Expand Down Expand Up @@ -81,30 +78,30 @@ class HttpDetails {

//!TODO: Improve token refresh implementation not to use the SDK core
//!TODO!: Improve token refresh implementation not to use the SDK core
if (this.token != null && this.tokenType == 'bearer') {
if (this.token != null &&
(this.tokenType == 'bearer' || this.tokenType == 'ApiToken')) {
final OAuthToken token = OAuthToken(
token: this.token as String,
expiresIn: user?.tokenExpiry as int,
refreshToken: user?.refreshToken as String,
url: user?.baseUrl as String,
tokenCreatedAt: DateTime.parse(user?.tokenCreatedAt as String),
tokenExpiresAt: DateTime.parse(user?.tokenExpiresAt as String),
);

if (token.isTokenExpired() && user != null) {
dynamic tokenObject = await token.renew();
if (tokenObject != null && tokenObject['access_token'] != null) {
dynamic userObject = user.toJson();
AuthToken authToken = AuthToken.fromJson(tokenObject);
DateTime now = DateTime.now();
DateTime tokenCreatedAt = now.subtract(Duration(minutes: 2));
userObject['token'] = authToken.accessToken;
userObject['tokenType'] = authToken.tokenType;
userObject['tokenExpiry'] = token.expiresIn;
userObject['refreshToken'] = token.refreshToken;
userObject['isLoggedIn'] = true;
userObject['dirty'] = true;
userObject['authType'] = "token";
userObject['tokenCreatedAt'] = tokenCreatedAt.toIso8601String();
userObject['tokenExpiresAt'] = DateTime.now()
.add(Duration(seconds: token.expiresIn))
.toIso8601String();
User userData = User.fromApi(userObject);
await UserQuery(database: database).setData(userData).save();
this.token = authToken.accessToken;
Expand All @@ -125,6 +122,8 @@ class HttpDetails {
switch (this.tokenType) {
case 'bearer':
return 'Bearer';
case 'ApiToken':
return 'ApiToken';
default:
return 'Basic';
}
Expand Down

0 comments on commit 2c18479

Please sign in to comment.