feat: applied auth wirth session token on dart backend
This commit is contained in:
parent
55edac6abe
commit
e9221f36ef
@ -1,11 +1,14 @@
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:backend_dart/application/service/dto/auth_dto.dart';
|
||||
import 'package:backend_dart/application/service/helper.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/errors/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';
|
||||
@ -37,20 +40,28 @@ class AuthService {
|
||||
),
|
||||
),
|
||||
)
|
||||
.flatMap((user) => authRepository.generateToken(user.id).map((token) =>
|
||||
TokenResponseDTO(token: token, userId: user.id).toJson()))
|
||||
.map(jsonEncode)
|
||||
.toResponse()
|
||||
.flatMap((user) => authRepository.generateToken(user.id).map(
|
||||
(token) => Response.ok(
|
||||
jsonEncode(
|
||||
TokenResponseDTO(token: token, userId: user.id).toJson(),
|
||||
),
|
||||
headers: {
|
||||
'Set-Cookie':
|
||||
'session_token=$token; HttpOnly; Path=/, user_id=${user.id}; HttpOnly; Path=/',
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
),
|
||||
))
|
||||
.getOrElse(ResponseHelpers.fromError)
|
||||
.run();
|
||||
}
|
||||
|
||||
/// Route to validate a token
|
||||
@Route.post('/validate')
|
||||
Future<Response> validateToken(Request request) async {
|
||||
return requestToJson(request)
|
||||
.flatMap(validateJsonKeys(['token']))
|
||||
.flatMap((json) => decodeJson(json, TokenRequestDTO.fromJson))
|
||||
.map((tokenRequest) => tokenRequest.token)
|
||||
return readCookie(request, 'session_token')
|
||||
.toTaskEither<IError>(() => AppError.authenticationError(
|
||||
message: 'No token found in the request'))
|
||||
.flatMap((token) => authRepository.validateToken(token).map((userId) =>
|
||||
TokenResponseDTO(token: token, userId: userId).toJson()))
|
||||
.map(jsonEncode)
|
||||
@ -61,14 +72,20 @@ class AuthService {
|
||||
/// Route to revoke a token
|
||||
@Route.post('/logout')
|
||||
Future<Response> logout(Request request) async {
|
||||
return requestToJson(request)
|
||||
.flatMap(validateJsonKeys(['token']))
|
||||
.flatMap((json) => decodeJson(json, TokenRequestDTO.fromJson))
|
||||
.map((tokenRequest) => tokenRequest.token)
|
||||
return readCookie(request, 'session_token')
|
||||
.toTaskEither<IError>(() => AppError.authenticationError(
|
||||
message: 'No token found in the request'))
|
||||
.flatMap(authRepository.revokeToken)
|
||||
.map((_) => {'message': 'Token revoked successfully'})
|
||||
.map(jsonEncode)
|
||||
.toResponse()
|
||||
.map((_) => Response.ok(
|
||||
jsonEncode({'message': 'Token revoked successfully'}),
|
||||
headers: {
|
||||
// Clear cookies by setting Max-Age to 0
|
||||
'Set-Cookie':
|
||||
'session_token=; Max-Age=0; HttpOnly; Path=/, user_id=; Max-Age=0; HttpOnly; Path=/',
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
))
|
||||
.getOrElse(ResponseHelpers.fromError)
|
||||
.run();
|
||||
}
|
||||
|
||||
|
@ -16,18 +16,6 @@ class TokenResponseDTO with _$TokenResponseDTO {
|
||||
_$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<String, dynamic> json) =>
|
||||
_$TokenRequestDTOFromJson(json);
|
||||
}
|
||||
|
||||
/// LoginRequestDTO represents the login request.
|
||||
@freezed
|
||||
class LoginRequestDTO with _$LoginRequestDTO {
|
||||
|
@ -182,157 +182,6 @@ abstract class _TokenResponseDTO implements TokenResponseDTO {
|
||||
throw _privateConstructorUsedError;
|
||||
}
|
||||
|
||||
TokenRequestDTO _$TokenRequestDTOFromJson(Map<String, dynamic> json) {
|
||||
return _TokenRequestDTO.fromJson(json);
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
mixin _$TokenRequestDTO {
|
||||
String get token => throw _privateConstructorUsedError;
|
||||
|
||||
/// Serializes this TokenRequestDTO to a JSON map.
|
||||
Map<String, dynamic> 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<TokenRequestDTO> 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<String, dynamic> 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<String, dynamic> toJson() {
|
||||
return _$$TokenRequestDTOImplToJson(
|
||||
this,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
abstract class _TokenRequestDTO implements TokenRequestDTO {
|
||||
const factory _TokenRequestDTO({required final String token}) =
|
||||
_$TokenRequestDTOImpl;
|
||||
|
||||
factory _TokenRequestDTO.fromJson(Map<String, dynamic> 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<String, dynamic> json) {
|
||||
return _LoginRequestDTO.fromJson(json);
|
||||
}
|
||||
|
@ -20,18 +20,6 @@ Map<String, dynamic> _$$TokenResponseDTOImplToJson(
|
||||
'userId': instance.userId,
|
||||
};
|
||||
|
||||
_$TokenRequestDTOImpl _$$TokenRequestDTOImplFromJson(
|
||||
Map<String, dynamic> json) =>
|
||||
_$TokenRequestDTOImpl(
|
||||
token: json['token'] as String,
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$$TokenRequestDTOImplToJson(
|
||||
_$TokenRequestDTOImpl instance) =>
|
||||
<String, dynamic>{
|
||||
'token': instance.token,
|
||||
};
|
||||
|
||||
_$LoginRequestDTOImpl _$$LoginRequestDTOImplFromJson(
|
||||
Map<String, dynamic> json) =>
|
||||
_$LoginRequestDTOImpl(
|
||||
|
33
backend-dart/lib/application/service/helper.dart
Normal file
33
backend-dart/lib/application/service/helper.dart
Normal file
@ -0,0 +1,33 @@
|
||||
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:fpdart/fpdart.dart';
|
||||
import 'package:shelf/shelf.dart';
|
||||
|
||||
TaskOption<String> readCookie(Request request, String cookieName) {
|
||||
// Retrieve the "Cookie" header
|
||||
final cookieHeader = request.headers['cookie'];
|
||||
if (cookieHeader == null) return TaskOption.none();
|
||||
// No cookies found
|
||||
|
||||
// Split the cookies into individual key-value pairs
|
||||
final cookies = cookieHeader.split(';');
|
||||
|
||||
// Find the cookie with the matching name
|
||||
for (var cookie in cookies) {
|
||||
final parts = cookie.trim().split('=');
|
||||
if (parts.length == 2 && parts[0] == cookieName && parts[1].isNotEmpty) {
|
||||
return TaskOption.some(parts[1]);
|
||||
}
|
||||
}
|
||||
|
||||
return TaskOption.none(); // Cookie not found
|
||||
}
|
||||
|
||||
TaskEither<IError, String> checkAuth(
|
||||
Request request, AuthRepository authRepository) {
|
||||
return readCookie(request, 'session_token')
|
||||
.toTaskEither<IError>(() => AppError.authenticationError(
|
||||
message: 'No token found in the request'))
|
||||
.flatMap(authRepository.validateToken);
|
||||
}
|
@ -1,10 +1,12 @@
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:backend_dart/application/service/dto/project_dto.dart';
|
||||
import 'package:backend_dart/application/service/helper.dart';
|
||||
import 'package:backend_dart/application/service/mapper/project_dto_mapper.dart';
|
||||
import 'package:backend_dart/common/request_helper.dart';
|
||||
import 'package:backend_dart/common/response_helpers.dart';
|
||||
import 'package:backend_dart/common/validation.dart';
|
||||
import 'package:backend_dart/domain/repository/auth_repository.dart';
|
||||
import 'package:backend_dart/domain/repository/project_repository.dart';
|
||||
import 'package:shelf/shelf.dart';
|
||||
import 'package:shelf_router/shelf_router.dart';
|
||||
@ -13,13 +15,14 @@ part 'project_service.g.dart'; // generated with 'pub run build_runner build'
|
||||
|
||||
class ProjectService {
|
||||
final ProjectRepository projects;
|
||||
final AuthRepository authRepository;
|
||||
final ProjectDtoMapper mapper = ProjectDtoMapper();
|
||||
ProjectService(this.projects);
|
||||
ProjectService(this.projects, this.authRepository);
|
||||
|
||||
@Route.get('/')
|
||||
Future<Response> listProjects(Request request) async {
|
||||
return projects
|
||||
.findAll()
|
||||
return checkAuth(request, authRepository)
|
||||
.flatMap((_) => projects.findAll())
|
||||
.flatMap(mapper.listTo)
|
||||
.map((projects) => projects.map((project) => project.toJson()).toList())
|
||||
.map(jsonEncode)
|
||||
@ -29,8 +32,8 @@ class ProjectService {
|
||||
|
||||
@Route.get('/<projectId>')
|
||||
Future<Response> fetchProject(Request request, String projectId) async {
|
||||
return projects
|
||||
.findById(projectId)
|
||||
return checkAuth(request, authRepository)
|
||||
.flatMap((_) => projects.findById(projectId))
|
||||
.flatMap(mapper.to)
|
||||
.map((dto) => dto.toJson())
|
||||
.toResponse()
|
||||
@ -39,7 +42,8 @@ class ProjectService {
|
||||
|
||||
@Route.post('/')
|
||||
Future<Response> createProject(Request request) async {
|
||||
return requestToJson(request)
|
||||
return checkAuth(request, authRepository)
|
||||
.flatMap((_) => requestToJson(request))
|
||||
.flatMap(validateJsonKeys(['name', 'userId'])) // Add required fields
|
||||
.flatMap((json) => decodeJson(json, ProjectCreateDto.fromJson))
|
||||
.flatMap(mapper.fromCreateTo)
|
||||
@ -52,7 +56,8 @@ class ProjectService {
|
||||
|
||||
@Route.put('/<projectId>')
|
||||
Future<Response> updateProject(Request request, String projectId) async {
|
||||
return requestToJson(request)
|
||||
return checkAuth(request, authRepository)
|
||||
.flatMap((_) => requestToJson(request))
|
||||
.flatMap(validateJsonKeys([]))
|
||||
.flatMap((json) => decodeJson(json, ProjectUpdateDto.fromJson))
|
||||
.flatMap((dto) => mapper.fromUpdateTo(dto, projectId))
|
||||
@ -65,8 +70,8 @@ class ProjectService {
|
||||
|
||||
@Route.delete('/<projectId>')
|
||||
Future<Response> deleteProject(Request request, String projectId) async {
|
||||
return projects
|
||||
.delete(projectId)
|
||||
return checkAuth(request, authRepository)
|
||||
.flatMap((_) => projects.delete(projectId))
|
||||
.flatMap(mapper.to)
|
||||
.map((dto) => dto.toJson())
|
||||
.toResponse()
|
||||
|
@ -1,10 +1,12 @@
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:backend_dart/application/service/dto/project_task_dto.dart';
|
||||
import 'package:backend_dart/application/service/helper.dart';
|
||||
import 'package:backend_dart/application/service/mapper/project_task_dto_mapper.dart';
|
||||
import 'package:backend_dart/common/request_helper.dart';
|
||||
import 'package:backend_dart/common/response_helpers.dart';
|
||||
import 'package:backend_dart/common/validation.dart';
|
||||
import 'package:backend_dart/domain/repository/auth_repository.dart';
|
||||
import 'package:backend_dart/domain/repository/project_task_repository.dart';
|
||||
import 'package:shelf/shelf.dart';
|
||||
import 'package:shelf_router/shelf_router.dart';
|
||||
@ -13,13 +15,15 @@ part 'project_task_service.g.dart'; // Generated with 'pub run build_runner buil
|
||||
|
||||
class ProjectTaskService {
|
||||
final ProjectTaskRepository tasks;
|
||||
final AuthRepository authRepository;
|
||||
|
||||
final ProjectTaskDtoMapper mapper = ProjectTaskDtoMapper();
|
||||
ProjectTaskService(this.tasks);
|
||||
ProjectTaskService(this.tasks, this.authRepository);
|
||||
|
||||
@Route.get('/')
|
||||
Future<Response> listTasks(Request request) async {
|
||||
return tasks
|
||||
.findAll()
|
||||
return checkAuth(request, authRepository)
|
||||
.flatMap((_) => tasks.findAll())
|
||||
.flatMap(mapper.listTo)
|
||||
.map((tasks) => tasks.map((task) => task.toJson()).toList())
|
||||
.map(jsonEncode)
|
||||
@ -29,8 +33,8 @@ class ProjectTaskService {
|
||||
|
||||
@Route.get('/<taskId>')
|
||||
Future<Response> fetchTask(Request request, String taskId) async {
|
||||
return tasks
|
||||
.findById(taskId)
|
||||
return checkAuth(request, authRepository)
|
||||
.flatMap((_) => tasks.findById(taskId))
|
||||
.flatMap(mapper.to)
|
||||
.map((dto) => dto.toJson())
|
||||
.toResponse()
|
||||
@ -39,7 +43,8 @@ class ProjectTaskService {
|
||||
|
||||
@Route.post('/')
|
||||
Future<Response> createTask(Request request) async {
|
||||
return requestToJson(request)
|
||||
return checkAuth(request, authRepository)
|
||||
.flatMap((_) => requestToJson(request))
|
||||
.flatMap(validateJsonKeys(['name', 'projectId'])) // Add required fields
|
||||
.flatMap((json) => decodeJson(json, ProjectTaskCreateDto.fromJson))
|
||||
.flatMap(mapper.fromCreateTo)
|
||||
@ -52,7 +57,8 @@ class ProjectTaskService {
|
||||
|
||||
@Route.put('/<taskId>')
|
||||
Future<Response> updateTask(Request request, String taskId) async {
|
||||
return requestToJson(request)
|
||||
return checkAuth(request, authRepository)
|
||||
.flatMap((_) => requestToJson(request))
|
||||
.flatMap(validateJsonKeys([]))
|
||||
.flatMap((json) => decodeJson(json, ProjectTaskUpdateDto.fromJson))
|
||||
.flatMap((dto) => mapper.fromUpdateTo(dto, taskId))
|
||||
@ -65,8 +71,8 @@ class ProjectTaskService {
|
||||
|
||||
@Route.delete('/<taskId>')
|
||||
Future<Response> deleteTask(Request request, String taskId) async {
|
||||
return tasks
|
||||
.delete(taskId)
|
||||
return checkAuth(request, authRepository)
|
||||
.flatMap((_) => tasks.delete(taskId))
|
||||
.flatMap(mapper.to)
|
||||
.map((dto) => dto.toJson())
|
||||
.toResponse()
|
||||
|
@ -8,22 +8,26 @@ import 'package:riverpod/riverpod.dart';
|
||||
|
||||
final userServiceProvider = Provider<UserService>((ref) {
|
||||
final database = ref.read(userRepoProvider);
|
||||
return UserService(database);
|
||||
final authRepository = ref.read(authProvider);
|
||||
return UserService(database, authRepository);
|
||||
});
|
||||
|
||||
final projectServiceProvider = Provider<ProjectService>((ref) {
|
||||
final database = ref.read(projectProvider);
|
||||
return ProjectService(database);
|
||||
final authRepository = ref.read(authProvider);
|
||||
return ProjectService(database, authRepository);
|
||||
});
|
||||
|
||||
final projectTaskServiceProvider = Provider<ProjectTaskService>((ref) {
|
||||
final database = ref.read(projectTaskProvider);
|
||||
return ProjectTaskService(database);
|
||||
final authRepository = ref.read(authProvider);
|
||||
return ProjectTaskService(database, authRepository);
|
||||
});
|
||||
|
||||
final timeEntryServiceProvider = Provider<TimeEntryService>((ref) {
|
||||
final database = ref.read(timeEntryProvider);
|
||||
return TimeEntryService(database);
|
||||
final authRepository = ref.read(authProvider);
|
||||
return TimeEntryService(database, authRepository);
|
||||
});
|
||||
|
||||
final authServiceProvider = Provider<AuthService>((ref) {
|
||||
|
@ -1,10 +1,12 @@
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:backend_dart/application/service/dto/time_entry_dto.dart';
|
||||
import 'package:backend_dart/application/service/helper.dart';
|
||||
import 'package:backend_dart/application/service/mapper/time_entry_dto_mapper.dart';
|
||||
import 'package:backend_dart/common/request_helper.dart';
|
||||
import 'package:backend_dart/common/response_helpers.dart';
|
||||
import 'package:backend_dart/common/validation.dart';
|
||||
import 'package:backend_dart/domain/repository/auth_repository.dart';
|
||||
import 'package:backend_dart/domain/repository/time_entry_repository.dart';
|
||||
import 'package:shelf/shelf.dart';
|
||||
import 'package:shelf_router/shelf_router.dart';
|
||||
@ -13,13 +15,14 @@ part 'time_entry_service.g.dart'; // Generated with 'pub run build_runner build'
|
||||
|
||||
class TimeEntryService {
|
||||
final TimeEntryRepository entries;
|
||||
final AuthRepository authRepository;
|
||||
final TimeEntryDtoMapper mapper = TimeEntryDtoMapper();
|
||||
TimeEntryService(this.entries);
|
||||
TimeEntryService(this.entries, this.authRepository);
|
||||
|
||||
@Route.get('/')
|
||||
Future<Response> listEntries(Request request) async {
|
||||
return entries
|
||||
.findAll()
|
||||
return checkAuth(request, authRepository)
|
||||
.flatMap((_) => entries.findAll())
|
||||
.flatMap(mapper.listTo)
|
||||
.map((entries) => entries.map((entry) => entry.toJson()).toList())
|
||||
.map(jsonEncode)
|
||||
@ -29,8 +32,8 @@ class TimeEntryService {
|
||||
|
||||
@Route.get('/<entryId>')
|
||||
Future<Response> fetchEntry(Request request, String entryId) async {
|
||||
return entries
|
||||
.findById(entryId)
|
||||
return checkAuth(request, authRepository)
|
||||
.flatMap((_) => entries.findById(entryId))
|
||||
.flatMap(mapper.to)
|
||||
.map((dto) => dto.toJson())
|
||||
.toResponse()
|
||||
@ -39,7 +42,8 @@ class TimeEntryService {
|
||||
|
||||
@Route.post('/')
|
||||
Future<Response> createEntry(Request request) async {
|
||||
return requestToJson(request)
|
||||
return checkAuth(request, authRepository)
|
||||
.flatMap((_) => requestToJson(request))
|
||||
.flatMap(
|
||||
validateJsonKeys(['startTime', 'endTime', 'userId', 'projectId']))
|
||||
.flatMap((json) => decodeJson(json, TimeEntryCreateDto.fromJson))
|
||||
@ -53,7 +57,8 @@ class TimeEntryService {
|
||||
|
||||
@Route.put('/<entryId>')
|
||||
Future<Response> updateEntry(Request request, String entryId) async {
|
||||
return requestToJson(request)
|
||||
return checkAuth(request, authRepository)
|
||||
.flatMap((_) => requestToJson(request))
|
||||
.flatMap(validateJsonKeys([]))
|
||||
.flatMap((json) => decodeJson(json, TimeEntryUpdateDto.fromJson))
|
||||
.flatMap((dto) => mapper.fromUpdateTo(dto, entryId))
|
||||
@ -66,8 +71,8 @@ class TimeEntryService {
|
||||
|
||||
@Route.delete('/<entryId>')
|
||||
Future<Response> deleteEntry(Request request, String entryId) async {
|
||||
return entries
|
||||
.delete(entryId)
|
||||
return checkAuth(request, authRepository)
|
||||
.flatMap((_) => entries.delete(entryId))
|
||||
.map((dto) => dto.toJson())
|
||||
.toResponse()
|
||||
.run();
|
||||
|
@ -1,10 +1,12 @@
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:backend_dart/application/service/dto/user_dto.dart';
|
||||
import 'package:backend_dart/application/service/helper.dart';
|
||||
import 'package:backend_dart/application/service/mapper/user_dto_mapper.dart';
|
||||
import 'package:backend_dart/common/request_helper.dart';
|
||||
import 'package:backend_dart/common/response_helpers.dart';
|
||||
import 'package:backend_dart/common/validation.dart';
|
||||
import 'package:backend_dart/domain/repository/auth_repository.dart';
|
||||
import 'package:backend_dart/domain/repository/user_repository.dart';
|
||||
import 'package:shelf/shelf.dart';
|
||||
import 'package:shelf_router/shelf_router.dart';
|
||||
@ -13,13 +15,15 @@ part 'user_service.g.dart'; // generated with 'pub run build_runner build'
|
||||
|
||||
class UserService {
|
||||
final UserRepository users;
|
||||
final AuthRepository authRepository;
|
||||
|
||||
final UserDtoMapper mapper = UserDtoMapper();
|
||||
UserService(this.users);
|
||||
UserService(this.users, this.authRepository);
|
||||
|
||||
@Route.get('/')
|
||||
Future<Response> listUsers(Request request) async {
|
||||
return users
|
||||
.findAll()
|
||||
return checkAuth(request, authRepository)
|
||||
.flatMap((_) => users.findAll())
|
||||
.flatMap(mapper.listTo)
|
||||
.map((users) => users.map((user) => user.toJson()).toList())
|
||||
.map(jsonEncode)
|
||||
@ -29,8 +33,8 @@ class UserService {
|
||||
|
||||
@Route.get('/<userId>')
|
||||
Future<Response> fetchUser(Request request, String userId) async {
|
||||
return users
|
||||
.findById(userId)
|
||||
return checkAuth(request, authRepository)
|
||||
.flatMap((_) => users.findById(userId))
|
||||
.flatMap(mapper.to)
|
||||
.map((dto) => dto.toJson())
|
||||
.toResponse()
|
||||
@ -48,11 +52,22 @@ class UserService {
|
||||
.map((dto) => dto.toJson())
|
||||
.toResponse()
|
||||
.run();
|
||||
//return checkAuth(request, authRepository) // ignore auth for initial user creation
|
||||
// .flatMap((_) => requestToJson(request))
|
||||
// .flatMap(validateJsonKeys(['name', 'email', 'password']))
|
||||
// .flatMap((json) => decodeJson(json, UserCreateDto.fromJson))
|
||||
// .flatMap(mapper.fromCreateTo)
|
||||
// .flatMap(users.create)
|
||||
// .flatMap(mapper.to)
|
||||
// .map((dto) => dto.toJson())
|
||||
// .toResponse()
|
||||
// .run();
|
||||
}
|
||||
|
||||
@Route.put('/<userId>')
|
||||
Future<Response> updateUser(Request request, String userId) async {
|
||||
return requestToJson(request)
|
||||
return checkAuth(request, authRepository)
|
||||
.flatMap((_) => requestToJson(request))
|
||||
.flatMap(validateJsonKeys([]))
|
||||
.flatMap((json) => decodeJson(json, UserUpdateDto.fromJson))
|
||||
.flatMap((dto) => mapper.fromUpdateTo(dto, userId))
|
||||
@ -65,8 +80,8 @@ class UserService {
|
||||
|
||||
@Route.delete('/<userId>')
|
||||
Future<Response> deleteUser(Request request, String userId) async {
|
||||
return users
|
||||
.delete(userId)
|
||||
return checkAuth(request, authRepository)
|
||||
.flatMap((_) => users.delete(userId))
|
||||
.flatMap(mapper.to)
|
||||
.map((dto) => dto.toJson())
|
||||
.toResponse()
|
||||
|
@ -14,8 +14,8 @@ extension TaskEitherResponseExtensions
|
||||
|
||||
extension TaskEitherResponseExtensionsFromString on TaskEither<IError, String> {
|
||||
Task<Response> toResponse() => match(
|
||||
(left) => ResponseHelpers.fromError(left),
|
||||
(right) => Response.ok(right),
|
||||
ResponseHelpers.fromError,
|
||||
Response.ok,
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -106,15 +106,15 @@ func (s *AuthService) Logout(c *gin.Context) {
|
||||
|
||||
func setSessionTokenCookie(c *gin.Context, user entities.User) func(token string) string {
|
||||
return func(token string) string {
|
||||
c.SetCookie("session_token", token, 3600, "/", "localhost", false, true)
|
||||
c.SetCookie("user_id", user.ID, 3600, "/", "localhost", false, true)
|
||||
c.SetCookie("session_token", token, 3600, "/", "", false, true)
|
||||
c.SetCookie("user_id", user.ID, 3600, "/", "", false, true)
|
||||
return token
|
||||
}
|
||||
}
|
||||
|
||||
func deleteSessionTokenCookie(c *gin.Context) {
|
||||
c.SetCookie("session_token", "", -1, "/", "localhost", false, true)
|
||||
c.SetCookie("user_id", "", -1, "/", "localhost", false, true)
|
||||
c.SetCookie("session_token", "", -1, "/", "", false, true)
|
||||
c.SetCookie("user_id", "", -1, "/", "", false, true)
|
||||
}
|
||||
|
||||
func validatePassword(password string) func(user entities.User) E.Either[error, entities.User] {
|
||||
|
@ -3,7 +3,7 @@ package dto
|
||||
// TokenResponseDTO represents the response for a token generation or validation.
|
||||
type TokenResponseDTO struct {
|
||||
Token string `json:"token"`
|
||||
UserID string `json:"user_id"`
|
||||
UserID string `json:"userId"`
|
||||
}
|
||||
|
||||
// LoginRequestDTO represents the login request.
|
||||
|
Loading…
x
Reference in New Issue
Block a user