diff --git a/backend-dart/lib/application/repository/in_memory_auth_repository_impl.dart b/backend-dart/lib/application/repository/in_memory_auth_repository_impl.dart new file mode 100644 index 0000000..1fb35fe --- /dev/null +++ b/backend-dart/lib/application/repository/in_memory_auth_repository_impl.dart @@ -0,0 +1,81 @@ +import 'package:backend_dart/domain/errors/app_error.dart'; +import 'package:backend_dart/domain/errors/error.dart'; +import 'package:backend_dart/domain/repository/auth_repository.dart'; +import 'package:dart_jsonwebtoken/dart_jsonwebtoken.dart'; +import 'package:fpdart/fpdart.dart'; + +class InMemoryAuthRepositoryImpl implements AuthRepository { + final String secretKey; + final Map sessionCache = {}; + final Duration tokenExpiry; + + InMemoryAuthRepositoryImpl({ + required this.secretKey, + this.tokenExpiry = const Duration(hours: 24), + }); + + @override + TaskEither generateToken(String userId) { + return TaskEither.tryCatch( + () async { + final jwt = JWT({ + 'userId': userId, + 'exp': DateTime.now().add(tokenExpiry).millisecondsSinceEpoch, + }); + final token = jwt.sign(SecretKey(secretKey)); + + // Add to cache + sessionCache[token] = userId; + + return token; + }, + (error, _) => + AppError.authenticationError(message: 'Failed to generate token'), + ); + } + + @override + TaskEither validateToken(String token) { + return TaskEither.tryCatch( + () async { + final jwt = JWT.verify(token, SecretKey(secretKey)); + + // Extract userId + final userId = jwt.payload['userId'] as String?; + + if (userId == null) { + throw AppError.authenticationError( + message: 'Invalid token payload: userId not found'); + } + + // Check if the token exists in the cache + if (!sessionCache.containsKey(token)) { + throw AppError.authenticationError( + message: 'Token not found in cache'); + } + + return userId; + }, + (error, _) => error is AppError + ? error + : AppError.authenticationError(message: 'Failed to validate token'), + ); + } + + @override + TaskEither revokeToken(String token) { + return TaskEither.tryCatch( + () async { + if (sessionCache.containsKey(token)) { + sessionCache.remove(token); + return; + } else { + throw AppError.authenticationError(message: 'Token not found'); + } + }, + (error, _) => error is AppError + ? error + : AppError.authenticationError(message: 'Failed to revoke token'), + ); + } +} diff --git a/backend-dart/lib/application/repository/project_repository_impl.dart b/backend-dart/lib/application/repository/project_repository_impl.dart index 5532a64..9e49e2b 100644 --- a/backend-dart/lib/application/repository/project_repository_impl.dart +++ b/backend-dart/lib/application/repository/project_repository_impl.dart @@ -1,6 +1,6 @@ import 'package:backend_dart/domain/data/database.dart'; import 'package:backend_dart/domain/entities/project.dart'; -import 'package:backend_dart/domain/interface/error.dart'; +import 'package:backend_dart/domain/errors/error.dart'; import 'package:backend_dart/domain/repository/project_repository.dart'; import 'package:fpdart/fpdart.dart'; diff --git a/backend-dart/lib/application/repository/project_task_repository_impl.dart b/backend-dart/lib/application/repository/project_task_repository_impl.dart index 2e762ac..2921395 100644 --- a/backend-dart/lib/application/repository/project_task_repository_impl.dart +++ b/backend-dart/lib/application/repository/project_task_repository_impl.dart @@ -1,6 +1,6 @@ import 'package:backend_dart/domain/data/database.dart'; import 'package:backend_dart/domain/entities/project_task.dart'; -import 'package:backend_dart/domain/interface/error.dart'; +import 'package:backend_dart/domain/errors/error.dart'; import 'package:backend_dart/domain/repository/project_task_repository.dart'; import 'package:fpdart/fpdart.dart'; diff --git a/backend-dart/lib/application/repository/provider.dart b/backend-dart/lib/application/repository/provider.dart index 2f89b13..4e7843f 100644 --- a/backend-dart/lib/application/repository/provider.dart +++ b/backend-dart/lib/application/repository/provider.dart @@ -1,7 +1,9 @@ +import 'package:backend_dart/application/repository/in_memory_auth_repository_impl.dart'; import 'package:backend_dart/application/repository/project_repository_impl.dart'; import 'package:backend_dart/application/repository/project_task_repository_impl.dart'; import 'package:backend_dart/application/repository/time_entry_repository_impl.dart'; import 'package:backend_dart/application/repository/user_repository_impl.dart'; +import 'package:backend_dart/domain/repository/auth_repository.dart'; import 'package:backend_dart/domain/repository/project_repository.dart'; import 'package:backend_dart/domain/repository/project_task_repository.dart'; import 'package:backend_dart/domain/repository/time_entry_repository.dart'; @@ -28,3 +30,7 @@ final timeEntryProvider = Provider((ref) { final database = ref.read(databaseProvider); return TimeEntryRepositoryImpl(database); }); + +final authProvider = Provider((ref) { + return InMemoryAuthRepositoryImpl(secretKey: "Secret"); +}); diff --git a/backend-dart/lib/application/repository/time_entry_repository_impl.dart b/backend-dart/lib/application/repository/time_entry_repository_impl.dart index 929c909..df4c8aa 100644 --- a/backend-dart/lib/application/repository/time_entry_repository_impl.dart +++ b/backend-dart/lib/application/repository/time_entry_repository_impl.dart @@ -1,6 +1,6 @@ import 'package:backend_dart/domain/data/database.dart'; import 'package:backend_dart/domain/entities/time_entry.dart'; -import 'package:backend_dart/domain/interface/error.dart'; +import 'package:backend_dart/domain/errors/error.dart'; import 'package:backend_dart/domain/repository/time_entry_repository.dart'; import 'package:fpdart/fpdart.dart'; diff --git a/backend-dart/lib/application/repository/user_repository_impl.dart b/backend-dart/lib/application/repository/user_repository_impl.dart index 8554ec1..49dec81 100755 --- a/backend-dart/lib/application/repository/user_repository_impl.dart +++ b/backend-dart/lib/application/repository/user_repository_impl.dart @@ -1,6 +1,6 @@ import 'package:backend_dart/domain/entities/user.dart'; import 'package:backend_dart/domain/data/database.dart'; -import 'package:backend_dart/domain/interface/error.dart'; +import 'package:backend_dart/domain/errors/error.dart'; import 'package:backend_dart/domain/repository/user_repository.dart'; import 'package:fpdart/fpdart.dart'; diff --git a/backend-dart/lib/application/service/auth_service.dart b/backend-dart/lib/application/service/auth_service.dart new file mode 100644 index 0000000..89f4fbc --- /dev/null +++ b/backend-dart/lib/application/service/auth_service.dart @@ -0,0 +1,77 @@ +import 'dart:convert'; +import 'package:backend_dart/application/service/dto/auth_dto.dart'; +import 'package:backend_dart/common/request_helper.dart'; +import 'package:backend_dart/common/response_helpers.dart'; +import 'package:backend_dart/common/secure_hash.dart'; +import 'package:backend_dart/common/validation.dart'; +import 'package:backend_dart/domain/entities/user.dart'; +import 'package:backend_dart/domain/errors/app_error.dart'; +import 'package:backend_dart/domain/repository/auth_repository.dart'; +import 'package:backend_dart/domain/repository/user_repository.dart'; +import 'package:fpdart/fpdart.dart'; +import 'package:shelf/shelf.dart'; +import 'package:shelf_router/shelf_router.dart'; + +part 'auth_service.g.dart'; + +class AuthService { + final AuthRepository authRepository; + final UserRepository users; + + AuthService(this.authRepository, this.users); + + /// Route to generate a token + @Route.post('/login') + Future generateToken(Request request) async { + return requestToJson(request) + .flatMap(validateJsonKeys(['email', 'password'])) + .flatMap((json) => decodeJson(json, LoginRequestDTO.fromJson)) + .flatMap( + (loginRequest) => users.findByEmail(loginRequest.email).flatMap( + (user) => user.passwordHash == + generateSecureHash(loginRequest.password) + ? TaskEither.right(user) + : TaskEither.left( + AppError.authenticationError( + message: 'Invalid email or password'), + ), + ), + ) + .flatMap((user) => authRepository.generateToken(user.id).map((token) => + TokenResponseDTO(token: token, userId: user.id).toJson())) + .map(jsonEncode) + .toResponse() + .run(); + } + + /// Route to validate a token + @Route.post('/validate') + Future validateToken(Request request) async { + return requestToJson(request) + .flatMap(validateJsonKeys(['token'])) + .flatMap((json) => decodeJson(json, TokenRequestDTO.fromJson)) + .map((tokenRequest) => tokenRequest.token) + .flatMap((token) => authRepository.validateToken(token).map((userId) => + TokenResponseDTO(token: token, userId: userId).toJson())) + .map(jsonEncode) + .toResponse() + .run(); + } + + /// Route to revoke a token + @Route.post('/revoke') + Future revokeToken(Request request) async { + return requestToJson(request) + .flatMap(validateJsonKeys(['token'])) + .flatMap((json) => decodeJson(json, TokenRequestDTO.fromJson)) + .map((tokenRequest) => tokenRequest.token) + .flatMap(authRepository.revokeToken) + .map((_) => {'message': 'Token revoked successfully'}) + .map(jsonEncode) + .toResponse() + .run(); + } + + /// Router for the AuthService + Router get router => _$AuthServiceRouter(this); +} diff --git a/backend-dart/lib/application/service/auth_service.g.dart b/backend-dart/lib/application/service/auth_service.g.dart new file mode 100644 index 0000000..33b4e91 --- /dev/null +++ b/backend-dart/lib/application/service/auth_service.g.dart @@ -0,0 +1,27 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'auth_service.dart'; + +// ************************************************************************** +// ShelfRouterGenerator +// ************************************************************************** + +Router _$AuthServiceRouter(AuthService service) { + final router = Router(); + router.add( + 'POST', + r'/login', + service.generateToken, + ); + router.add( + 'POST', + r'/validate', + service.validateToken, + ); + router.add( + 'POST', + r'/revoke', + service.revokeToken, + ); + return router; +} diff --git a/backend-dart/lib/application/service/dto/auth_dto.dart b/backend-dart/lib/application/service/dto/auth_dto.dart new file mode 100644 index 0000000..d839b68 --- /dev/null +++ b/backend-dart/lib/application/service/dto/auth_dto.dart @@ -0,0 +1,42 @@ +import 'package:freezed_annotation/freezed_annotation.dart'; + +part 'auth_dto.freezed.dart'; +part 'auth_dto.g.dart'; + +/// TokenResponseDTO represents the response for a token generation or validation. +@freezed +class TokenResponseDTO with _$TokenResponseDTO { + const factory TokenResponseDTO({ + required String token, + required String userId, + }) = _TokenResponseDTO; + + /// JSON serialization + factory TokenResponseDTO.fromJson(Map json) => + _$TokenResponseDTOFromJson(json); +} + +/// TokenRequestDTO represents a request for operations involving tokens. +@freezed +class TokenRequestDTO with _$TokenRequestDTO { + const factory TokenRequestDTO({ + required String token, + }) = _TokenRequestDTO; + + /// JSON serialization + factory TokenRequestDTO.fromJson(Map json) => + _$TokenRequestDTOFromJson(json); +} + +/// LoginRequestDTO represents the login request. +@freezed +class LoginRequestDTO with _$LoginRequestDTO { + const factory LoginRequestDTO({ + required String email, + required String password, + }) = _LoginRequestDTO; + + /// JSON serialization + factory LoginRequestDTO.fromJson(Map json) => + _$LoginRequestDTOFromJson(json); +} diff --git a/backend-dart/lib/application/service/dto/auth_dto.freezed.dart b/backend-dart/lib/application/service/dto/auth_dto.freezed.dart new file mode 100644 index 0000000..ef0c95f --- /dev/null +++ b/backend-dart/lib/application/service/dto/auth_dto.freezed.dart @@ -0,0 +1,503 @@ +// coverage:ignore-file +// GENERATED CODE - DO NOT MODIFY BY HAND +// ignore_for_file: type=lint +// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark + +part of 'auth_dto.dart'; + +// ************************************************************************** +// FreezedGenerator +// ************************************************************************** + +T _$identity(T value) => value; + +final _privateConstructorUsedError = UnsupportedError( + 'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#adding-getters-and-methods-to-our-models'); + +TokenResponseDTO _$TokenResponseDTOFromJson(Map json) { + return _TokenResponseDTO.fromJson(json); +} + +/// @nodoc +mixin _$TokenResponseDTO { + String get token => throw _privateConstructorUsedError; + String get userId => throw _privateConstructorUsedError; + + /// Serializes this TokenResponseDTO to a JSON map. + Map toJson() => throw _privateConstructorUsedError; + + /// Create a copy of TokenResponseDTO + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + $TokenResponseDTOCopyWith get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $TokenResponseDTOCopyWith<$Res> { + factory $TokenResponseDTOCopyWith( + TokenResponseDTO value, $Res Function(TokenResponseDTO) then) = + _$TokenResponseDTOCopyWithImpl<$Res, TokenResponseDTO>; + @useResult + $Res call({String token, String userId}); +} + +/// @nodoc +class _$TokenResponseDTOCopyWithImpl<$Res, $Val extends TokenResponseDTO> + implements $TokenResponseDTOCopyWith<$Res> { + _$TokenResponseDTOCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + /// Create a copy of TokenResponseDTO + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? token = null, + Object? userId = null, + }) { + return _then(_value.copyWith( + token: null == token + ? _value.token + : token // ignore: cast_nullable_to_non_nullable + as String, + userId: null == userId + ? _value.userId + : userId // ignore: cast_nullable_to_non_nullable + as String, + ) as $Val); + } +} + +/// @nodoc +abstract class _$$TokenResponseDTOImplCopyWith<$Res> + implements $TokenResponseDTOCopyWith<$Res> { + factory _$$TokenResponseDTOImplCopyWith(_$TokenResponseDTOImpl value, + $Res Function(_$TokenResponseDTOImpl) then) = + __$$TokenResponseDTOImplCopyWithImpl<$Res>; + @override + @useResult + $Res call({String token, String userId}); +} + +/// @nodoc +class __$$TokenResponseDTOImplCopyWithImpl<$Res> + extends _$TokenResponseDTOCopyWithImpl<$Res, _$TokenResponseDTOImpl> + implements _$$TokenResponseDTOImplCopyWith<$Res> { + __$$TokenResponseDTOImplCopyWithImpl(_$TokenResponseDTOImpl _value, + $Res Function(_$TokenResponseDTOImpl) _then) + : super(_value, _then); + + /// Create a copy of TokenResponseDTO + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? token = null, + Object? userId = null, + }) { + return _then(_$TokenResponseDTOImpl( + token: null == token + ? _value.token + : token // ignore: cast_nullable_to_non_nullable + as String, + userId: null == userId + ? _value.userId + : userId // ignore: cast_nullable_to_non_nullable + as String, + )); + } +} + +/// @nodoc +@JsonSerializable() +class _$TokenResponseDTOImpl implements _TokenResponseDTO { + const _$TokenResponseDTOImpl({required this.token, required this.userId}); + + factory _$TokenResponseDTOImpl.fromJson(Map json) => + _$$TokenResponseDTOImplFromJson(json); + + @override + final String token; + @override + final String userId; + + @override + String toString() { + return 'TokenResponseDTO(token: $token, userId: $userId)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$TokenResponseDTOImpl && + (identical(other.token, token) || other.token == token) && + (identical(other.userId, userId) || other.userId == userId)); + } + + @JsonKey(includeFromJson: false, includeToJson: false) + @override + int get hashCode => Object.hash(runtimeType, token, userId); + + /// Create a copy of TokenResponseDTO + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @override + @pragma('vm:prefer-inline') + _$$TokenResponseDTOImplCopyWith<_$TokenResponseDTOImpl> get copyWith => + __$$TokenResponseDTOImplCopyWithImpl<_$TokenResponseDTOImpl>( + this, _$identity); + + @override + Map toJson() { + return _$$TokenResponseDTOImplToJson( + this, + ); + } +} + +abstract class _TokenResponseDTO implements TokenResponseDTO { + const factory _TokenResponseDTO( + {required final String token, + required final String userId}) = _$TokenResponseDTOImpl; + + factory _TokenResponseDTO.fromJson(Map json) = + _$TokenResponseDTOImpl.fromJson; + + @override + String get token; + @override + String get userId; + + /// Create a copy of TokenResponseDTO + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + _$$TokenResponseDTOImplCopyWith<_$TokenResponseDTOImpl> get copyWith => + throw _privateConstructorUsedError; +} + +TokenRequestDTO _$TokenRequestDTOFromJson(Map json) { + return _TokenRequestDTO.fromJson(json); +} + +/// @nodoc +mixin _$TokenRequestDTO { + String get token => throw _privateConstructorUsedError; + + /// Serializes this TokenRequestDTO to a JSON map. + Map toJson() => throw _privateConstructorUsedError; + + /// Create a copy of TokenRequestDTO + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + $TokenRequestDTOCopyWith get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $TokenRequestDTOCopyWith<$Res> { + factory $TokenRequestDTOCopyWith( + TokenRequestDTO value, $Res Function(TokenRequestDTO) then) = + _$TokenRequestDTOCopyWithImpl<$Res, TokenRequestDTO>; + @useResult + $Res call({String token}); +} + +/// @nodoc +class _$TokenRequestDTOCopyWithImpl<$Res, $Val extends TokenRequestDTO> + implements $TokenRequestDTOCopyWith<$Res> { + _$TokenRequestDTOCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + /// Create a copy of TokenRequestDTO + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? token = null, + }) { + return _then(_value.copyWith( + token: null == token + ? _value.token + : token // ignore: cast_nullable_to_non_nullable + as String, + ) as $Val); + } +} + +/// @nodoc +abstract class _$$TokenRequestDTOImplCopyWith<$Res> + implements $TokenRequestDTOCopyWith<$Res> { + factory _$$TokenRequestDTOImplCopyWith(_$TokenRequestDTOImpl value, + $Res Function(_$TokenRequestDTOImpl) then) = + __$$TokenRequestDTOImplCopyWithImpl<$Res>; + @override + @useResult + $Res call({String token}); +} + +/// @nodoc +class __$$TokenRequestDTOImplCopyWithImpl<$Res> + extends _$TokenRequestDTOCopyWithImpl<$Res, _$TokenRequestDTOImpl> + implements _$$TokenRequestDTOImplCopyWith<$Res> { + __$$TokenRequestDTOImplCopyWithImpl( + _$TokenRequestDTOImpl _value, $Res Function(_$TokenRequestDTOImpl) _then) + : super(_value, _then); + + /// Create a copy of TokenRequestDTO + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? token = null, + }) { + return _then(_$TokenRequestDTOImpl( + token: null == token + ? _value.token + : token // ignore: cast_nullable_to_non_nullable + as String, + )); + } +} + +/// @nodoc +@JsonSerializable() +class _$TokenRequestDTOImpl implements _TokenRequestDTO { + const _$TokenRequestDTOImpl({required this.token}); + + factory _$TokenRequestDTOImpl.fromJson(Map json) => + _$$TokenRequestDTOImplFromJson(json); + + @override + final String token; + + @override + String toString() { + return 'TokenRequestDTO(token: $token)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$TokenRequestDTOImpl && + (identical(other.token, token) || other.token == token)); + } + + @JsonKey(includeFromJson: false, includeToJson: false) + @override + int get hashCode => Object.hash(runtimeType, token); + + /// Create a copy of TokenRequestDTO + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @override + @pragma('vm:prefer-inline') + _$$TokenRequestDTOImplCopyWith<_$TokenRequestDTOImpl> get copyWith => + __$$TokenRequestDTOImplCopyWithImpl<_$TokenRequestDTOImpl>( + this, _$identity); + + @override + Map toJson() { + return _$$TokenRequestDTOImplToJson( + this, + ); + } +} + +abstract class _TokenRequestDTO implements TokenRequestDTO { + const factory _TokenRequestDTO({required final String token}) = + _$TokenRequestDTOImpl; + + factory _TokenRequestDTO.fromJson(Map json) = + _$TokenRequestDTOImpl.fromJson; + + @override + String get token; + + /// Create a copy of TokenRequestDTO + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + _$$TokenRequestDTOImplCopyWith<_$TokenRequestDTOImpl> get copyWith => + throw _privateConstructorUsedError; +} + +LoginRequestDTO _$LoginRequestDTOFromJson(Map json) { + return _LoginRequestDTO.fromJson(json); +} + +/// @nodoc +mixin _$LoginRequestDTO { + String get email => throw _privateConstructorUsedError; + String get password => throw _privateConstructorUsedError; + + /// Serializes this LoginRequestDTO to a JSON map. + Map toJson() => throw _privateConstructorUsedError; + + /// Create a copy of LoginRequestDTO + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + $LoginRequestDTOCopyWith get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $LoginRequestDTOCopyWith<$Res> { + factory $LoginRequestDTOCopyWith( + LoginRequestDTO value, $Res Function(LoginRequestDTO) then) = + _$LoginRequestDTOCopyWithImpl<$Res, LoginRequestDTO>; + @useResult + $Res call({String email, String password}); +} + +/// @nodoc +class _$LoginRequestDTOCopyWithImpl<$Res, $Val extends LoginRequestDTO> + implements $LoginRequestDTOCopyWith<$Res> { + _$LoginRequestDTOCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + /// Create a copy of LoginRequestDTO + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? email = null, + Object? password = null, + }) { + return _then(_value.copyWith( + email: null == email + ? _value.email + : email // ignore: cast_nullable_to_non_nullable + as String, + password: null == password + ? _value.password + : password // ignore: cast_nullable_to_non_nullable + as String, + ) as $Val); + } +} + +/// @nodoc +abstract class _$$LoginRequestDTOImplCopyWith<$Res> + implements $LoginRequestDTOCopyWith<$Res> { + factory _$$LoginRequestDTOImplCopyWith(_$LoginRequestDTOImpl value, + $Res Function(_$LoginRequestDTOImpl) then) = + __$$LoginRequestDTOImplCopyWithImpl<$Res>; + @override + @useResult + $Res call({String email, String password}); +} + +/// @nodoc +class __$$LoginRequestDTOImplCopyWithImpl<$Res> + extends _$LoginRequestDTOCopyWithImpl<$Res, _$LoginRequestDTOImpl> + implements _$$LoginRequestDTOImplCopyWith<$Res> { + __$$LoginRequestDTOImplCopyWithImpl( + _$LoginRequestDTOImpl _value, $Res Function(_$LoginRequestDTOImpl) _then) + : super(_value, _then); + + /// Create a copy of LoginRequestDTO + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? email = null, + Object? password = null, + }) { + return _then(_$LoginRequestDTOImpl( + email: null == email + ? _value.email + : email // ignore: cast_nullable_to_non_nullable + as String, + password: null == password + ? _value.password + : password // ignore: cast_nullable_to_non_nullable + as String, + )); + } +} + +/// @nodoc +@JsonSerializable() +class _$LoginRequestDTOImpl implements _LoginRequestDTO { + const _$LoginRequestDTOImpl({required this.email, required this.password}); + + factory _$LoginRequestDTOImpl.fromJson(Map json) => + _$$LoginRequestDTOImplFromJson(json); + + @override + final String email; + @override + final String password; + + @override + String toString() { + return 'LoginRequestDTO(email: $email, password: $password)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$LoginRequestDTOImpl && + (identical(other.email, email) || other.email == email) && + (identical(other.password, password) || + other.password == password)); + } + + @JsonKey(includeFromJson: false, includeToJson: false) + @override + int get hashCode => Object.hash(runtimeType, email, password); + + /// Create a copy of LoginRequestDTO + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @override + @pragma('vm:prefer-inline') + _$$LoginRequestDTOImplCopyWith<_$LoginRequestDTOImpl> get copyWith => + __$$LoginRequestDTOImplCopyWithImpl<_$LoginRequestDTOImpl>( + this, _$identity); + + @override + Map toJson() { + return _$$LoginRequestDTOImplToJson( + this, + ); + } +} + +abstract class _LoginRequestDTO implements LoginRequestDTO { + const factory _LoginRequestDTO( + {required final String email, + required final String password}) = _$LoginRequestDTOImpl; + + factory _LoginRequestDTO.fromJson(Map json) = + _$LoginRequestDTOImpl.fromJson; + + @override + String get email; + @override + String get password; + + /// Create a copy of LoginRequestDTO + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + _$$LoginRequestDTOImplCopyWith<_$LoginRequestDTOImpl> get copyWith => + throw _privateConstructorUsedError; +} diff --git a/backend-dart/lib/application/service/dto/auth_dto.g.dart b/backend-dart/lib/application/service/dto/auth_dto.g.dart new file mode 100644 index 0000000..18b05dd --- /dev/null +++ b/backend-dart/lib/application/service/dto/auth_dto.g.dart @@ -0,0 +1,47 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'auth_dto.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +_$TokenResponseDTOImpl _$$TokenResponseDTOImplFromJson( + Map json) => + _$TokenResponseDTOImpl( + token: json['token'] as String, + userId: json['userId'] as String, + ); + +Map _$$TokenResponseDTOImplToJson( + _$TokenResponseDTOImpl instance) => + { + 'token': instance.token, + 'userId': instance.userId, + }; + +_$TokenRequestDTOImpl _$$TokenRequestDTOImplFromJson( + Map json) => + _$TokenRequestDTOImpl( + token: json['token'] as String, + ); + +Map _$$TokenRequestDTOImplToJson( + _$TokenRequestDTOImpl instance) => + { + 'token': instance.token, + }; + +_$LoginRequestDTOImpl _$$LoginRequestDTOImplFromJson( + Map json) => + _$LoginRequestDTOImpl( + email: json['email'] as String, + password: json['password'] as String, + ); + +Map _$$LoginRequestDTOImplToJson( + _$LoginRequestDTOImpl instance) => + { + 'email': instance.email, + 'password': instance.password, + }; diff --git a/backend-dart/lib/application/service/mapper/project_dto_mapper.dart b/backend-dart/lib/application/service/mapper/project_dto_mapper.dart index 5260f39..d7b55ee 100644 --- a/backend-dart/lib/application/service/mapper/project_dto_mapper.dart +++ b/backend-dart/lib/application/service/mapper/project_dto_mapper.dart @@ -1,6 +1,6 @@ import 'package:backend_dart/application/service/dto/project_dto.dart'; import 'package:backend_dart/domain/entities/project.dart'; -import 'package:backend_dart/domain/interface/error.dart'; +import 'package:backend_dart/domain/errors/error.dart'; import 'package:fpdart/fpdart.dart'; class ProjectDtoMapper { diff --git a/backend-dart/lib/application/service/mapper/project_task_dto_mapper.dart b/backend-dart/lib/application/service/mapper/project_task_dto_mapper.dart index 1c1db96..cafe51e 100644 --- a/backend-dart/lib/application/service/mapper/project_task_dto_mapper.dart +++ b/backend-dart/lib/application/service/mapper/project_task_dto_mapper.dart @@ -1,6 +1,6 @@ import 'package:backend_dart/application/service/dto/project_task_dto.dart'; import 'package:backend_dart/domain/entities/project_task.dart'; -import 'package:backend_dart/domain/interface/error.dart'; +import 'package:backend_dart/domain/errors/error.dart'; import 'package:fpdart/fpdart.dart'; class ProjectTaskDtoMapper { diff --git a/backend-dart/lib/application/service/mapper/time_entry_dto_mapper.dart b/backend-dart/lib/application/service/mapper/time_entry_dto_mapper.dart index 39c6017..bd76dee 100644 --- a/backend-dart/lib/application/service/mapper/time_entry_dto_mapper.dart +++ b/backend-dart/lib/application/service/mapper/time_entry_dto_mapper.dart @@ -1,6 +1,6 @@ import 'package:backend_dart/application/service/dto/time_entry_dto.dart'; import 'package:backend_dart/domain/entities/time_entry.dart'; -import 'package:backend_dart/domain/interface/error.dart'; +import 'package:backend_dart/domain/errors/error.dart'; import 'package:fpdart/fpdart.dart'; class TimeEntryDtoMapper { diff --git a/backend-dart/lib/application/service/mapper/user_dto_mapper.dart b/backend-dart/lib/application/service/mapper/user_dto_mapper.dart index 46f293d..ea821ad 100644 --- a/backend-dart/lib/application/service/mapper/user_dto_mapper.dart +++ b/backend-dart/lib/application/service/mapper/user_dto_mapper.dart @@ -1,6 +1,6 @@ import 'package:backend_dart/application/service/dto/user_dto.dart'; import 'package:backend_dart/domain/entities/user.dart'; -import 'package:backend_dart/domain/interface/error.dart'; +import 'package:backend_dart/domain/errors/error.dart'; import 'package:fpdart/fpdart.dart'; class UserDtoMapper { diff --git a/backend-dart/lib/application/service/service_provider.dart b/backend-dart/lib/application/service/service_provider.dart index 25115e5..b1640d8 100644 --- a/backend-dart/lib/application/service/service_provider.dart +++ b/backend-dart/lib/application/service/service_provider.dart @@ -1,4 +1,5 @@ import 'package:backend_dart/application/repository/provider.dart'; +import 'package:backend_dart/application/service/auth_service.dart'; import 'package:backend_dart/application/service/project_service.dart'; import 'package:backend_dart/application/service/project_task_service.dart'; import 'package:backend_dart/application/service/time_entry_service.dart'; @@ -24,3 +25,9 @@ final timeEntryServiceProvider = Provider((ref) { final database = ref.read(timeEntryProvider); return TimeEntryService(database); }); + +final authServiceProvider = Provider((ref) { + final authRepository = ref.read(authProvider); + final users = ref.read(userRepoProvider); + return AuthService(authRepository, users); +}); diff --git a/backend-dart/lib/common/error_on_null.dart b/backend-dart/lib/common/error_on_null.dart index c8ddfd9..18eb676 100644 --- a/backend-dart/lib/common/error_on_null.dart +++ b/backend-dart/lib/common/error_on_null.dart @@ -1,4 +1,4 @@ -import 'package:backend_dart/domain/interface/error.dart'; +import 'package:backend_dart/domain/errors/error.dart'; import 'package:fpdart/fpdart.dart'; TaskEither Function(T?) errorOnNull(IError error) { diff --git a/backend-dart/lib/common/request_helper.dart b/backend-dart/lib/common/request_helper.dart index 36ed344..d2b7c2d 100644 --- a/backend-dart/lib/common/request_helper.dart +++ b/backend-dart/lib/common/request_helper.dart @@ -2,7 +2,7 @@ import 'dart:convert'; import 'dart:core'; import 'package:backend_dart/domain/errors/app_error.dart'; -import 'package:backend_dart/domain/interface/error.dart'; +import 'package:backend_dart/domain/errors/error.dart'; import 'package:fpdart/fpdart.dart'; import 'package:shelf/shelf.dart'; diff --git a/backend-dart/lib/common/response_helpers.dart b/backend-dart/lib/common/response_helpers.dart index 358556c..79bb197 100644 --- a/backend-dart/lib/common/response_helpers.dart +++ b/backend-dart/lib/common/response_helpers.dart @@ -1,6 +1,6 @@ import 'dart:convert'; import 'package:backend_dart/domain/errors/error_code.dart'; -import 'package:backend_dart/domain/interface/error.dart'; +import 'package:backend_dart/domain/errors/error.dart'; import 'package:fpdart/fpdart.dart'; import 'package:shelf/shelf.dart'; diff --git a/backend-dart/lib/domain/data/project_data_source.dart b/backend-dart/lib/domain/data/project_data_source.dart index 78b0423..b2c0321 100644 --- a/backend-dart/lib/domain/data/project_data_source.dart +++ b/backend-dart/lib/domain/data/project_data_source.dart @@ -1,5 +1,5 @@ import 'package:backend_dart/domain/entities/project.dart'; -import 'package:backend_dart/domain/interface/error.dart'; +import 'package:backend_dart/domain/errors/error.dart'; import 'package:fpdart/fpdart.dart'; /// Interface for managing project data interactions. diff --git a/backend-dart/lib/domain/data/project_task_data_source.dart b/backend-dart/lib/domain/data/project_task_data_source.dart index 42db459..d703a51 100644 --- a/backend-dart/lib/domain/data/project_task_data_source.dart +++ b/backend-dart/lib/domain/data/project_task_data_source.dart @@ -1,5 +1,5 @@ import 'package:backend_dart/domain/entities/project_task.dart'; -import 'package:backend_dart/domain/interface/error.dart'; +import 'package:backend_dart/domain/errors/error.dart'; import 'package:fpdart/fpdart.dart'; /// Interface for managing task data interactions. diff --git a/backend-dart/lib/domain/data/time_entry_data_source.dart b/backend-dart/lib/domain/data/time_entry_data_source.dart index 3e72ffa..d306d15 100644 --- a/backend-dart/lib/domain/data/time_entry_data_source.dart +++ b/backend-dart/lib/domain/data/time_entry_data_source.dart @@ -1,5 +1,5 @@ import 'package:backend_dart/domain/entities/time_entry.dart'; -import 'package:backend_dart/domain/interface/error.dart'; +import 'package:backend_dart/domain/errors/error.dart'; import 'package:fpdart/fpdart.dart'; /// Interface for managing time entry data interactions. diff --git a/backend-dart/lib/domain/data/user_data_source.dart b/backend-dart/lib/domain/data/user_data_source.dart index b497746..021fd63 100644 --- a/backend-dart/lib/domain/data/user_data_source.dart +++ b/backend-dart/lib/domain/data/user_data_source.dart @@ -1,5 +1,5 @@ import 'package:backend_dart/domain/entities/user.dart'; -import 'package:backend_dart/domain/interface/error.dart'; +import 'package:backend_dart/domain/errors/error.dart'; import 'package:fpdart/fpdart.dart'; abstract class UserDataSource { diff --git a/backend-dart/lib/domain/errors/app_error.dart b/backend-dart/lib/domain/errors/app_error.dart index 0ea4fc6..5cd61ab 100644 --- a/backend-dart/lib/domain/errors/app_error.dart +++ b/backend-dart/lib/domain/errors/app_error.dart @@ -1,4 +1,4 @@ -import 'package:backend_dart/domain/interface/error.dart'; +import 'package:backend_dart/domain/errors/error.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; import 'error_code.dart'; @@ -48,4 +48,8 @@ class AppError with _$AppError implements IError { factory AppError.inputError({String? message}) { return AppError.fromErrorCode(ErrorCode.inputError, message: message); } + + factory AppError.authenticationError({String? message}) { + return AppError.fromErrorCode(ErrorCode.authenticationError, message: message); + } } diff --git a/backend-dart/lib/domain/interface/error.dart b/backend-dart/lib/domain/errors/error.dart similarity index 100% rename from backend-dart/lib/domain/interface/error.dart rename to backend-dart/lib/domain/errors/error.dart diff --git a/backend-dart/lib/domain/errors/error_code.dart b/backend-dart/lib/domain/errors/error_code.dart index fa75d72..a36141c 100644 --- a/backend-dart/lib/domain/errors/error_code.dart +++ b/backend-dart/lib/domain/errors/error_code.dart @@ -3,6 +3,7 @@ enum ErrorCode { validationError, // Eingabevalidierungsfehler unexpectedError, // Unerwarteter Fehler authenticationError, // Authentifizierungsfehler + authorizationError, // Autorisierungsfehler permissionDenied, // Berechtigungsfehler notFound, // Ressource nicht gefunden exception, // Ausnahme diff --git a/backend-dart/lib/domain/interface/mapper.dart b/backend-dart/lib/domain/interface/mapper.dart deleted file mode 100644 index 8cffc2a..0000000 --- a/backend-dart/lib/domain/interface/mapper.dart +++ /dev/null @@ -1,16 +0,0 @@ -import 'package:backend_dart/domain/interface/error.dart'; -import 'package:fpdart/fpdart.dart'; - -abstract class IMapper { - /// Konvertiert von Typ U (Origin) zu Typ V (Target) - TaskEither to(U origin); - - /// Konvertiert von Typ V (Target) zu Typ U (Origin) - TaskEither from(V target); - - /// Konvertiert eine Liste von Typ U (Origin) zu einer Liste von Typ V (Target) - TaskEither> listTo(Iterable origins); - - /// Konvertiert eine Liste von Typ V (Target) zu einer Liste von Typ U (Origin) - TaskEither> listFrom(Iterable targets); -} diff --git a/backend-dart/lib/domain/repository/auth_repository.dart b/backend-dart/lib/domain/repository/auth_repository.dart new file mode 100644 index 0000000..e85c907 --- /dev/null +++ b/backend-dart/lib/domain/repository/auth_repository.dart @@ -0,0 +1,8 @@ +import 'package:backend_dart/domain/errors/error.dart'; +import 'package:fpdart/fpdart.dart'; + +abstract class AuthRepository { + TaskEither generateToken(String userId); + TaskEither validateToken(String token); + TaskEither revokeToken(String token); +} diff --git a/backend-dart/lib/domain/repository/project_repository.dart b/backend-dart/lib/domain/repository/project_repository.dart index 7a0721e..22e6236 100644 --- a/backend-dart/lib/domain/repository/project_repository.dart +++ b/backend-dart/lib/domain/repository/project_repository.dart @@ -1,6 +1,6 @@ import 'package:fpdart/fpdart.dart'; import 'package:backend_dart/domain/entities/project.dart'; -import 'package:backend_dart/domain/interface/error.dart'; +import 'package:backend_dart/domain/errors/error.dart'; abstract class ProjectRepository { /// Creates a new project. diff --git a/backend-dart/lib/domain/repository/project_task_repository.dart b/backend-dart/lib/domain/repository/project_task_repository.dart index df534ad..445047c 100644 --- a/backend-dart/lib/domain/repository/project_task_repository.dart +++ b/backend-dart/lib/domain/repository/project_task_repository.dart @@ -1,6 +1,6 @@ import 'package:fpdart/fpdart.dart'; import 'package:backend_dart/domain/entities/project_task.dart'; -import 'package:backend_dart/domain/interface/error.dart'; +import 'package:backend_dart/domain/errors/error.dart'; abstract class ProjectTaskRepository { /// Creates a new project task. diff --git a/backend-dart/lib/domain/repository/time_entry_repository.dart b/backend-dart/lib/domain/repository/time_entry_repository.dart index cb1279e..3ec16da 100644 --- a/backend-dart/lib/domain/repository/time_entry_repository.dart +++ b/backend-dart/lib/domain/repository/time_entry_repository.dart @@ -1,6 +1,6 @@ import 'package:fpdart/fpdart.dart'; import 'package:backend_dart/domain/entities/time_entry.dart'; -import 'package:backend_dart/domain/interface/error.dart'; +import 'package:backend_dart/domain/errors/error.dart'; abstract class TimeEntryRepository { /// Creates a new time entry. diff --git a/backend-dart/lib/domain/repository/user_repository.dart b/backend-dart/lib/domain/repository/user_repository.dart index 083e181..b8a47a8 100755 --- a/backend-dart/lib/domain/repository/user_repository.dart +++ b/backend-dart/lib/domain/repository/user_repository.dart @@ -1,5 +1,5 @@ import 'package:backend_dart/domain/entities/user.dart'; -import 'package:backend_dart/domain/interface/error.dart'; +import 'package:backend_dart/domain/errors/error.dart'; import 'package:fpdart/fpdart.dart'; abstract class UserRepository { diff --git a/backend-dart/lib/infrastructure/persistence/mapper/project_dbo_mapper.dart b/backend-dart/lib/infrastructure/persistence/mapper/project_dbo_mapper.dart index ff1cae1..8cf90ad 100644 --- a/backend-dart/lib/infrastructure/persistence/mapper/project_dbo_mapper.dart +++ b/backend-dart/lib/infrastructure/persistence/mapper/project_dbo_mapper.dart @@ -1,6 +1,6 @@ import 'package:backend_dart/common/extensions.dart'; import 'package:backend_dart/domain/entities/project.dart'; -import 'package:backend_dart/domain/interface/error.dart'; +import 'package:backend_dart/domain/errors/error.dart'; import 'package:backend_dart/infrastructure/persistence/db/model.dart'; import 'package:backend_dart/infrastructure/persistence/db/prisma.dart'; import 'package:fpdart/fpdart.dart'; diff --git a/backend-dart/lib/infrastructure/persistence/mapper/project_task_dbo_mapper.dart b/backend-dart/lib/infrastructure/persistence/mapper/project_task_dbo_mapper.dart index 3425def..05fc638 100644 --- a/backend-dart/lib/infrastructure/persistence/mapper/project_task_dbo_mapper.dart +++ b/backend-dart/lib/infrastructure/persistence/mapper/project_task_dbo_mapper.dart @@ -1,6 +1,6 @@ import 'package:backend_dart/common/extensions.dart'; import 'package:backend_dart/domain/entities/project_task.dart'; -import 'package:backend_dart/domain/interface/error.dart'; +import 'package:backend_dart/domain/errors/error.dart'; import 'package:backend_dart/infrastructure/persistence/db/model.dart'; import 'package:backend_dart/infrastructure/persistence/db/prisma.dart'; import 'package:fpdart/fpdart.dart'; diff --git a/backend-dart/lib/infrastructure/persistence/mapper/time_entry_dbo_mapper.dart b/backend-dart/lib/infrastructure/persistence/mapper/time_entry_dbo_mapper.dart index 9afe474..4ef9d92 100644 --- a/backend-dart/lib/infrastructure/persistence/mapper/time_entry_dbo_mapper.dart +++ b/backend-dart/lib/infrastructure/persistence/mapper/time_entry_dbo_mapper.dart @@ -1,6 +1,6 @@ import 'package:backend_dart/common/extensions.dart'; import 'package:backend_dart/domain/entities/time_entry.dart'; -import 'package:backend_dart/domain/interface/error.dart'; +import 'package:backend_dart/domain/errors/error.dart'; import 'package:backend_dart/infrastructure/persistence/db/model.dart'; import 'package:backend_dart/infrastructure/persistence/db/prisma.dart'; import 'package:fpdart/fpdart.dart'; diff --git a/backend-dart/lib/infrastructure/persistence/mapper/user_dbo_mapper.dart b/backend-dart/lib/infrastructure/persistence/mapper/user_dbo_mapper.dart index 6f6a8cf..d5ca68f 100644 --- a/backend-dart/lib/infrastructure/persistence/mapper/user_dbo_mapper.dart +++ b/backend-dart/lib/infrastructure/persistence/mapper/user_dbo_mapper.dart @@ -1,7 +1,7 @@ import 'package:backend_dart/common/extensions.dart'; import 'package:backend_dart/common/secure_hash.dart'; import 'package:backend_dart/domain/entities/user.dart'; -import 'package:backend_dart/domain/interface/error.dart'; +import 'package:backend_dart/domain/errors/error.dart'; import 'package:backend_dart/infrastructure/persistence/db/model.dart'; import 'package:backend_dart/infrastructure/persistence/db/prisma.dart'; import 'package:fpdart/fpdart.dart'; diff --git a/backend-dart/lib/infrastructure/persistence/prisma_project_data_source.dart b/backend-dart/lib/infrastructure/persistence/prisma_project_data_source.dart index 4028152..6103aaa 100644 --- a/backend-dart/lib/infrastructure/persistence/prisma_project_data_source.dart +++ b/backend-dart/lib/infrastructure/persistence/prisma_project_data_source.dart @@ -2,7 +2,7 @@ import 'package:backend_dart/common/error_on_null.dart'; import 'package:backend_dart/domain/data/project_data_source.dart'; import 'package:backend_dart/domain/entities/project.dart'; import 'package:backend_dart/domain/errors/app_error.dart'; -import 'package:backend_dart/domain/interface/error.dart'; +import 'package:backend_dart/domain/errors/error.dart'; import 'package:backend_dart/infrastructure/persistence/db/client.dart'; import 'package:backend_dart/infrastructure/persistence/db/model.dart'; import 'package:backend_dart/infrastructure/persistence/db/prisma.dart'; diff --git a/backend-dart/lib/infrastructure/persistence/prisma_project_task_data_source.dart b/backend-dart/lib/infrastructure/persistence/prisma_project_task_data_source.dart index d33633c..392a5b5 100644 --- a/backend-dart/lib/infrastructure/persistence/prisma_project_task_data_source.dart +++ b/backend-dart/lib/infrastructure/persistence/prisma_project_task_data_source.dart @@ -2,7 +2,7 @@ import 'package:backend_dart/common/error_on_null.dart'; import 'package:backend_dart/domain/data/project_task_data_source.dart'; import 'package:backend_dart/domain/entities/project_task.dart'; import 'package:backend_dart/domain/errors/app_error.dart'; -import 'package:backend_dart/domain/interface/error.dart'; +import 'package:backend_dart/domain/errors/error.dart'; import 'package:backend_dart/infrastructure/persistence/db/client.dart'; import 'package:backend_dart/infrastructure/persistence/db/model.dart'; import 'package:backend_dart/infrastructure/persistence/db/prisma.dart'; diff --git a/backend-dart/lib/infrastructure/persistence/prisma_time_entry_data_source.dart b/backend-dart/lib/infrastructure/persistence/prisma_time_entry_data_source.dart index cece960..bfb4f97 100644 --- a/backend-dart/lib/infrastructure/persistence/prisma_time_entry_data_source.dart +++ b/backend-dart/lib/infrastructure/persistence/prisma_time_entry_data_source.dart @@ -2,7 +2,7 @@ import 'package:backend_dart/common/error_on_null.dart'; import 'package:backend_dart/domain/data/time_entry_data_source.dart'; import 'package:backend_dart/domain/entities/time_entry.dart'; import 'package:backend_dart/domain/errors/app_error.dart'; -import 'package:backend_dart/domain/interface/error.dart'; +import 'package:backend_dart/domain/errors/error.dart'; import 'package:backend_dart/infrastructure/persistence/db/client.dart'; import 'package:backend_dart/infrastructure/persistence/db/model.dart'; import 'package:backend_dart/infrastructure/persistence/db/prisma.dart'; diff --git a/backend-dart/lib/infrastructure/persistence/prisma_user_data_source.dart b/backend-dart/lib/infrastructure/persistence/prisma_user_data_source.dart index ff4f404..f5c44d6 100755 --- a/backend-dart/lib/infrastructure/persistence/prisma_user_data_source.dart +++ b/backend-dart/lib/infrastructure/persistence/prisma_user_data_source.dart @@ -2,7 +2,7 @@ import 'package:backend_dart/common/error_on_null.dart'; import 'package:backend_dart/domain/data/user_data_source.dart'; import 'package:backend_dart/domain/entities/user.dart'; import 'package:backend_dart/domain/errors/app_error.dart'; -import 'package:backend_dart/domain/interface/error.dart'; +import 'package:backend_dart/domain/errors/error.dart'; import 'package:backend_dart/infrastructure/persistence/db/model.dart'; import 'package:backend_dart/infrastructure/persistence/db/prisma.dart'; import 'package:backend_dart/infrastructure/persistence/mapper/user_dbo_mapper.dart'; diff --git a/backend-dart/lib/interfaces/http/router.dart b/backend-dart/lib/interfaces/http/router.dart index 4b235a8..d4596c1 100644 --- a/backend-dart/lib/interfaces/http/router.dart +++ b/backend-dart/lib/interfaces/http/router.dart @@ -20,12 +20,14 @@ Router getRouter(ProviderContainer container) { final projectService = container.read(projectServiceProvider); final projectTaskService = container.read(projectTaskServiceProvider); final timeEntryService = container.read(timeEntryServiceProvider); + final authService = container.read(authServiceProvider); // UserService-Router router.mount('/api/users/', userService.router.call); router.mount('/api/projects/', projectService.router.call); router.mount('/api/project-tasks/', projectTaskService.router.call); router.mount('/api/time-entries/', timeEntryService.router.call); + router.mount('/api/auth/', authService.router.call); return router; } diff --git a/backend-dart/pubspec.lock b/backend-dart/pubspec.lock index c6915f8..b5b2fc5 100755 --- a/backend-dart/pubspec.lock +++ b/backend-dart/pubspec.lock @@ -14,6 +14,14 @@ packages: description: dart source: sdk version: "0.3.3" + adaptive_number: + dependency: transitive + description: + name: adaptive_number + sha256: "3a567544e9b5c9c803006f51140ad544aedc79604fd4f3f2c1380003f97c1d77" + url: "https://pub.dev" + source: hosted + version: "1.0.0" analyzer: dependency: transitive description: @@ -238,6 +246,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.0.0+6.11.0" + dart_jsonwebtoken: + dependency: "direct main" + description: + name: dart_jsonwebtoken + sha256: "866787dc17afaef46a9ea7dd33eefe60c6d82084b4a36d70e8e788d091cd04ef" + url: "https://pub.dev" + source: hosted + version: "2.14.2" dart_style: dependency: transitive description: @@ -254,6 +270,14 @@ packages: url: "https://pub.dev" source: hosted version: "3.0.2" + ed25519_edwards: + dependency: transitive + description: + name: ed25519_edwards + sha256: "6ce0112d131327ec6d42beede1e5dfd526069b18ad45dcf654f15074ad9276cd" + url: "https://pub.dev" + source: hosted + version: "0.3.1" file: dependency: transitive description: @@ -478,6 +502,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.9.1" + pointycastle: + dependency: transitive + description: + name: pointycastle + sha256: "4be0097fcf3fd3e8449e53730c631200ebc7b88016acecab2b0da2f0149222fe" + url: "https://pub.dev" + source: hosted + version: "3.9.1" pool: dependency: transitive description: diff --git a/backend-dart/pubspec.yaml b/backend-dart/pubspec.yaml index e99c0e1..973101c 100755 --- a/backend-dart/pubspec.yaml +++ b/backend-dart/pubspec.yaml @@ -22,6 +22,7 @@ dependencies: freezed_annotation: ^2.4.4 uuid: ^4.5.1 crypto: ^3.0.6 + dart_jsonwebtoken: ^2.14.2 dev_dependencies: lints: ^3.0.0 diff --git a/backend-go/cmd/actatempus/main.go b/backend-go/cmd/actatempus/main.go index 6e02541..f19816e 100755 --- a/backend-go/cmd/actatempus/main.go +++ b/backend-go/cmd/actatempus/main.go @@ -28,7 +28,7 @@ func main() { projectRepo := repository.NewProjectRepository(database.Projects()) projectTaskRepo := repository.NewProjectTaskRepository(database.ProjectTasks()) timeEntryRepo := repository.NewTimeEntryRepository(database.TimeEntries()) - authRepo := repository.NewInMemoryAuthRepository("secret") + authRepo := repository.NewInMemoryAuthRepositoryImpl("secret") // Initialize services userService := services.NewUserService(userRepo) diff --git a/backend-go/internal/application/repository/in_memory_auth_repository.go b/backend-go/internal/application/repository/in_memory_auth_repository_impl.go similarity index 97% rename from backend-go/internal/application/repository/in_memory_auth_repository.go rename to backend-go/internal/application/repository/in_memory_auth_repository_impl.go index 547b348..690833c 100644 --- a/backend-go/internal/application/repository/in_memory_auth_repository.go +++ b/backend-go/internal/application/repository/in_memory_auth_repository_impl.go @@ -19,7 +19,7 @@ type InMemoryAuthRepository struct { mu sync.RWMutex } -func NewInMemoryAuthRepository(secretKey string) repository.AuthRepository { +func NewInMemoryAuthRepositoryImpl(secretKey string) repository.AuthRepository { return &InMemoryAuthRepository{ secretKey: secretKey, sessionCache: make(map[string]string),