Refactor code structure for improved readability and maintainability
Test Suite / test (24.15.0) (push) Has been cancelled

This commit is contained in:
Nils-Johan Gynther
2026-05-06 07:37:59 +02:00
parent e4f201ea36
commit 969dafdbc6
273 changed files with 11357 additions and 39 deletions
+8
View File
@@ -0,0 +1,8 @@
import { OnApplicationBootstrap } from '@nestjs/common';
import { PrismaService } from '../prisma/prisma.service';
export declare class AdminBootstrapService implements OnApplicationBootstrap {
private readonly prisma;
private readonly logger;
constructor(prisma: PrismaService);
onApplicationBootstrap(): Promise<void>;
}
+62
View File
@@ -0,0 +1,62 @@
"use strict";
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __metadata = (this && this.__metadata) || function (k, v) {
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
var AdminBootstrapService_1;
Object.defineProperty(exports, "__esModule", { value: true });
exports.AdminBootstrapService = void 0;
const common_1 = require("@nestjs/common");
const bcrypt = require("bcryptjs");
const prisma_service_1 = require("../prisma/prisma.service");
const SEED_USERS = [
{ username: 'Nadmin', email: 'nadmin@localhost', passwordEnvKey: 'ADMIN_NADMIN_PASSWORD', role: 'admin' },
{ username: 'Padmin', email: 'padmin@localhost', passwordEnvKey: 'ADMIN_PADMIN_PASSWORD', role: 'admin' },
{ username: 'user1', email: 'user1@localhost', passwordEnvKey: 'SEED_USER1_PASSWORD', role: 'user' },
{ username: 'user2', email: 'user2@localhost', passwordEnvKey: 'SEED_USER2_PASSWORD', role: 'user' },
];
let AdminBootstrapService = AdminBootstrapService_1 = class AdminBootstrapService {
constructor(prisma) {
this.prisma = prisma;
this.logger = new common_1.Logger(AdminBootstrapService_1.name);
}
async onApplicationBootstrap() {
for (const seed of SEED_USERS) {
const password = process.env[seed.passwordEnvKey];
if (!password) {
this.logger.warn(`${seed.passwordEnvKey} not set — skipping ${seed.username}`);
continue;
}
const existing = await this.prisma.user.findUnique({ where: { username: seed.username } });
if (existing) {
if (existing.role !== seed.role) {
await this.prisma.user.update({ where: { id: existing.id }, data: { role: seed.role } });
this.logger.log(`Updated role for ${seed.username}${seed.role}`);
}
}
else {
const passwordHash = await bcrypt.hash(password, 12);
await this.prisma.user.create({
data: {
username: seed.username,
email: seed.email,
passwordHash,
role: seed.role,
},
});
this.logger.log(`Created ${seed.role} user: ${seed.username}`);
}
}
}
};
exports.AdminBootstrapService = AdminBootstrapService;
exports.AdminBootstrapService = AdminBootstrapService = AdminBootstrapService_1 = __decorate([
(0, common_1.Injectable)(),
__metadata("design:paramtypes", [prisma_service_1.PrismaService])
], AdminBootstrapService);
//# sourceMappingURL=admin-bootstrap.service.js.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"admin-bootstrap.service.js","sourceRoot":"","sources":["../../src/users/admin-bootstrap.service.ts"],"names":[],"mappings":";;;;;;;;;;;;;AAAA,2CAA4E;AAC5E,mCAAmC;AACnC,6DAAyD;AASzD,MAAM,UAAU,GAAe;IAC7B,EAAE,QAAQ,EAAE,QAAQ,EAAE,KAAK,EAAE,kBAAkB,EAAE,cAAc,EAAE,uBAAuB,EAAE,IAAI,EAAE,OAAO,EAAE;IACzG,EAAE,QAAQ,EAAE,QAAQ,EAAE,KAAK,EAAE,kBAAkB,EAAE,cAAc,EAAE,uBAAuB,EAAE,IAAI,EAAE,OAAO,EAAE;IACzG,EAAE,QAAQ,EAAE,OAAO,EAAG,KAAK,EAAE,iBAAiB,EAAG,cAAc,EAAE,qBAAqB,EAAI,IAAI,EAAE,MAAM,EAAE;IACxG,EAAE,QAAQ,EAAE,OAAO,EAAG,KAAK,EAAE,iBAAiB,EAAG,cAAc,EAAE,qBAAqB,EAAI,IAAI,EAAE,MAAM,EAAE;CACzG,CAAC;AAGK,IAAM,qBAAqB,6BAA3B,MAAM,qBAAqB;IAGhC,YAA6B,MAAqB;QAArB,WAAM,GAAN,MAAM,CAAe;QAFjC,WAAM,GAAG,IAAI,eAAM,CAAC,uBAAqB,CAAC,IAAI,CAAC,CAAC;IAEZ,CAAC;IAEtD,KAAK,CAAC,sBAAsB;QAC1B,KAAK,MAAM,IAAI,IAAI,UAAU,EAAE,CAAC;YAC9B,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;YAClD,IAAI,CAAC,QAAQ,EAAE,CAAC;gBACd,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,cAAc,uBAAuB,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC;gBAC/E,SAAS;YACX,CAAC;YAED,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE,KAAK,EAAE,EAAE,QAAQ,EAAE,IAAI,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;YAE3F,IAAI,QAAQ,EAAE,CAAC;gBACb,IAAI,QAAQ,CAAC,IAAI,KAAK,IAAI,CAAC,IAAI,EAAE,CAAC;oBAChC,MAAM,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,EAAE,QAAQ,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;oBACzF,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,oBAAoB,IAAI,CAAC,QAAQ,MAAM,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;gBACtE,CAAC;YACH,CAAC;iBAAM,CAAC;gBACN,MAAM,YAAY,GAAG,MAAM,MAAM,CAAC,IAAI,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;gBACrD,MAAM,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC;oBAC5B,IAAI,EAAE;wBACJ,QAAQ,EAAE,IAAI,CAAC,QAAQ;wBACvB,KAAK,EAAE,IAAI,CAAC,KAAK;wBACjB,YAAY;wBACZ,IAAI,EAAE,IAAI,CAAC,IAAI;qBAChB;iBACF,CAAC,CAAC;gBACH,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,WAAW,IAAI,CAAC,IAAI,UAAU,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC;YACjE,CAAC;QACH,CAAC;IACH,CAAC;CACF,CAAA;AAlCY,sDAAqB;gCAArB,qBAAqB;IADjC,IAAA,mBAAU,GAAE;qCAI0B,8BAAa;GAHvC,qBAAqB,CAkCjC"}
+107
View File
@@ -0,0 +1,107 @@
import { UsersService } from './users.service';
declare class SetRoleDto {
role: string;
}
declare class SetPremiumDto {
isPremium: boolean;
}
declare class SetRecipeSharingDto {
canShareRecipes: boolean;
}
declare class AdminCreateUserDto {
username: string;
email: string;
password: string;
role?: string;
}
declare class UpdateEmailDto {
email: string;
}
declare class UpdateProfileDto {
firstName?: string;
lastName?: string;
email?: string;
}
export declare class UsersController {
private readonly usersService;
constructor(usersService: UsersService);
getMe(user: {
userId: number;
username: string;
}): Promise<{
id: number | undefined;
username: string | undefined;
email: string | undefined;
firstName: string | null | undefined;
lastName: string | null | undefined;
role: string | undefined;
}>;
updateMe(user: {
userId: number;
username: string;
}, dto: UpdateProfileDto): Promise<{
id: number;
username: string;
email: string;
firstName: string | null;
lastName: string | null;
}>;
listUsers(): import(".prisma/client").Prisma.PrismaPromise<{
id: number;
createdAt: Date;
username: string;
email: string;
firstName: string | null;
lastName: string | null;
role: string;
isPremium: boolean;
canShareRecipes: boolean;
}[]>;
setRole(id: number, caller: {
userId: number;
username: string;
role: string;
}, dto: SetRoleDto): Promise<{
id: number;
username: string;
role: string;
}>;
setPremium(id: number, dto: SetPremiumDto): Promise<{
id: number;
username: string;
isPremium: boolean;
}>;
setRecipeSharing(id: number, dto: SetRecipeSharingDto): Promise<{
id: number;
username: string;
canShareRecipes: boolean;
}>;
adminCreateUser(dto: AdminCreateUserDto): Promise<{
id: number;
username: string;
email: string;
role: string;
createdAt: Date;
}>;
deleteUser(id: number, caller: {
userId: number;
}): Promise<{
deleted: boolean;
}>;
resetPassword(id: number, caller: {
userId: number;
}): Promise<{
to: string;
subject: string;
body: string;
temporaryPassword: string;
}>;
updateEmail(id: number, caller: {
userId: number;
}, dto: UpdateEmailDto): Promise<{
id: number;
username: string;
email: string;
}>;
}
export {};
+252
View File
@@ -0,0 +1,252 @@
"use strict";
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __metadata = (this && this.__metadata) || function (k, v) {
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
var __param = (this && this.__param) || function (paramIndex, decorator) {
return function (target, key) { decorator(target, key, paramIndex); }
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.UsersController = void 0;
const common_1 = require("@nestjs/common");
const class_validator_1 = require("class-validator");
const users_service_1 = require("./users.service");
const current_user_decorator_1 = require("../auth/decorators/current-user.decorator");
const roles_decorator_1 = require("../auth/decorators/roles.decorator");
class SetRoleDto {
}
__decorate([
(0, class_validator_1.IsIn)(['admin', 'user']),
__metadata("design:type", String)
], SetRoleDto.prototype, "role", void 0);
class SetPremiumDto {
}
__decorate([
(0, class_validator_1.IsBoolean)(),
__metadata("design:type", Boolean)
], SetPremiumDto.prototype, "isPremium", void 0);
class SetRecipeSharingDto {
}
__decorate([
(0, class_validator_1.IsBoolean)(),
__metadata("design:type", Boolean)
], SetRecipeSharingDto.prototype, "canShareRecipes", void 0);
class AdminCreateUserDto {
}
__decorate([
(0, class_validator_1.IsString)(),
(0, class_validator_1.MinLength)(2),
(0, class_validator_1.MaxLength)(50),
__metadata("design:type", String)
], AdminCreateUserDto.prototype, "username", void 0);
__decorate([
(0, class_validator_1.IsEmail)(),
__metadata("design:type", String)
], AdminCreateUserDto.prototype, "email", void 0);
__decorate([
(0, class_validator_1.IsString)(),
(0, class_validator_1.MinLength)(8),
__metadata("design:type", String)
], AdminCreateUserDto.prototype, "password", void 0);
__decorate([
(0, class_validator_1.IsOptional)(),
(0, class_validator_1.IsIn)(['admin', 'user']),
__metadata("design:type", String)
], AdminCreateUserDto.prototype, "role", void 0);
class UpdateEmailDto {
}
__decorate([
(0, class_validator_1.IsEmail)(),
__metadata("design:type", String)
], UpdateEmailDto.prototype, "email", void 0);
class UpdateProfileDto {
}
__decorate([
(0, class_validator_1.IsOptional)(),
(0, class_validator_1.IsString)(),
(0, class_validator_1.MaxLength)(100),
__metadata("design:type", String)
], UpdateProfileDto.prototype, "firstName", void 0);
__decorate([
(0, class_validator_1.IsOptional)(),
(0, class_validator_1.IsString)(),
(0, class_validator_1.MaxLength)(100),
__metadata("design:type", String)
], UpdateProfileDto.prototype, "lastName", void 0);
__decorate([
(0, class_validator_1.IsOptional)(),
(0, class_validator_1.IsEmail)(),
__metadata("design:type", String)
], UpdateProfileDto.prototype, "email", void 0);
let UsersController = class UsersController {
constructor(usersService) {
this.usersService = usersService;
}
async getMe(user) {
const found = await this.usersService.findById(user.userId);
return {
id: found?.id,
username: found?.username,
email: found?.email,
firstName: found?.firstName,
lastName: found?.lastName,
role: found?.role,
};
}
async updateMe(user, dto) {
const updated = await this.usersService.updateProfile(user.userId, dto);
return {
id: updated.id,
username: updated.username,
email: updated.email,
firstName: updated.firstName,
lastName: updated.lastName,
};
}
listUsers() {
return this.usersService.findAll();
}
async setRole(id, caller, dto) {
if (caller.userId === id)
throw new common_1.BadRequestException('Du kan inte ändra din egen roll');
const updated = await this.usersService.setRole(id, dto.role);
return { id: updated.id, username: updated.username, role: updated.role };
}
async setPremium(id, dto) {
const updated = await this.usersService.setPremium(id, dto.isPremium);
return { id: updated.id, username: updated.username, isPremium: updated.isPremium };
}
async setRecipeSharing(id, dto) {
const updated = await this.usersService.setRecipeSharing(id, dto.canShareRecipes);
return { id: updated.id, username: updated.username, canShareRecipes: updated.canShareRecipes };
}
async adminCreateUser(dto) {
const user = await this.usersService.adminCreate(dto);
return { id: user.id, username: user.username, email: user.email, role: user.role, createdAt: user.createdAt };
}
async deleteUser(id, caller) {
if (caller.userId === id)
throw new common_1.BadRequestException('Du kan inte ta bort ditt eget konto');
await this.usersService.deleteUser(id);
return { deleted: true };
}
async resetPassword(id, caller) {
if (caller.userId === id)
throw new common_1.BadRequestException('Du kan inte återställa ditt eget lösenord härifrån');
const user = await this.usersService.findById(id);
if (!user)
throw new common_1.BadRequestException('Användaren hittades inte');
const { temporaryPassword } = await this.usersService.resetPassword(id);
const appUrl = process.env.NEXT_PUBLIC_APP_URL ?? 'appen';
const displayName = user.firstName ? user.firstName : user.username;
return {
to: user.email,
subject: 'Ditt lösenord har återställts',
body: `Hej ${displayName},\n\nDitt lösenord har återställts av en administratör.\nDitt nya tillôlliga lösenord är: ${temporaryPassword}\n\nLogga in på ${appUrl} och byt lösenord snarast.\n\nHälsningar`,
temporaryPassword,
};
}
async updateEmail(id, caller, dto) {
if (caller.userId === id)
throw new common_1.BadRequestException('Använd "Min profil" för att ändra din egen e-post');
const updated = await this.usersService.updateEmail(id, dto.email);
return { id: updated.id, username: updated.username, email: updated.email };
}
};
exports.UsersController = UsersController;
__decorate([
(0, common_1.Get)('me'),
__param(0, (0, current_user_decorator_1.CurrentUser)()),
__metadata("design:type", Function),
__metadata("design:paramtypes", [Object]),
__metadata("design:returntype", Promise)
], UsersController.prototype, "getMe", null);
__decorate([
(0, common_1.Patch)('me'),
__param(0, (0, current_user_decorator_1.CurrentUser)()),
__param(1, (0, common_1.Body)()),
__metadata("design:type", Function),
__metadata("design:paramtypes", [Object, UpdateProfileDto]),
__metadata("design:returntype", Promise)
], UsersController.prototype, "updateMe", null);
__decorate([
(0, roles_decorator_1.Roles)('admin'),
(0, common_1.Get)(),
__metadata("design:type", Function),
__metadata("design:paramtypes", []),
__metadata("design:returntype", void 0)
], UsersController.prototype, "listUsers", null);
__decorate([
(0, roles_decorator_1.Roles)('admin'),
(0, common_1.Patch)(':id/role'),
__param(0, (0, common_1.Param)('id', common_1.ParseIntPipe)),
__param(1, (0, current_user_decorator_1.CurrentUser)()),
__param(2, (0, common_1.Body)()),
__metadata("design:type", Function),
__metadata("design:paramtypes", [Number, Object, SetRoleDto]),
__metadata("design:returntype", Promise)
], UsersController.prototype, "setRole", null);
__decorate([
(0, roles_decorator_1.Roles)('admin'),
(0, common_1.Patch)(':id/premium'),
__param(0, (0, common_1.Param)('id', common_1.ParseIntPipe)),
__param(1, (0, common_1.Body)()),
__metadata("design:type", Function),
__metadata("design:paramtypes", [Number, SetPremiumDto]),
__metadata("design:returntype", Promise)
], UsersController.prototype, "setPremium", null);
__decorate([
(0, roles_decorator_1.Roles)('admin'),
(0, common_1.Patch)(':id/recipe-sharing'),
__param(0, (0, common_1.Param)('id', common_1.ParseIntPipe)),
__param(1, (0, common_1.Body)()),
__metadata("design:type", Function),
__metadata("design:paramtypes", [Number, SetRecipeSharingDto]),
__metadata("design:returntype", Promise)
], UsersController.prototype, "setRecipeSharing", null);
__decorate([
(0, roles_decorator_1.Roles)('admin'),
(0, common_1.Post)(),
__param(0, (0, common_1.Body)()),
__metadata("design:type", Function),
__metadata("design:paramtypes", [AdminCreateUserDto]),
__metadata("design:returntype", Promise)
], UsersController.prototype, "adminCreateUser", null);
__decorate([
(0, roles_decorator_1.Roles)('admin'),
(0, common_1.Delete)(':id'),
__param(0, (0, common_1.Param)('id', common_1.ParseIntPipe)),
__param(1, (0, current_user_decorator_1.CurrentUser)()),
__metadata("design:type", Function),
__metadata("design:paramtypes", [Number, Object]),
__metadata("design:returntype", Promise)
], UsersController.prototype, "deleteUser", null);
__decorate([
(0, roles_decorator_1.Roles)('admin'),
(0, common_1.Post)(':id/reset-password'),
__param(0, (0, common_1.Param)('id', common_1.ParseIntPipe)),
__param(1, (0, current_user_decorator_1.CurrentUser)()),
__metadata("design:type", Function),
__metadata("design:paramtypes", [Number, Object]),
__metadata("design:returntype", Promise)
], UsersController.prototype, "resetPassword", null);
__decorate([
(0, roles_decorator_1.Roles)('admin'),
(0, common_1.Patch)(':id/email'),
__param(0, (0, common_1.Param)('id', common_1.ParseIntPipe)),
__param(1, (0, current_user_decorator_1.CurrentUser)()),
__param(2, (0, common_1.Body)()),
__metadata("design:type", Function),
__metadata("design:paramtypes", [Number, Object, UpdateEmailDto]),
__metadata("design:returntype", Promise)
], UsersController.prototype, "updateEmail", null);
exports.UsersController = UsersController = __decorate([
(0, common_1.Controller)('users'),
__metadata("design:paramtypes", [users_service_1.UsersService])
], UsersController);
//# sourceMappingURL=users.controller.js.map
File diff suppressed because one or more lines are too long
+2
View File
@@ -0,0 +1,2 @@
export declare class UsersModule {
}
+26
View File
@@ -0,0 +1,26 @@
"use strict";
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.UsersModule = void 0;
const common_1 = require("@nestjs/common");
const users_service_1 = require("./users.service");
const users_controller_1 = require("./users.controller");
const admin_bootstrap_service_1 = require("./admin-bootstrap.service");
const prisma_module_1 = require("../prisma/prisma.module");
let UsersModule = class UsersModule {
};
exports.UsersModule = UsersModule;
exports.UsersModule = UsersModule = __decorate([
(0, common_1.Module)({
imports: [prisma_module_1.PrismaModule],
providers: [users_service_1.UsersService, admin_bootstrap_service_1.AdminBootstrapService],
controllers: [users_controller_1.UsersController],
exports: [users_service_1.UsersService],
})
], UsersModule);
//# sourceMappingURL=users.module.js.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"users.module.js","sourceRoot":"","sources":["../../src/users/users.module.ts"],"names":[],"mappings":";;;;;;;;;AAAA,2CAAwC;AACxC,mDAA+C;AAC/C,yDAAqD;AACrD,uEAAkE;AAClE,2DAAuD;AAQhD,IAAM,WAAW,GAAjB,MAAM,WAAW;CAAG,CAAA;AAAd,kCAAW;sBAAX,WAAW;IANvB,IAAA,eAAM,EAAC;QACN,OAAO,EAAE,CAAC,4BAAY,CAAC;QACvB,SAAS,EAAE,CAAC,4BAAY,EAAE,+CAAqB,CAAC;QAChD,WAAW,EAAE,CAAC,kCAAe,CAAC;QAC9B,OAAO,EAAE,CAAC,4BAAY,CAAC;KACxB,CAAC;GACW,WAAW,CAAG"}
+162
View File
@@ -0,0 +1,162 @@
import { PrismaService } from '../prisma/prisma.service';
export declare class UsersService {
private readonly prisma;
constructor(prisma: PrismaService);
findByUsername(username: string): import(".prisma/client").Prisma.Prisma__UserClient<{
id: number;
createdAt: Date;
updatedAt: Date;
username: string;
email: string;
firstName: string | null;
lastName: string | null;
passwordHash: string;
role: string;
isPremium: boolean;
canShareRecipes: boolean;
} | null, null, import("@prisma/client/runtime/library").DefaultArgs, import(".prisma/client").Prisma.PrismaClientOptions>;
findById(id: number): import(".prisma/client").Prisma.Prisma__UserClient<{
id: number;
createdAt: Date;
updatedAt: Date;
username: string;
email: string;
firstName: string | null;
lastName: string | null;
passwordHash: string;
role: string;
isPremium: boolean;
canShareRecipes: boolean;
} | null, null, import("@prisma/client/runtime/library").DefaultArgs, import(".prisma/client").Prisma.PrismaClientOptions>;
create(data: {
username: string;
email: string;
passwordHash: string;
}): import(".prisma/client").Prisma.Prisma__UserClient<{
id: number;
createdAt: Date;
updatedAt: Date;
username: string;
email: string;
firstName: string | null;
lastName: string | null;
passwordHash: string;
role: string;
isPremium: boolean;
canShareRecipes: boolean;
}, never, import("@prisma/client/runtime/library").DefaultArgs, import(".prisma/client").Prisma.PrismaClientOptions>;
updateProfile(id: number, data: {
firstName?: string;
lastName?: string;
email?: string;
}): import(".prisma/client").Prisma.Prisma__UserClient<{
id: number;
createdAt: Date;
updatedAt: Date;
username: string;
email: string;
firstName: string | null;
lastName: string | null;
passwordHash: string;
role: string;
isPremium: boolean;
canShareRecipes: boolean;
}, never, import("@prisma/client/runtime/library").DefaultArgs, import(".prisma/client").Prisma.PrismaClientOptions>;
findAll(): import(".prisma/client").Prisma.PrismaPromise<{
id: number;
createdAt: Date;
username: string;
email: string;
firstName: string | null;
lastName: string | null;
role: string;
isPremium: boolean;
canShareRecipes: boolean;
}[]>;
setRole(id: number, role: string): import(".prisma/client").Prisma.Prisma__UserClient<{
id: number;
createdAt: Date;
updatedAt: Date;
username: string;
email: string;
firstName: string | null;
lastName: string | null;
passwordHash: string;
role: string;
isPremium: boolean;
canShareRecipes: boolean;
}, never, import("@prisma/client/runtime/library").DefaultArgs, import(".prisma/client").Prisma.PrismaClientOptions>;
setPremium(id: number, isPremium: boolean): import(".prisma/client").Prisma.Prisma__UserClient<{
id: number;
createdAt: Date;
updatedAt: Date;
username: string;
email: string;
firstName: string | null;
lastName: string | null;
passwordHash: string;
role: string;
isPremium: boolean;
canShareRecipes: boolean;
}, never, import("@prisma/client/runtime/library").DefaultArgs, import(".prisma/client").Prisma.PrismaClientOptions>;
setRecipeSharing(id: number, canShareRecipes: boolean): import(".prisma/client").Prisma.Prisma__UserClient<{
id: number;
createdAt: Date;
updatedAt: Date;
username: string;
email: string;
firstName: string | null;
lastName: string | null;
passwordHash: string;
role: string;
isPremium: boolean;
canShareRecipes: boolean;
}, never, import("@prisma/client/runtime/library").DefaultArgs, import(".prisma/client").Prisma.PrismaClientOptions>;
adminCreate(data: {
username: string;
email: string;
password: string;
role?: string;
}): Promise<{
id: number;
createdAt: Date;
updatedAt: Date;
username: string;
email: string;
firstName: string | null;
lastName: string | null;
passwordHash: string;
role: string;
isPremium: boolean;
canShareRecipes: boolean;
}>;
deleteUser(id: number): import(".prisma/client").Prisma.Prisma__UserClient<{
id: number;
createdAt: Date;
updatedAt: Date;
username: string;
email: string;
firstName: string | null;
lastName: string | null;
passwordHash: string;
role: string;
isPremium: boolean;
canShareRecipes: boolean;
}, never, import("@prisma/client/runtime/library").DefaultArgs, import(".prisma/client").Prisma.PrismaClientOptions>;
resetPassword(id: number): Promise<{
temporaryPassword: string;
}>;
updateEmail(id: number, email: string): import(".prisma/client").Prisma.Prisma__UserClient<{
id: number;
createdAt: Date;
updatedAt: Date;
username: string;
email: string;
firstName: string | null;
lastName: string | null;
passwordHash: string;
role: string;
isPremium: boolean;
canShareRecipes: boolean;
}, never, import("@prisma/client/runtime/library").DefaultArgs, import(".prisma/client").Prisma.PrismaClientOptions>;
}
+88
View File
@@ -0,0 +1,88 @@
"use strict";
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __metadata = (this && this.__metadata) || function (k, v) {
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.UsersService = void 0;
const common_1 = require("@nestjs/common");
const prisma_service_1 = require("../prisma/prisma.service");
const bcrypt = require("bcryptjs");
const crypto = require("crypto");
let UsersService = class UsersService {
constructor(prisma) {
this.prisma = prisma;
}
findByUsername(username) {
return this.prisma.user.findUnique({ where: { username } });
}
findById(id) {
return this.prisma.user.findUnique({ where: { id } });
}
create(data) {
return this.prisma.user.create({ data });
}
updateProfile(id, data) {
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,
createdAt: true,
},
orderBy: { username: 'asc' },
});
}
setRole(id, role) {
return this.prisma.user.update({ where: { id }, data: { role } });
}
setPremium(id, isPremium) {
return this.prisma.user.update({ where: { id }, data: { isPremium } });
}
setRecipeSharing(id, canShareRecipes) {
return this.prisma.user.update({ where: { id }, data: { canShareRecipes } });
}
async adminCreate(data) {
const existing = await this.prisma.user.findFirst({
where: { OR: [{ username: data.username }, { email: data.email }] },
});
if (existing) {
throw new common_1.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) {
return this.prisma.user.delete({ where: { id } });
}
async resetPassword(id) {
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 };
}
updateEmail(id, email) {
return this.prisma.user.update({ where: { id }, data: { email } });
}
};
exports.UsersService = UsersService;
exports.UsersService = UsersService = __decorate([
(0, common_1.Injectable)(),
__metadata("design:paramtypes", [prisma_service_1.PrismaService])
], UsersService);
//# sourceMappingURL=users.service.js.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"users.service.js","sourceRoot":"","sources":["../../src/users/users.service.ts"],"names":[],"mappings":"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"}