Refactor code structure for improved readability and maintainability
Test Suite / test (24.15.0) (push) Has been cancelled
Test Suite / test (24.15.0) (push) Has been cancelled
This commit is contained in:
@@ -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
@@ -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
|
||||
@@ -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
@@ -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
@@ -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
|
||||
+1
File diff suppressed because one or more lines are too long
Vendored
+2
@@ -0,0 +1,2 @@
|
||||
export declare class UsersModule {
|
||||
}
|
||||
Vendored
+26
@@ -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
@@ -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
@@ -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>;
|
||||
}
|
||||
Vendored
+88
@@ -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
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"users.service.js","sourceRoot":"","sources":["../../src/users/users.service.ts"],"names":[],"mappings":"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"}
|
||||
Reference in New Issue
Block a user