mirror of
https://github.com/Mercantec-GHC/h4-projekt-gruppe-0-sm.git
synced 2025-04-27 16:24:07 +02:00
195 lines
5.2 KiB
Dart
195 lines
5.2 KiB
Dart
import 'dart:io';
|
|
|
|
import 'package:flutter/material.dart';
|
|
import 'package:mobile/models/user.dart';
|
|
import 'package:mobile/results.dart';
|
|
import 'package:mobile/server/server.dart';
|
|
import 'package:path_provider/path_provider.dart';
|
|
|
|
class CookieController {
|
|
CookieController();
|
|
|
|
static Future<File> get _cacheFile async {
|
|
final directory = await getApplicationCacheDirectory();
|
|
return File("${directory.path}/cookies.txt").create();
|
|
}
|
|
|
|
Future<void> clear() async {
|
|
(await _cacheFile).writeAsString("", mode: FileMode.write);
|
|
}
|
|
|
|
Future<void> save(String token) async {
|
|
(await _cacheFile).writeAsString(token, mode: FileMode.write);
|
|
}
|
|
|
|
Future<Result<String, Null>> load() async {
|
|
final token = await (await _cacheFile).readAsString();
|
|
if (token.isEmpty) {
|
|
return const Err(null);
|
|
}
|
|
return Ok(token);
|
|
}
|
|
}
|
|
|
|
class SessionController {
|
|
final Server server;
|
|
final CookieController cookieController = CookieController();
|
|
|
|
User? _sessionUser;
|
|
|
|
final List<_ChangeListener> _sessionChangeListeners = [];
|
|
final List<_ChangeListener> _userChangeListeners = [];
|
|
|
|
SessionController({required this.server});
|
|
|
|
Future<Result<Null, String>> loginUser(String email, String password) async {
|
|
final loginResult = await server.login(email, password);
|
|
switch (loginResult) {
|
|
case Ok<String, String>(value: final sessionToken):
|
|
await cookieController.save(sessionToken);
|
|
notifySessionChangeListeners();
|
|
return const Ok(null);
|
|
case Err<String, String>(value: final message):
|
|
return Err(message);
|
|
}
|
|
}
|
|
|
|
Future<Result<Null, Null>> loadCachedUser() async {
|
|
switch (await cookieController.load()) {
|
|
case Ok<String, Null>():
|
|
return _loadCurrentUser();
|
|
case Err<String, Null>():
|
|
notifyUserChangeListeners();
|
|
return const Err(null);
|
|
}
|
|
}
|
|
|
|
Future<Result<Null, Null>> loadUpdatedUser() async {
|
|
return _loadCurrentUser();
|
|
}
|
|
|
|
Future<Result<Null, Null>> _loadCurrentUser() async {
|
|
final sessionUserResult = await requestWithSession<User>(
|
|
(server, sessionToken) => server.sessionUser(sessionToken));
|
|
switch (sessionUserResult) {
|
|
case Ok<User, String>(value: final sessionUser):
|
|
_sessionUser = sessionUser;
|
|
notifyUserChangeListeners();
|
|
return const Ok(null);
|
|
case Err<User, String>():
|
|
return const Err(null);
|
|
}
|
|
}
|
|
|
|
Future<Null> logout() async {
|
|
switch (await cookieController.load()) {
|
|
case Ok<String, Null>(value: final sessionToken):
|
|
await server.logout(sessionToken);
|
|
await cookieController.clear();
|
|
_sessionUser = null;
|
|
notifySessionChangeListeners();
|
|
case Err<String, Null>():
|
|
notifySessionChangeListeners();
|
|
return;
|
|
}
|
|
}
|
|
|
|
User get user {
|
|
final user = _sessionUser;
|
|
if (user == null) {
|
|
throw NoUser();
|
|
}
|
|
return user;
|
|
}
|
|
|
|
bool get hasUser {
|
|
return _sessionUser != null;
|
|
}
|
|
|
|
Future<Result<Null, String>> addBalance() async {
|
|
final addBalanceResult = await requestWithSession(
|
|
(server, sessionToken) => server.addBalance(sessionToken));
|
|
if (addBalanceResult case Err<Null, String>(value: final message)) {
|
|
return Err(message);
|
|
}
|
|
if (await _loadCurrentUser() case Err<Null, Null>()) {
|
|
return const Err("could not fetch user");
|
|
}
|
|
return const Ok(null);
|
|
}
|
|
|
|
/// Package private.
|
|
Future<Result<T, String>> requestWithSession<T>(
|
|
Future<Result<T, String>> Function(Server server, String sessionToken)
|
|
func) async {
|
|
switch (await cookieController.load()) {
|
|
case Err<String, Null>():
|
|
return const Err("unathorized");
|
|
case Ok<String, Null>(value: final sessionToken):
|
|
final result = await func(server, sessionToken);
|
|
if (result case Err<T, String>(value: final message)) {
|
|
if (message == "unauthorized") {
|
|
cookieController.clear();
|
|
_sessionUser = null;
|
|
notifySessionChangeListeners();
|
|
notifyUserChangeListeners();
|
|
return const Err("unathorized");
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
}
|
|
|
|
void notifySessionChangeListeners() {
|
|
for (final listener in _sessionChangeListeners) {
|
|
listener.notify();
|
|
}
|
|
}
|
|
|
|
void notifyUserChangeListeners() {
|
|
for (final listener in _userChangeListeners) {
|
|
listener.notify();
|
|
}
|
|
}
|
|
|
|
void _addSessionChangeListener(_ChangeListener listener) {
|
|
_sessionChangeListeners.add(listener);
|
|
}
|
|
|
|
void _addUserChangeListener(_ChangeListener listener) {
|
|
_userChangeListeners.add(listener);
|
|
}
|
|
}
|
|
|
|
abstract class _ChangeListener {
|
|
void notify();
|
|
}
|
|
|
|
class NoUser implements Exception {}
|
|
|
|
class SessionProvider extends ChangeNotifier implements _ChangeListener {
|
|
final SessionController controller;
|
|
|
|
SessionProvider({required this.controller}) {
|
|
controller._addSessionChangeListener(this);
|
|
}
|
|
|
|
@override
|
|
void notify() {
|
|
notifyListeners();
|
|
}
|
|
}
|
|
|
|
class CurrentUserProvider extends ChangeNotifier implements _ChangeListener {
|
|
final SessionController controller;
|
|
|
|
CurrentUserProvider({required this.controller}) {
|
|
controller._addUserChangeListener(this);
|
|
}
|
|
|
|
@override
|
|
void notify() {
|
|
notifyListeners();
|
|
}
|
|
}
|