From b51169ab3c73189fd2ff8fe3b12aa2d80a3e6305 Mon Sep 17 00:00:00 2001 From: Armand <4831c0@proton.me> Date: Fri, 12 Sep 2025 18:12:54 +0200 Subject: [PATCH] token: add support for guardians --- .../lib/helpers/api/client/kreta_client.dart | 4 +- firka/lib/helpers/db/models/token_model.dart | 16 +- .../lib/helpers/db/models/token_model.g.dart | 273 +++++++++++++++--- 3 files changed, 251 insertions(+), 42 deletions(-) diff --git a/firka/lib/helpers/api/client/kreta_client.dart b/firka/lib/helpers/api/client/kreta_client.dart index e63771cb..1ea40b85 100644 --- a/firka/lib/helpers/api/client/kreta_client.dart +++ b/firka/lib/helpers/api/client/kreta_client.dart @@ -114,7 +114,7 @@ class KretaClient { // it would be *ideal* to use xor and left shift here, however // binary operations seem to round the number down to // 32 bits for some reason??? - var cacheKey = model.studentId! + ((id.index + 1) * pow(10, 11)); + var cacheKey = model.studentIdNorm! + ((id.index + 1) * pow(10, 11)); var cache = await isar.genericCacheModels.get(cacheKey as int); dynamic resp; @@ -352,7 +352,7 @@ class KretaClient { bool forceCache, int counter, Future Function(dynamic, int) storeCache) async { - var cacheKey = genCacheKey(from, model.studentId!); + var cacheKey = genCacheKey(from, model.studentIdNorm!); var cache = await cacheModel.get(cacheKey); var formatter = DateFormat('yyyy-MM-dd'); var fromStr = formatter.format(from); diff --git a/firka/lib/helpers/db/models/token_model.dart b/firka/lib/helpers/db/models/token_model.dart index 9aa6a08c..b53393f1 100644 --- a/firka/lib/helpers/db/models/token_model.dart +++ b/firka/lib/helpers/db/models/token_model.dart @@ -8,7 +8,8 @@ part 'token_model.g.dart'; @collection class TokenModel { - Id? studentId; // Custom unique student identifier + Id? studentIdNorm; // Custom unique student identifier with "G0" removed + String? studentId; // Custom unique student identifier String? iss; // Institution id for student String? idToken; // Unique identifier for the token if needed String? accessToken; // The main auth token @@ -17,10 +18,11 @@ class TokenModel { TokenModel(); - factory TokenModel.fromValues(Id studentId, String iss, String idToken, - String accessToken, String refreshToken, int expiryDate) { + factory TokenModel.fromValues(Id studentIdNorm, studentId, String iss, + String idToken, String accessToken, String refreshToken, int expiryDate) { var m = TokenModel(); + m.studentIdNorm = studentIdNorm; m.studentId = studentId; m.iss = iss; m.idToken = idToken; @@ -35,16 +37,16 @@ class TokenModel { var m = TokenModel(); final jwt = JWT.decode(resp.idToken); - // TODO: Add a proper model for jwt id - - m.studentId = int.parse(jwt.payload["kreta:user_name"]); + m.studentIdNorm = int.parse( + jwt.payload["kreta:user_name"].toString().replaceAll("G0", "")); + m.studentId = jwt.payload["kreta:user_name"]; m.iss = jwt.payload["kreta:institute_code"]; m.idToken = resp.idToken; m.accessToken = resp.accessToken; m.refreshToken = resp.refreshToken; m.expiryDate = timeNow() .add(Duration(seconds: resp.expiresIn)) - .subtract(Duration(minutes: 10)); // just to be safe + .subtract(Duration(minutes: 1)); // just to be safe return m; } diff --git a/firka/lib/helpers/db/models/token_model.g.dart b/firka/lib/helpers/db/models/token_model.g.dart index dbe50d69..9765a4ca 100644 --- a/firka/lib/helpers/db/models/token_model.g.dart +++ b/firka/lib/helpers/db/models/token_model.g.dart @@ -41,13 +41,18 @@ const TokenModelSchema = CollectionSchema( id: 4, name: r'refreshToken', type: IsarType.string, + ), + r'studentId': PropertySchema( + id: 5, + name: r'studentId', + type: IsarType.string, ) }, estimateSize: _tokenModelEstimateSize, serialize: _tokenModelSerialize, deserialize: _tokenModelDeserialize, deserializeProp: _tokenModelDeserializeProp, - idName: r'studentId', + idName: r'studentIdNorm', indexes: {}, links: {}, embeddedSchemas: {}, @@ -87,6 +92,12 @@ int _tokenModelEstimateSize( bytesCount += 3 + value.length * 3; } } + { + final value = object.studentId; + if (value != null) { + bytesCount += 3 + value.length * 3; + } + } return bytesCount; } @@ -101,6 +112,7 @@ void _tokenModelSerialize( writer.writeString(offsets[2], object.idToken); writer.writeString(offsets[3], object.iss); writer.writeString(offsets[4], object.refreshToken); + writer.writeString(offsets[5], object.studentId); } TokenModel _tokenModelDeserialize( @@ -115,7 +127,8 @@ TokenModel _tokenModelDeserialize( object.idToken = reader.readStringOrNull(offsets[2]); object.iss = reader.readStringOrNull(offsets[3]); object.refreshToken = reader.readStringOrNull(offsets[4]); - object.studentId = id; + object.studentId = reader.readStringOrNull(offsets[5]); + object.studentIdNorm = id; return object; } @@ -136,13 +149,15 @@ P _tokenModelDeserializeProp

( return (reader.readStringOrNull(offset)) as P; case 4: return (reader.readStringOrNull(offset)) as P; + case 5: + return (reader.readStringOrNull(offset)) as P; default: throw IsarError('Unknown property with id $propertyId'); } } Id _tokenModelGetId(TokenModel object) { - return object.studentId ?? Isar.autoIncrement; + return object.studentIdNorm ?? Isar.autoIncrement; } List> _tokenModelGetLinks(TokenModel object) { @@ -150,12 +165,12 @@ List> _tokenModelGetLinks(TokenModel object) { } void _tokenModelAttach(IsarCollection col, Id id, TokenModel object) { - object.studentId = id; + object.studentIdNorm = id; } extension TokenModelQueryWhereSort on QueryBuilder { - QueryBuilder anyStudentId() { + QueryBuilder anyStudentIdNorm() { return QueryBuilder.apply(this, (query) { return query.addWhereClause(const IdWhereClause.any()); }); @@ -164,70 +179,71 @@ extension TokenModelQueryWhereSort extension TokenModelQueryWhere on QueryBuilder { - QueryBuilder studentIdEqualTo( - Id studentId) { + QueryBuilder studentIdNormEqualTo( + Id studentIdNorm) { return QueryBuilder.apply(this, (query) { return query.addWhereClause(IdWhereClause.between( - lower: studentId, - upper: studentId, + lower: studentIdNorm, + upper: studentIdNorm, )); }); } - QueryBuilder studentIdNotEqualTo( - Id studentId) { + QueryBuilder + studentIdNormNotEqualTo(Id studentIdNorm) { return QueryBuilder.apply(this, (query) { if (query.whereSort == Sort.asc) { return query .addWhereClause( - IdWhereClause.lessThan(upper: studentId, includeUpper: false), + IdWhereClause.lessThan(upper: studentIdNorm, includeUpper: false), ) .addWhereClause( - IdWhereClause.greaterThan(lower: studentId, includeLower: false), + IdWhereClause.greaterThan( + lower: studentIdNorm, includeLower: false), ); } else { return query .addWhereClause( - IdWhereClause.greaterThan(lower: studentId, includeLower: false), + IdWhereClause.greaterThan( + lower: studentIdNorm, includeLower: false), ) .addWhereClause( - IdWhereClause.lessThan(upper: studentId, includeUpper: false), + IdWhereClause.lessThan(upper: studentIdNorm, includeUpper: false), ); } }); } - QueryBuilder studentIdGreaterThan( - Id studentId, - {bool include = false}) { + QueryBuilder + studentIdNormGreaterThan(Id studentIdNorm, {bool include = false}) { return QueryBuilder.apply(this, (query) { return query.addWhereClause( - IdWhereClause.greaterThan(lower: studentId, includeLower: include), + IdWhereClause.greaterThan(lower: studentIdNorm, includeLower: include), ); }); } - QueryBuilder studentIdLessThan( - Id studentId, + QueryBuilder studentIdNormLessThan( + Id studentIdNorm, {bool include = false}) { return QueryBuilder.apply(this, (query) { return query.addWhereClause( - IdWhereClause.lessThan(upper: studentId, includeUpper: include), + IdWhereClause.lessThan(upper: studentIdNorm, includeUpper: include), ); }); } - QueryBuilder studentIdBetween( - Id lowerStudentId, - Id upperStudentId, { + QueryBuilder studentIdNormBetween( + Id lowerStudentIdNorm, + Id upperStudentIdNorm, { bool includeLower = true, bool includeUpper = true, }) { return QueryBuilder.apply(this, (query) { return query.addWhereClause(IdWhereClause.between( - lower: lowerStudentId, + lower: lowerStudentIdNorm, includeLower: includeLower, - upper: upperStudentId, + upper: upperStudentIdNorm, includeUpper: includeUpper, )); }); @@ -931,43 +947,197 @@ extension TokenModelQueryFilter } QueryBuilder studentIdEqualTo( - Id? value) { + String? value, { + bool caseSensitive = true, + }) { return QueryBuilder.apply(this, (query) { return query.addFilterCondition(FilterCondition.equalTo( property: r'studentId', value: value, + caseSensitive: caseSensitive, )); }); } QueryBuilder studentIdGreaterThan( - Id? value, { + String? value, { bool include = false, + bool caseSensitive = true, }) { return QueryBuilder.apply(this, (query) { return query.addFilterCondition(FilterCondition.greaterThan( include: include, property: r'studentId', value: value, + caseSensitive: caseSensitive, )); }); } QueryBuilder studentIdLessThan( - Id? value, { + String? value, { bool include = false, + bool caseSensitive = true, }) { return QueryBuilder.apply(this, (query) { return query.addFilterCondition(FilterCondition.lessThan( include: include, property: r'studentId', value: value, + caseSensitive: caseSensitive, )); }); } QueryBuilder studentIdBetween( + String? lower, + String? upper, { + bool includeLower = true, + bool includeUpper = true, + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.between( + property: r'studentId', + lower: lower, + includeLower: includeLower, + upper: upper, + includeUpper: includeUpper, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder + studentIdStartsWith( + String value, { + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.startsWith( + property: r'studentId', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder studentIdEndsWith( + String value, { + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.endsWith( + property: r'studentId', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder studentIdContains( + String value, + {bool caseSensitive = true}) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.contains( + property: r'studentId', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder studentIdMatches( + String pattern, + {bool caseSensitive = true}) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.matches( + property: r'studentId', + wildcard: pattern, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder + studentIdIsEmpty() { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.equalTo( + property: r'studentId', + value: '', + )); + }); + } + + QueryBuilder + studentIdIsNotEmpty() { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.greaterThan( + property: r'studentId', + value: '', + )); + }); + } + + QueryBuilder + studentIdNormIsNull() { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(const FilterCondition.isNull( + property: r'studentIdNorm', + )); + }); + } + + QueryBuilder + studentIdNormIsNotNull() { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(const FilterCondition.isNotNull( + property: r'studentIdNorm', + )); + }); + } + + QueryBuilder + studentIdNormEqualTo(Id? value) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.equalTo( + property: r'studentIdNorm', + value: value, + )); + }); + } + + QueryBuilder + studentIdNormGreaterThan( + Id? value, { + bool include = false, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.greaterThan( + include: include, + property: r'studentIdNorm', + value: value, + )); + }); + } + + QueryBuilder + studentIdNormLessThan( + Id? value, { + bool include = false, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.lessThan( + include: include, + property: r'studentIdNorm', + value: value, + )); + }); + } + + QueryBuilder + studentIdNormBetween( Id? lower, Id? upper, { bool includeLower = true, @@ -975,7 +1145,7 @@ extension TokenModelQueryFilter }) { return QueryBuilder.apply(this, (query) { return query.addFilterCondition(FilterCondition.between( - property: r'studentId', + property: r'studentIdNorm', lower: lower, includeLower: includeLower, upper: upper, @@ -1052,6 +1222,18 @@ extension TokenModelQuerySortBy return query.addSortBy(r'refreshToken', Sort.desc); }); } + + QueryBuilder sortByStudentId() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'studentId', Sort.asc); + }); + } + + QueryBuilder sortByStudentIdDesc() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'studentId', Sort.desc); + }); + } } extension TokenModelQuerySortThenBy @@ -1127,6 +1309,18 @@ extension TokenModelQuerySortThenBy return query.addSortBy(r'studentId', Sort.desc); }); } + + QueryBuilder thenByStudentIdNorm() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'studentIdNorm', Sort.asc); + }); + } + + QueryBuilder thenByStudentIdNormDesc() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'studentIdNorm', Sort.desc); + }); + } } extension TokenModelQueryWhereDistinct @@ -1164,13 +1358,20 @@ extension TokenModelQueryWhereDistinct return query.addDistinctBy(r'refreshToken', caseSensitive: caseSensitive); }); } + + QueryBuilder distinctByStudentId( + {bool caseSensitive = true}) { + return QueryBuilder.apply(this, (query) { + return query.addDistinctBy(r'studentId', caseSensitive: caseSensitive); + }); + } } extension TokenModelQueryProperty on QueryBuilder { - QueryBuilder studentIdProperty() { + QueryBuilder studentIdNormProperty() { return QueryBuilder.apply(this, (query) { - return query.addPropertyName(r'studentId'); + return query.addPropertyName(r'studentIdNorm'); }); } @@ -1203,4 +1404,10 @@ extension TokenModelQueryProperty return query.addPropertyName(r'refreshToken'); }); } + + QueryBuilder studentIdProperty() { + return QueryBuilder.apply(this, (query) { + return query.addPropertyName(r'studentId'); + }); + } }