import 'dart:async'; import 'package:fixnum/fixnum.dart'; import 'package:app/pb/google/protobuf/timestamp.pb.dart'; import 'package:path/path.dart'; import 'package:sqflite/sqflite.dart'; class Session { Session({ this.sessionId, this.accessToken, this.accessTokenExpiresAt, this.refreshToken, this.refreshTokenExpiresAt, this.accountId, }); String? sessionId; String? accessToken; String? refreshToken; Timestamp? accessTokenExpiresAt; Timestamp? refreshTokenExpiresAt; Int64? accountId; late Database _database; Future get database async => _database; static Future get session async { final Database db = await openDatabase( join(await getDatabasesPath(), 'df_database.db'), onCreate: (db, version) { return db.execute( 'CREATE TABLE sessions(accountId INTEGER PRIMARY KEY, sessionId TEXT, accessToken TEXT, accessTokenExpiresAt TEXT, refreshToken TEXT, refreshTokenExpiresAt TEXT)', ); }, version: 1, ); Session s = Session(); s._database = db; final sessions = await s.getSessions(); if (sessions.isNotEmpty) { final session = sessions[0]; session._database = db; return session; } return s; } void _init() { _initDatabase(); } void reset() { if (sessionId != null) { removeSession(sessionId!); } sessionId = null; accessToken = null; refreshToken = null; accessTokenExpiresAt = null; refreshTokenExpiresAt = null; } Future _initDatabase() async { // print('DB: INITIALIZING - start'); _database = await openDatabase( join(await getDatabasesPath(), 'df_database.db'), onCreate: (db, version) { return db.execute( 'CREATE TABLE sessions(accountId INTEGER PRIMARY KEY, sessionId TEXT, accessToken TEXT, accessTokenExpiresAt TEXT, refreshToken TEXT, refreshTokenExpiresAt TEXT)', ); }, version: 1, ); // print('DB: INITIALIZING - end'); return _database; } Map toMap() { return { 'accountId': accountId?.toInt(), 'sessionId': sessionId, 'accessToken': accessToken, 'accessTokenExpiresAt': accessTokenExpiresAt?.toDateTime().toString(), 'refreshToken': refreshToken, 'refreshTokenExpiresAt': refreshTokenExpiresAt?.toDateTime().toString(), }; } @override String toString() { return 'Session{accountId: $accountId, sessionId: $sessionId, accessToken: $accessToken, accessTokenExpiresAt: ${accessTokenExpiresAt.toString()}, refreshToken: $refreshToken, refreshTokenExpiresAt: ${refreshTokenExpiresAt.toString()}}'; } static newSession(Session session) async { final db = await openDatabase( join(await getDatabasesPath(), 'df_database.db'), onCreate: (db, version) { return db.execute( 'CREATE TABLE sessions(accountId INTEGER PRIMARY KEY, sessionId TEXT, accessToken TEXT, accessTokenExpiresAt TEXT, refreshToken TEXT, refreshTokenExpiresAt TEXT)', ); }, version: 1, ); await db.insert( 'sessions', session.toMap(), conflictAlgorithm: ConflictAlgorithm.replace, ); } static Future updateToken(Session s) async { final db = await openDatabase( join(await getDatabasesPath(), 'df_database.db'), onCreate: (db, version) { return db.execute( 'CREATE TABLE sessions(accountId INTEGER PRIMARY KEY, sessionId TEXT, accessToken TEXT, accessTokenExpiresAt TEXT, refreshToken TEXT, refreshTokenExpiresAt TEXT)', ); }, version: 1, ); await db.update( 'sessions', s.toMap(), ); return s; //await getSession(s.accountId!); } Future insertSession(Session session) async { // print('INSERTING SESSION: ${session.sessionId}'); final db = _database; await db.insert( 'sessions', session.toMap(), conflictAlgorithm: ConflictAlgorithm.replace, ); // print('INSERT RESULT: $result'); } Future updateSession(Session session) async { sessionId = session.sessionId; accessToken = session.accessToken; accessTokenExpiresAt = session.accessTokenExpiresAt; refreshToken = session.refreshToken; refreshTokenExpiresAt = session.refreshTokenExpiresAt; final db = _database; await db.update('sessions', session.toMap()); return session; } Future removeSession(String sessionId) async { final db = _database; await db.delete('sessions', where: 'sessionId = ?', whereArgs: [sessionId]); this.sessionId = null; refreshToken = null; accessTokenExpiresAt = null; refreshTokenExpiresAt = null; accountId = null; accessToken = null; } Future> getSessions() async { final db = await database; final List> maps = await db.query('sessions'); // print(maps); final List sessions = List.generate( maps.length, (i) { // print('GOT MAP: ${maps[i]}'); if (maps[i]['sessionId'] == null) { return Session(); } return Session( sessionId: maps[i]['sessionId'] as String, accessToken: maps[i]['accessToken'] as String, accessTokenExpiresAt: Timestamp.fromDateTime( DateTime.parse(maps[i]['accessTokenExpiresAt'] as String)), refreshToken: maps[i]['refreshToken'] as String, refreshTokenExpiresAt: Timestamp.fromDateTime( DateTime.parse(maps[i]['refreshTokenExpiresAt'] as String)), accountId: Int64(maps[i]['accountId'] as int), ); }, ); return sessions; } static Future getSession(Int64 accountId) async { final Database db = await openDatabase( join(await getDatabasesPath(), 'df_database.db'), onCreate: (db, version) { return db.execute( 'CREATE TABLE sessions(accountId INTEGER PRIMARY KEY, sessionId TEXT, accessToken TEXT, accessTokenExpiresAt TEXT, refreshToken TEXT, refreshTokenExpiresAt TEXT)', ); }, version: 1, ); final List> maps = await db.query('sessions', where: 'accountId = ?', whereArgs: [accountId], limit: 1); final List sessions = List.generate( maps.length, (i) { return Session( sessionId: maps[i]['sessionId'] as String, accessToken: maps[i]['accessToken'] as String, accessTokenExpiresAt: maps[i]['accessTokenExpiresAt'] as Timestamp, refreshToken: maps[i]['refreshToken'] as String, refreshTokenExpiresAt: maps[i]['refreshTokenExpiresAt'] as Timestamp, accountId: maps[i]['accountId'] as Int64, ); }, ); return sessions[0]; } }