97 lines
6.4 KiB
TypeScript
97 lines
6.4 KiB
TypeScript
import { Injectable, ConflictException } from '@nestjs/common';
|
|
import { PrismaService } from '../prisma/prisma.service';
|
|
import * as bcrypt from 'bcryptjs';
|
|
import * as crypto from 'crypto';
|
|
|
|
@Injectable()
|
|
export class UsersService {
|
|
constructor(private readonly prisma: PrismaService) {}
|
|
|
|
findByUsername(username: string) {
|
|
return this.prisma.user.findUnique({ where: { username } });
|
|
}
|
|
|
|
findById(id: number) {
|
|
return this.prisma.user.findUnique({ where: { id } });
|
|
}
|
|
|
|
create(data: { username: string; email: string; passwordHash: string }) {
|
|
return this.prisma.user.create({ data });
|
|
}
|
|
|
|
updateProfile(id: number, data: { firstName?: string; lastName?: string; email?: string }) {
|
|
return this.prisma.user.update({ where: { id }, data });
|
|
}
|
|
|
|
findAll() {
|
|
return this.prisma.user.findMany({
|
|
select: {
|
|
id: true,
|
|
username: true,
|
|
email: true,
|
|
firstName: true,
|
|
lastName: true,
|
|
role: true,
|
|
isPremium: true,
|
|
canShareRecipes: true,
|
|
aiEngineEnabled: true,
|
|
createdAt: true,
|
|
},
|
|
orderBy: { username: 'asc' },
|
|
});
|
|
}
|
|
|
|
setRole(id: number, role: string) {
|
|
return this.prisma.user.update({ where: { id }, data: { role } });
|
|
}
|
|
|
|
setPremium(id: number, isPremium: boolean) {
|
|
return this.prisma.user.update({ where: { id }, data: { isPremium } });
|
|
}
|
|
|
|
setRecipeSharing(id: number, canShareRecipes: boolean) {
|
|
return this.prisma.user.update({ where: { id }, data: { canShareRecipes } });
|
|
}
|
|
|
|
setAiEngineEnabled(id: number, aiEngineEnabled: boolean) {
|
|
return this.prisma.user.update({ where: { id }, data: { aiEngineEnabled } });
|
|
}
|
|
|
|
async adminCreate(data: { username: string; email: string; password: string; role?: string }) {
|
|
const existing = await this.prisma.user.findFirst({
|
|
where: { OR: [{ username: data.username }, { email: data.email }] },
|
|
});
|
|
if (existing) {
|
|
throw new ConflictException(
|
|
existing.username === data.username ? 'Användarnamnet är redan taget' : 'E-postadressen används redan',
|
|
);
|
|
}
|
|
const passwordHash = await bcrypt.hash(data.password, 12);
|
|
return this.prisma.user.create({
|
|
data: { username: data.username, email: data.email, passwordHash, role: data.role ?? 'user' },
|
|
});
|
|
}
|
|
|
|
deleteUser(id: number) {
|
|
return this.prisma.user.delete({ where: { id } });
|
|
}
|
|
|
|
async resetPassword(id: number): Promise<{ temporaryPassword: string }> {
|
|
// Generera läsbart 12-teckens lösenord (4 ord från slumpmässiga bytes)
|
|
const temporaryPassword = crypto.randomBytes(9).toString('base64url').slice(0, 12);
|
|
const passwordHash = await bcrypt.hash(temporaryPassword, 12);
|
|
await this.prisma.user.update({ where: { id }, data: { passwordHash } });
|
|
return { temporaryPassword };
|
|
}
|
|
|
|
async deleteUserAndData(userId: number) {
|
|
await this.prisma.$transaction([
|
|
this.prisma.product.deleteMany({ where: { ownerId: userId } }),
|
|
this.prisma.recipe.deleteMany({ where: { ownerId: userId } }),
|
|
this.prisma.inventoryItem.deleteMany({ where: { userId } }),
|
|
this.prisma.mealPlanEntry.deleteMany({ where: { userId } }),
|
|
this.prisma.user.delete({ where: { id: userId } }),
|
|
]);
|
|
}
|
|
}
|