mnemo_cards/mnemo_cards_backend/lib/user/user_repository.dart
Dmitry a6abcfa7e6
Some checks failed
Backend CI / test (push) Waiting to run
Backend CI / build (push) Blocked by required conditions
Web App CI / test (push) Waiting to run
Web App CI / build (push) Blocked by required conditions
Deploy Mnemo Cards / Deploy Backend (push) Waiting to run
Deploy Mnemo Cards / Deploy Web App (push) Blocked by required conditions
Deploy Mnemo Cards / Final Verification (push) Blocked by required conditions
Mobile App CI / test (push) Has been cancelled
Deploy Telegram Bot / Deploy Telegram Bot (push) Has been cancelled
Mobile App CI / build-android (push) Has been cancelled
Mobile App CI / build-ios (push) Has been cancelled
repo
2026-01-08 19:07:56 +03:00

181 lines
5.8 KiB
Dart
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import 'package:drift/drift.dart';
import 'package:drift_postgres/drift_postgres.dart';
import 'package:injectable/injectable.dart';
import 'package:mnemo_cards_backend/database/database.dart';
import 'package:mnemo_cards_backend/packs/card_pack_drift_extension.dart';
import 'package:mnemo_cards_common_backend/mnemo_cards_common_backend.dart';
import 'user_drift_extension.dart';
/// Repository для работы с пользователями
/// Работает с доменными моделями (UserModel), использует DAO для доступа к БД
@lazySingleton
class UserRepository {
final AppDatabase _db;
UserRepository(this._db);
/// Получить пользователя по ID
/// [includePacks] - загружать ли связанные паки пользователя
Future<UserModel?> getUserById(
String id, {
bool includePacks = false,
}) async {
final user = await _db.userDao.getUserById(id);
if (user == null) return null;
if (includePacks) {
final packs = await _db.userDao.getUserPacks(id);
return await user.toUserModel(packs);
}
return await user.toUserModel();
}
/// Получить пользователя по email
Future<UserModel?> getUserByEmail(String email) async {
final user = await _db.userDao.getUserByEmail(email);
if (user == null) return null;
return await user.toUserModel();
}
/// Получить пользователя по externalUserId
Future<UserModel?> getUserByExternalId(String externalId) async {
final user = await _db.userDao.getUserByExternalId(externalId);
if (user == null) return null;
return await user.toUserModel();
}
/// Получить пользователя с UserData
Future<UserModel?> getUserWithDataById(String id) async {
final userWithData = await _db.userDao.getUserWithDataById(id);
if (userWithData == null) return null;
final packs = await _db.userDao.getUserPacks(id);
final userModel = await userWithData.user.toUserModel(packs);
// TODO: загрузить UserDataModel если нужно
// userModel.userData = userWithData.userData?.toUserDataModel();
return userModel;
}
/// Создать пользователя
Future<String> createUser(UserModel userModel) async {
final userCompanion = userModel.toUsersCompanion();
return await _db.userDao.createUser(userCompanion);
}
/// Создать пользователя с UserData
Future<String> createUserWithData({
required UserModel userModel,
required UserDatasCompanion userData,
}) async {
final userCompanion = userModel.toUsersCompanion();
return await _db.userDao.createUserWithData(
user: userCompanion,
userData: userData,
);
}
/// Обновить пользователя
Future<void> updateUser(UserModel userModel) async {
if (userModel.id == null) {
throw ArgumentError('User ID is required');
}
await _db.userDao.updateUserPartial(
userModel.toUsersCompanion().copyWith(
updatedAt: Value(PgDateTime(DateTime.now())),
),
);
}
/// Обновить пользователя частично
Future<void> updateUserPartial(UsersCompanion updates) async {
await _db.userDao.updateUserPartial(updates);
}
/// Удалить пользователя (soft delete)
Future<void> softDeleteUser(String userId) async {
await _db.userDao.softDeleteUser(userId);
}
/// Получить всех пользователей (для админки)
Future<List<UserModel>> getAllUsers({
int? limit,
int? offset,
bool includeDeleted = false,
bool includePacks = false,
}) async {
final users = await _db.userDao.getAllUsers(
limit: limit,
offset: offset,
includeDeleted: includeDeleted,
);
if (includePacks) {
final userModels = <UserModel>[];
for (final user in users) {
final packs = await _db.userDao.getUserPacks(user.id);
final userModel = await user.toUserModel(packs);
userModels.add(userModel);
}
return userModels;
}
return await Future.wait(users.map((u) => u.toUserModel()));
}
/// Подсчитать пользователей
Future<int> countUsers({bool includeDeleted = false}) async {
return await _db.userDao.countUsers(includeDeleted: includeDeleted);
}
/// Получить паки пользователя
Future<List<CardPackModel>> getUserPacks(String userId) async {
final packs = await _db.userDao.getUserPacks(userId);
return await Future.wait(packs.map((p) => p.toModel()));
}
/// Проверить, есть ли у пользователя доступ к паку
Future<bool> hasPackAccess(String userId, String packId) async {
return await _db.userDao.hasPackAccess(userId, packId);
}
/// Дать пользователю доступ к паку
Future<void> grantPackAccess({
required String userId,
required String packId,
String grantType = 'purchase',
}) async {
await _db.userDao.grantPackAccess(
userId: userId,
packId: packId,
grantType: grantType,
);
}
/// Отозвать доступ к паку
Future<void> revokePackAccess(String userId, String packId) async {
await _db.userDao.revokePackAccess(userId, packId);
}
/// Получить UserData пользователя
Future<UserData?> getUserData(String userId) async {
return await _db.userDao.getUserData(userId);
}
/// Обновить UserData частично
Future<void> updateUserDataPartial(UserDatasCompanion updates) async {
await _db.userDao.updateUserDataPartial(updates);
}
/// Обновить время последнего визита
Future<void> updateLastOnline(String userId) async {
await _db.userDao.updateLastOnline(userId);
}
}