df/frontend/app/lib/model/services/backend_service.dart

510 lines
16 KiB
Dart

import 'dart:io';
import 'package:app/model/apis/app_exception.dart';
import 'package:app/model/services/storage_service.dart';
import 'package:app/pb/account.pb.dart';
import 'package:app/pb/account_info.pb.dart';
import 'package:app/pb/google/protobuf/timestamp.pb.dart';
import 'package:app/pb/person.pb.dart';
import 'package:app/data/database.dart';
import 'package:app/pb/rpc_create_account.pb.dart';
import 'package:app/pb/rpc_create_account_info.pb.dart';
import 'package:app/pb/rpc_create_person.pb.dart';
import 'package:app/pb/rpc_get_account.pb.dart';
import 'package:app/pb/rpc_get_account_info.pb.dart';
import 'package:app/pb/rpc_get_person.pb.dart';
import 'package:app/pb/rpc_list_persons.pb.dart';
import 'package:app/pb/rpc_login.pb.dart';
import 'package:app/pb/rpc_refresh_token.pb.dart';
import 'package:app/pb/rpc_resend_verification.pb.dart';
import 'package:app/pb/rpc_update_person.pb.dart';
import 'package:app/pb/service_df.pbgrpc.dart';
import 'package:fixnum/fixnum.dart';
import 'package:grpc/grpc.dart';
class BackendService {
BackendService() {
_init();
}
final String baseUrl = '10.0.0.2';
final String port = '9090';
final StorageService _storageService = StorageService();
late Session _session;
final dfClient _client = dfClient(
ClientChannel('df.itsscb.de',
port: 9090,
options: const ChannelOptions(
credentials: ChannelCredentials.insecure(),
)),
options: CallOptions(
timeout: const Duration(seconds: 5),
),
);
static get client => dfClient(
ClientChannel('df.itsscb.de',
port: 9090,
options: const ChannelOptions(
credentials: ChannelCredentials.insecure(),
)),
options: CallOptions(
timeout: const Duration(seconds: 5),
),
);
void _init() {
Session.session.then((value) => _session = value);
}
Future<Session?> _isLoggedIn() async {
Session session = await Session.session;
if (session.accessToken == null ||
session.refreshToken == null ||
session.accountId == null) {
return null;
}
if (session.accessTokenExpiresAt == null) {
return null;
}
if (session.refreshTokenExpiresAt == null) {
return null;
}
if (session.refreshTokenExpiresAt!.toDateTime().isBefore(DateTime.now())) {
return null;
} else {
if (session.refreshToken != null &&
session.accessTokenExpiresAt!.toDateTime().isBefore(DateTime.now())) {
session = await refreshToken(session);
}
}
return session;
}
static Future<bool> get isLoggedIn async {
Session session = await Session.session;
if (session.accessToken == null ||
session.refreshToken == null ||
session.accountId == null) {
return false;
}
if (session.accessTokenExpiresAt == null) {
await logout();
return false;
}
if (session.refreshTokenExpiresAt == null) {
await logout();
return false;
}
if (session.refreshTokenExpiresAt!.toDateTime().isBefore(DateTime.now())) {
await logout();
return false;
}
if (session.accessTokenExpiresAt!.toDateTime().isBefore(DateTime.now())) {
Session s = await BackendService.refreshToken(session);
if (s == session) {
return false;
}
}
return true;
}
static Future<Int64?> get accountId async {
return (await Session.session).accountId;
}
Future<bool> createAccount(
{required String email, required String password}) async {
try {
// final resp =
await BackendService.client.createAccount(CreateAccountRequest(
email: email,
password: password,
));
// print(resp);
// await _storageService.setAccountId(resp.account.id);
return await login(email: email, password: password);
} on SocketException {
throw FetchDataException('Keine Internet Verbindung');
} on GrpcError catch (err) {
throw FetchDataException('${err.message}');
} catch (err) {
throw InternalException(err.toString());
}
}
Future<bool> createAccountInfo(
{required String firstname,
required String lastname,
required String streetAddress,
required String zip,
required String city,
required String country,
required String phoneNumber,
required DateTime birthday}) async {
try {
final acc = await account;
if (acc == null) {
throw FetchDataException('AccountID nicht gespeichert');
}
final resp = BackendService.client.createAccountInfo(
CreateAccountInfoRequest(
accountId: acc.id,
firstname: firstname,
lastname: lastname,
street: streetAddress,
zip: zip,
city: city,
country: country,
phone: phoneNumber,
birthday: Timestamp.fromDateTime(birthday),
),
options: CallOptions(
metadata: {
'Authorization': 'Bearer ${await _storageService.accessToken}'
},
),
);
return resp != null;
} on SocketException {
throw FetchDataException('Keine Internet Verbindung');
} on GrpcError catch (err) {
throw FetchDataException('${err.message}');
} catch (err) {
throw InternalException(err.toString());
}
}
Future<bool> resendVerification({required Int64 accountId}) async {
try {
final resp = await BackendService.client.resendVerification(
ResendVerificationRequest(
accountId: accountId,
),
options: CallOptions(
metadata: {
'Authorization': 'Bearer ${await _storageService.accessToken}'
},
),
);
return resp.account.id == accountId;
} on SocketException {
throw FetchDataException('Keine Internet Verbindung');
} on GrpcError catch (err) {
throw FetchDataException('${err.message}');
} catch (err) {
throw InternalException(err.toString());
}
}
Future<Account?> get account async {
try {
final id = await _storageService.accountId;
if (id == 0) {
return null;
}
final resp = await _client.getAccount(GetAccountRequest(id: id),
options: CallOptions(metadata: {
'Authorization': 'Bearer ${await _storageService.accessToken}'
}));
if (resp.account.id < 1) {
return null;
}
return resp.account;
} on SocketException {
throw FetchDataException('Keine Internet Verbindung');
} on GrpcError catch (err) {
if (err.code == 12) {
throw UnauthorizedException('${err.message}');
}
throw FetchDataException('${err.message}');
} catch (err) {
throw InternalException(err.toString());
}
}
Future<Account> getAccount() async {
Session? session = await _isLoggedIn();
if (session == null) {
throw UnauthorizedException('Sitzung ist abgelaufen');
}
try {
final GetAccountResponse response = await _client.getAccount(
GetAccountRequest(id: session.accountId),
options: CallOptions(
metadata: {'Authorization': 'Bearer ${session.accessToken}'}));
return response.account;
} on SocketException {
throw FetchDataException('Keine Internet Verbindung');
} on GrpcError catch (err) {
if (err.code == 16) {
throw UnauthorizedException(err.message);
}
throw FetchDataException(err.message);
} catch (err) {
throw InternalException(err.toString());
}
}
Future<AccountInfo> getAccountInfo() async {
Session session = await Session.session;
if (session.accessTokenExpiresAt == null) {
throw UnauthorizedException('Keine Siztung gefunden');
}
if (session.accessTokenExpiresAt!.toDateTime().isBefore(DateTime.now())) {
session = await refreshToken(session);
if (session.accessTokenExpiresAt!.toDateTime().isBefore(DateTime.now())) {
throw UnauthorizedException('Sitzung ist abgelaufen');
}
}
try {
final GetAccountInfoResponse response = await _client
.getAccountInfo(GetAccountInfoRequest(accountId: _session.accountId));
return response.accountInfo;
} on SocketException {
throw FetchDataException('Keine Internet Verbindung');
} on GrpcError catch (err) {
if (err.code == 16) {
await refreshToken(session);
return getAccountInfo();
}
throw FetchDataException(err.message);
} catch (err) {
throw InternalException(err.toString());
}
}
Future<Person> getPerson(Int64 personId) async {
Session session = await Session.session;
if (session.accessTokenExpiresAt == null) {
throw UnauthorizedException('Keine Siztung gefunden');
}
if (session.accessTokenExpiresAt!.toDateTime().isBefore(DateTime.now())) {
session = await refreshToken(session);
if (session.accessTokenExpiresAt == null) {
throw UnauthorizedException('Sitzung ist abgelaufen');
}
}
try {
final GetPersonResponse response =
await _client.getPerson(GetPersonRequest(id: personId));
return response.person;
} on SocketException {
throw FetchDataException('Keine Internet Verbindung');
} on GrpcError catch (err) {
throw FetchDataException(err.message);
} catch (err) {
throw InternalException(err.toString());
}
}
Future<Person> updatePerson(
{required Int64 id,
String? firstname,
String? lastname,
String? street,
String? zip,
String? city,
String? country,
Timestamp? birthday}) async {
Session session = await Session.session;
if (session.accessTokenExpiresAt == null) {
throw UnauthorizedException('Keine Siztung gefunden');
}
if (session.accessTokenExpiresAt!.toDateTime().isBefore(DateTime.now())) {
session = await refreshToken(session);
if (session.accessTokenExpiresAt == null) {
throw UnauthorizedException('Sitzung ist abgelaufen');
}
}
try {
final UpdatePersonRequest req = UpdatePersonRequest(
id: id,
);
if (lastname != null) {
req.lastname = lastname;
}
if (firstname != null) {
req.firstname = firstname;
}
if (street != null) {
req.street = street;
}
if (city != null) {
req.city = city;
}
if (zip != null) {
req.zip = zip;
}
if (country != null) {
req.country = country;
}
if (birthday != null) {
req.birthday = birthday;
}
final UpdatePersonResponse response = await _client.updatePerson(req,
options: CallOptions(
metadata: {'Authorization': 'Bearer ${session.accessToken}'}));
return response.person;
} on SocketException {
throw FetchDataException('Keine Internet Verbindung');
} on GrpcError catch (err) {
throw FetchDataException(err.message);
} catch (err) {
throw InternalException(err.toString());
}
}
Future<Person> createPerson(
{required String firstname,
required String lastname,
required String street,
required String zip,
required String city,
required String country,
required Timestamp birthday}) async {
Session session = await Session.session;
if (session.accessTokenExpiresAt == null) {
throw UnauthorizedException('Keine Siztung gefunden');
}
if (session.accessTokenExpiresAt!.toDateTime().isBefore(DateTime.now())) {
session = await refreshToken(session);
if (session.accessTokenExpiresAt == null) {
throw UnauthorizedException('Sitzung ist abgelaufen');
}
}
try {
final CreatePersonRequest req = CreatePersonRequest(
accountId: session.accountId,
lastname: lastname,
firstname: firstname,
street: street,
city: city,
zip: zip,
country: country,
birthday: birthday,
);
final CreatePersonResponse response = await _client.createPerson(req,
options: CallOptions(
metadata: {'Authorization': 'Bearer ${session.accessToken}'}));
return response.person;
} on SocketException {
throw FetchDataException('Keine Internet Verbindung');
} on GrpcError catch (err) {
throw FetchDataException(err.message);
} catch (err) {
throw InternalException(err.toString());
}
}
Future<List<Person>> listPersons() async {
Session session = await Session.session;
if (session.accessTokenExpiresAt == null) {
throw UnauthorizedException('Keine Siztung gefunden');
}
if (session.accessTokenExpiresAt!.toDateTime().isBefore(DateTime.now())) {
session = await refreshToken(session);
if (session.accessTokenExpiresAt == null) {
throw UnauthorizedException('Sitzung ist abgelaufen');
}
}
try {
final ListPersonsResponse response = await _client.listPersons(
ListPersonsRequest(
accountId: session.accountId,
),
options: CallOptions(
metadata: {'Authorization': 'Bearer ${session.accessToken}'}));
return response.persons;
} on SocketException {
throw FetchDataException('Keine Internet Verbindung');
} on GrpcError catch (err) {
throw FetchDataException(err.message);
} catch (err) {
throw InternalException(err.toString());
}
}
// Future<List<Person>> listPersons() async {
// if (_session.accessToken == null) {
// refreshToken();
// }
// try {
// ListPersonsResponse response =
// await _client.listPersons(ListPersonsRequest(accountId: _session.accountId));
// return response.persons;
// } on SocketException {
// throw FetchDataException('Keine Internet Verbindung');
// } on GrpcError catch (err) {
// throw FetchDataException(err.message);
// } catch (err) {
// throw InternalException(err.toString());
// }
// }
Future<bool> login({required String email, required String password}) async {
try {
final LoginResponse response = await BackendService.client.login(
LoginRequest(
email: email,
password: password,
),
);
// Session s = Session(
// accessToken: response.accessToken,
// sessionId: response.sessionId,
// accessTokenExpiresAt: response.accessTokenExpiresAt,
// refreshToken: response.refreshToken,
// refreshTokenExpiresAt: response.refreshTokenExpiresAt,
// accountId: response.accountId,
// );
await _storageService.setAccessToken(response.accessToken);
await _storageService.setAccountId(response.accountId);
// await Session.newSession(s);
return response.accessToken != '';
} on SocketException {
throw FetchDataException('Keine Internet Verbindung');
} on GrpcError catch (err) {
throw FetchDataException(err.message);
} catch (err) {
throw InternalException(err.toString());
}
}
static Future<Session> refreshToken(Session session) async {
try {
final RefreshTokenResponse response = await BackendService.client
.refreshToken(
RefreshTokenRequest(refreshToken: session.refreshToken));
session.accessToken = response.accessToken;
session.accessTokenExpiresAt = response.accessTokenExpiresAt;
session = await Session.updateToken(session);
return session;
} on SocketException {
throw FetchDataException('Keine Internet Verbindung');
} on GrpcError catch (err) {
throw FetchDataException(err.message);
} catch (err) {
throw InternalException(err.toString());
}
}
static Future<void> logout() async {
Session session = await Session.session;
session.reset();
}
}