implemented user service (no auth!)

This commit is contained in:
2025-01-01 18:33:53 +00:00
parent 0ded723bb9
commit 8559b1c44e
34 changed files with 1437 additions and 158 deletions
@@ -1,13 +0,0 @@
import 'package:backend_dart/infrastructure/persistence/db/client.dart';
import 'package:backend_dart/infrastructure/persistence/prisma_user_repository.dart';
class Database {
final prisma = PrismaClient();
late final PrismaUserRepository users;
Database() {
users = PrismaUserRepository(prisma);
print('Database initialized');
}
}
@@ -1,8 +1,8 @@
import 'package:backend_dart/infrastructure/persistence/database.dart';
import 'package:backend_dart/infrastructure/persistence/prisma_database.dart';
import 'package:riverpod/riverpod.dart';
final databaseProvider = Provider<Database>((ref) {
final databaseProvider = Provider<PrismaDatabase>((ref) {
// Hier die Datenbankverbindung initialisieren
final database = Database();
final database = PrismaDatabase();
return database;
});
});
@@ -0,0 +1,37 @@
import 'package:backend_dart/domain/entities/user.dart';
import 'package:backend_dart/domain/interface/error.dart';
import 'package:backend_dart/domain/interface/mapper.dart';
import 'package:backend_dart/infrastructure/persistence/db/model.dart';
import 'package:fpdart/fpdart.dart';
class UserDboMapper implements IMapper<User, UserDbo> {
@override
TaskEither<IError, User> from(UserDbo target) => TaskEither.of(User(
id: target.id!,
name: target.name!,
email: target.email!,
password: target.password,
createdAt: target.createdAt,
updatedAt: target.updatedAt,
));
@override
TaskEither<IError, List<User>> listFrom(Iterable<UserDbo> targets) {
return TaskEither.traverseList(targets.toList(), from);
}
@override
TaskEither<IError, List<UserDbo>> listTo(Iterable<User> origins) {
return TaskEither.traverseList(origins.toList(), to);
}
@override
TaskEither<IError, UserDbo> to(User origin) => TaskEither.of(UserDbo(
id: origin.id,
name: origin.name,
email: origin.email,
password: origin.password,
createdAt: origin.createdAt,
updatedAt: origin.updatedAt,
));
}
@@ -0,0 +1,19 @@
import 'package:backend_dart/domain/interface/database.dart';
import 'package:backend_dart/infrastructure/persistence/db/client.dart';
import 'package:backend_dart/infrastructure/persistence/prisma_user_data_source.dart';
class PrismaDatabase implements IDatabase {
final prisma = PrismaClient();
late final PrismaUserDataSource _users;
PrismaDatabase() {
_users = PrismaUserDataSource(prisma);
print('Database initialized');
}
@override
get users => _users;
@override
Future<void> close() {
return Future.value();
}
}
@@ -0,0 +1,162 @@
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/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';
import 'package:fpdart/fpdart.dart';
import 'package:orm/orm.dart';
import 'package:uuid/uuid.dart';
import 'db/client.dart';
class PrismaUserDataSource implements UserDataSource<User> {
final PrismaClient prisma;
final UserDboMapper mapper = UserDboMapper();
PrismaUserDataSource(this.prisma);
@override
TaskEither<IError, User> create(User user) {
return TaskEither<IError, UserDbo>.tryCatch(
() async {
if (user.password == null) {
throw Exception('Password is required');
}
if (user.email == null) {
throw Exception('Email is required');
}
final createdUser = await prisma.userDbo.create(
data: PrismaUnion.$1(UserDboCreateInput(
id: user.id,
name: user.name!,
email: user.email!,
password: user.password!,
)),
);
return createdUser;
},
(error, _) => AppError.databaseError(
message: 'Failed to create user: ${error.toString()}',
),
).flatMap(mapper.from);
}
@override
TaskEither<IError, User> findByEmail(String email) {
return TaskEither<IError, UserDbo?>.tryCatch(
() async {
final user = await prisma.userDbo
.findUnique(where: UserDboWhereUniqueInput(email: email));
if (user == null) return null;
return user;
},
(error, _) => AppError.databaseError(
message: 'Failed to find user by email: ${error.toString()}',
),
)
.flatMap(errorOnNull(AppError.notFound(
'User with email $email found',
)))
.flatMap(mapper.from);
}
@override
TaskEither<IError, User> findById(String id) {
return TaskEither<IError, UserDbo?>.tryCatch(
() async {
final user = await prisma.userDbo
.findUnique(where: UserDboWhereUniqueInput(id: id));
return user;
},
(error, _) => AppError.databaseError(
message: 'Failed to find user by ID: ${error.toString()}',
),
)
.flatMap(errorOnNull(AppError.notFound(
"User with id $id not found",
)))
.flatMap(mapper.from);
}
@override
TaskEither<IError, User> update(User user) {
return mapper
.to(user)
.flatMap((userDbo) => TaskEither.tryCatch(() async {
// Führe das Update durch
if (userDbo.id == null) {
throw Exception('User ID is required');
}
final updatedUser = await prisma.userDbo.update(
data: PrismaUnion.$2(
UserDboUncheckedUpdateInput(
id: PrismaUnion.$1(userDbo.id!),
name: userDbo.name != null
? PrismaUnion.$1(userDbo.name!)
: null,
email: userDbo.email != null
? PrismaUnion.$1(userDbo.email!)
: null,
password: userDbo.password != null
? PrismaUnion.$1(userDbo.password!)
: null,
),
),
where: UserDboWhereUniqueInput(id: userDbo.id),
);
return updatedUser;
},
(error, _) => AppError.databaseError(
message: 'Failed to update user: ${error.toString()}',
)))
.flatMap(errorOnNull(AppError.notFound(
'User not found',
)))
.flatMap(mapper.from);
}
@override
TaskEither<IError, void> delete(String id) {
return TaskEither.tryCatch(
() async {
await prisma.userDbo.delete(where: UserDboWhereUniqueInput(id: id));
},
(error, _) => AppError.databaseError(
message: 'Failed to delete user: ${error.toString()}',
),
);
}
@override
TaskEither<IError, List<User>> findAll() {
return TaskEither<IError, Iterable<UserDbo>>.tryCatch(
() async => await prisma.userDbo.findMany(),
(error, _) => AppError.databaseError(
message: 'Failed to fetch all users: ${error.toString()}',
),
).flatMap(mapper.listFrom);
}
@override
TaskEither<IError, String> generateId() {
return TaskEither.tryCatch(
() async {
var uuid = Uuid();
do {
final id = uuid.v4();
final user = await prisma.userDbo.findUnique(
where: UserDboWhereUniqueInput(id: id),
);
if (user == null) return id;
} while (true);
},
(error, _) => AppError.databaseError(
message: 'Failed to generate ID: ${error.toString()}',
),
);
}
}
@@ -1,57 +0,0 @@
import 'package:backend_dart/domain/entities/user.dart';
import 'package:backend_dart/domain/repositories/user_repository.dart';
import 'package:backend_dart/infrastructure/persistence/db/prisma.dart';
import 'package:orm/orm.dart';
import 'db/client.dart';
class PrismaUserRepository implements UserRepository {
final PrismaClient prisma;
PrismaUserRepository(this.prisma);
@override
Future<void> create(User user) async {
if (user.password == null) {
throw Exception('Password is required');
}
prisma.userDbo.create(
data: PrismaUnion.$1(UserDboCreateInput(
id: user.id,
name: user.name,
email: user.email,
password: user.password!,
)));
}
@override
Future<User?> findByEmail(String email) async {
final user = await prisma.userDbo
.findUnique(where: UserDboWhereUniqueInput(email: email));
if (user == null) {
return null;
}
return User(
id: user.id!,
name: user.name!,
email: user.email!,
password: user.password,
);
}
@override
Future<User?> findById(String id) async {
final user =
await prisma.userDbo.findUnique(where: UserDboWhereUniqueInput(id: id));
if (user == null) {
return null;
}
return User(
id: user.id!,
name: user.name!,
email: user.email!,
password: user.password,
);
}
}