authentication
This commit is contained in:
@@ -6,7 +6,14 @@ DATABASE_HOST=localhost
|
||||
DATABASE_PORT=3306
|
||||
MYSQL_ROOT_PASSWORD=kjsdahflöijsdiu
|
||||
|
||||
# SECURITY
|
||||
# SSO
|
||||
SSO_TOKEN_URL=https://sso.beantastic.de/api/authorize
|
||||
SSO_VERIFY_URL=https://sso.beantastic.de/api/verify
|
||||
SSO_REDIRECT_URI=
|
||||
SSO_CLIENT_SECRET=
|
||||
SSO_CLIENT_ID=
|
||||
|
||||
|
||||
# SECURITY
|
||||
JWT_SECRET=
|
||||
JWT_EXPIRES_IN=10m
|
||||
17
api/package-lock.json
generated
17
api/package-lock.json
generated
@@ -25,6 +25,7 @@
|
||||
"typeorm": "^0.3.20"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@faker-js/faker": "^9.0.0",
|
||||
"@nestjs/cli": "^10.0.0",
|
||||
"@nestjs/schematics": "^10.0.0",
|
||||
"@nestjs/testing": "^10.0.0",
|
||||
@@ -903,6 +904,22 @@
|
||||
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@faker-js/faker": {
|
||||
"version": "9.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@faker-js/faker/-/faker-9.0.0.tgz",
|
||||
"integrity": "sha512-dTDHJSmz6c1OJ6HO7jiUiIb4sB20Dlkb3pxYsKm0qTXm2Bmj97rlXIhlvaFsW2rvCi+OLlwKLVSS6ZxFUVZvjQ==",
|
||||
"dev": true,
|
||||
"funding": [
|
||||
{
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/fakerjs"
|
||||
}
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18.0.0",
|
||||
"npm": ">=9.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@humanwhocodes/config-array": {
|
||||
"version": "0.11.14",
|
||||
"resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz",
|
||||
|
||||
@@ -36,6 +36,7 @@
|
||||
"typeorm": "^0.3.20"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@faker-js/faker": "^9.0.0",
|
||||
"@nestjs/cli": "^10.0.0",
|
||||
"@nestjs/schematics": "^10.0.0",
|
||||
"@nestjs/testing": "^10.0.0",
|
||||
|
||||
@@ -1,18 +1,22 @@
|
||||
import { Body, Controller, Get, Post } from '@nestjs/common';
|
||||
import { Body, Controller, Get, HttpException, HttpStatus, Post, UseGuards } from '@nestjs/common';
|
||||
import { AppService } from './app.service';
|
||||
import { LoginDTO } from './model/dto/login.dto';
|
||||
import { AuthGuard } from './core/guards/auth.guard';
|
||||
|
||||
@Controller()
|
||||
export class AppController {
|
||||
constructor(private readonly appService: AppService) {}
|
||||
|
||||
@UseGuards(AuthGuard)
|
||||
@Get()
|
||||
getHello(): any {
|
||||
|
||||
return this.appService.getHello();
|
||||
}
|
||||
|
||||
@Post()
|
||||
login(@Body() createUserDto: LoginDTO) {
|
||||
|
||||
return { success: createUserDto };
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,6 +4,9 @@ import { AppService } from './app.service';
|
||||
import { ConfigModule } from '@nestjs/config';
|
||||
import { DatabaseModule } from './shared/database/database.module';
|
||||
import { AuthModule } from './modules/auth/auth.module';
|
||||
import { AuthGuard } from './core/guards/auth.guard';
|
||||
import { UserModule } from './modules/user/user.module';
|
||||
import { RoleModule } from './modules/role/role.module';
|
||||
|
||||
@Module({
|
||||
imports: [
|
||||
@@ -13,8 +16,10 @@ import { AuthModule } from './modules/auth/auth.module';
|
||||
}),
|
||||
DatabaseModule,
|
||||
AuthModule,
|
||||
UserModule,
|
||||
RoleModule,
|
||||
],
|
||||
controllers: [AppController],
|
||||
providers: [AppService],
|
||||
providers: [AppService, AuthGuard],
|
||||
})
|
||||
export class AppModule {}
|
||||
|
||||
61
api/src/core/guards/auth.guard.ts
Normal file
61
api/src/core/guards/auth.guard.ts
Normal file
@@ -0,0 +1,61 @@
|
||||
import {
|
||||
CanActivate,
|
||||
ExecutionContext,
|
||||
HttpException,
|
||||
HttpStatus,
|
||||
Injectable,
|
||||
UnauthorizedException,
|
||||
} from '@nestjs/common';
|
||||
import { ConfigService } from '@nestjs/config';
|
||||
import { JsonWebTokenError, JwtService } from '@nestjs/jwt';
|
||||
import { Request } from 'express';
|
||||
import { IPayload } from 'src/model/interface';
|
||||
import { AuthService } from 'src/modules/auth/auth.service';
|
||||
|
||||
@Injectable()
|
||||
export class AuthGuard implements CanActivate {
|
||||
constructor(
|
||||
private readonly jwtService: JwtService,
|
||||
private config: ConfigService,
|
||||
private authService: AuthService,
|
||||
) {}
|
||||
|
||||
async canActivate(context: ExecutionContext): Promise<boolean> {
|
||||
const request = context.switchToHttp().getRequest<Request>();
|
||||
const token = this.extractTokenFromHeader(request);
|
||||
|
||||
if (!token) {
|
||||
throw new UnauthorizedException('Token not provided');
|
||||
}
|
||||
|
||||
try {
|
||||
const secret = this.config.get('JWT_SECRET');
|
||||
// Überprüft das JWT und dekodiert es
|
||||
const payload: IPayload = this.jwtService.verify(token, { secret });
|
||||
if (payload.type != 'access') {
|
||||
throw new UnauthorizedException('wrong token');
|
||||
}
|
||||
const user = await this.authService.getUserById(payload.id);
|
||||
if (!user.isActive) {
|
||||
throw new HttpException('not active', HttpStatus.FORBIDDEN);
|
||||
}
|
||||
request['user'] = user;
|
||||
} catch (error) {
|
||||
const j = error as JsonWebTokenError;
|
||||
const m = j.message;
|
||||
|
||||
throw new UnauthorizedException(m);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private extractTokenFromHeader(request: Request): string | null {
|
||||
const authHeader = request.headers['authorization'];
|
||||
if (!authHeader) {
|
||||
return null;
|
||||
}
|
||||
const [type, token] = authHeader.split(' ');
|
||||
return type === 'Bearer' && token ? token : null;
|
||||
}
|
||||
}
|
||||
5
api/src/model/decorators/admin.decorator.ts
Normal file
5
api/src/model/decorators/admin.decorator.ts
Normal file
@@ -0,0 +1,5 @@
|
||||
import { Expose } from 'class-transformer';
|
||||
|
||||
export function AdminGroup() {
|
||||
return Expose({ groups: ['admin'] }); // Setzt die Gruppe 'admin' automatisch
|
||||
}
|
||||
@@ -1,2 +1,3 @@
|
||||
export * from './sso.user.entity';
|
||||
export * from './user.entity';
|
||||
export * from './role.entity';
|
||||
|
||||
19
api/src/model/entitites/role.entity.ts
Normal file
19
api/src/model/entitites/role.entity.ts
Normal file
@@ -0,0 +1,19 @@
|
||||
import {
|
||||
Column,
|
||||
Entity,
|
||||
OneToMany,
|
||||
PrimaryGeneratedColumn,
|
||||
} from 'typeorm';
|
||||
import { User } from './user.entity';
|
||||
|
||||
@Entity()
|
||||
export class Role {
|
||||
@PrimaryGeneratedColumn('uuid')
|
||||
id: string;
|
||||
|
||||
@OneToMany(() => User, (user) => user.role)
|
||||
user: User[];
|
||||
|
||||
@Column({ nullable: true })
|
||||
name: string;
|
||||
}
|
||||
@@ -1,14 +1,17 @@
|
||||
import { Exclude } from 'class-transformer';
|
||||
import { Exclude, Transform } from 'class-transformer';
|
||||
import {
|
||||
Column,
|
||||
CreateDateColumn,
|
||||
Entity,
|
||||
JoinColumn,
|
||||
ManyToOne,
|
||||
OneToOne,
|
||||
PrimaryGeneratedColumn,
|
||||
} from 'typeorm';
|
||||
import { IUser } from '../interface';
|
||||
import { SSOUser } from './sso.user.entity';
|
||||
import { IsEmail } from 'class-validator';
|
||||
import { Role } from './role.entity';
|
||||
|
||||
@Entity()
|
||||
export class User implements IUser {
|
||||
@@ -35,10 +38,14 @@ export class User implements IUser {
|
||||
@OneToOne(() => SSOUser, (sso) => sso.user, { eager: true, cascade: true })
|
||||
external: SSOUser;
|
||||
|
||||
@Exclude()
|
||||
@Column({ default: true })
|
||||
isActive: boolean;
|
||||
|
||||
@ManyToOne(() => Role, (role) => role.user, { cascade: true })
|
||||
@JoinColumn()
|
||||
@Transform(({ value }) => value.name)
|
||||
role: Role;
|
||||
|
||||
accessToken?: string;
|
||||
refreshToken?: string;
|
||||
}
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import { Role } from '../entitites';
|
||||
|
||||
export interface IUser {
|
||||
id: string;
|
||||
username: string;
|
||||
@@ -7,4 +9,6 @@ export interface IUser {
|
||||
|
||||
accessToken?: string;
|
||||
refreshToken?: string;
|
||||
|
||||
role?: string | Role;
|
||||
}
|
||||
|
||||
@@ -1,2 +1,3 @@
|
||||
export * from './user.repository';
|
||||
export * from './ssouser.repository';
|
||||
export * from './role.repository';
|
||||
|
||||
14
api/src/model/repositories/role.repository.ts
Normal file
14
api/src/model/repositories/role.repository.ts
Normal file
@@ -0,0 +1,14 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { Repository, DataSource } from 'typeorm';
|
||||
import { Role } from '../entitites';
|
||||
|
||||
@Injectable()
|
||||
export class RoleRepository extends Repository<Role> {
|
||||
constructor(dataSource: DataSource) {
|
||||
super(Role, dataSource.createEntityManager());
|
||||
}
|
||||
|
||||
getStandardRole(): Promise<Role> {
|
||||
return this.findOne({ where: { name: 'develop' } });
|
||||
}
|
||||
}
|
||||
@@ -3,12 +3,14 @@ import { Repository, DataSource } from 'typeorm';
|
||||
import { User } from '../entitites';
|
||||
import { CreateUserDto } from '../dto/create-user.dto';
|
||||
import { SsoUserRepository } from './ssouser.repository';
|
||||
import { RoleRepository } from './role.repository';
|
||||
|
||||
@Injectable()
|
||||
export class UserRepository extends Repository<User> {
|
||||
constructor(
|
||||
dataSource: DataSource,
|
||||
private ssoRepo: SsoUserRepository,
|
||||
private roleRepo: RoleRepository,
|
||||
) {
|
||||
super(User, dataSource.createEntityManager());
|
||||
}
|
||||
@@ -38,6 +40,7 @@ export class UserRepository extends Repository<User> {
|
||||
externalId: createUserDto.externalId,
|
||||
});
|
||||
created.external = sso;
|
||||
created.role = await this.roleRepo.getStandardRole();
|
||||
const user = await this.save(created);
|
||||
sso.user = user;
|
||||
this.ssoRepo.save(sso);
|
||||
|
||||
@@ -1,13 +1,17 @@
|
||||
import {
|
||||
Body,
|
||||
Controller,
|
||||
Get,
|
||||
HttpException,
|
||||
HttpStatus,
|
||||
Post,
|
||||
Req,
|
||||
UseGuards,
|
||||
} from '@nestjs/common';
|
||||
import { AuthService } from './auth.service';
|
||||
import { AuthCodeDto } from 'src/model/dto';
|
||||
import { User } from 'src/model/entitites';
|
||||
import { AuthGuard } from 'src/core/guards/auth.guard';
|
||||
|
||||
@Controller('auth')
|
||||
export class AuthController {
|
||||
@@ -23,4 +27,19 @@ export class AuthController {
|
||||
}
|
||||
return user;
|
||||
}
|
||||
|
||||
@UseGuards(AuthGuard)
|
||||
@Get('me')
|
||||
getMe(@Req() req: any) {
|
||||
return req.user;
|
||||
}
|
||||
|
||||
@Post('refresh')
|
||||
async getNewAccessToken(@Body() b: any) {
|
||||
if (b.refreshToken) {
|
||||
return this.authService.getNewToken(b.refreshToken);
|
||||
}
|
||||
|
||||
throw new HttpException('no token', HttpStatus.BAD_REQUEST);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ import { AuthService } from './auth.service';
|
||||
import { DatabaseModule } from 'src/shared/database/database.module';
|
||||
import { ConfigModule, ConfigService } from '@nestjs/config';
|
||||
import { HttpModule } from '@nestjs/axios';
|
||||
import { JwtModule } from '@nestjs/jwt';
|
||||
import { JwtModule, JwtService } from '@nestjs/jwt';
|
||||
|
||||
@Module({
|
||||
controllers: [AuthController],
|
||||
@@ -22,5 +22,6 @@ import { JwtModule } from '@nestjs/jwt';
|
||||
}),
|
||||
}),
|
||||
],
|
||||
exports: [JwtModule, AuthService],
|
||||
})
|
||||
export class AuthModule {}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { HttpException, HttpStatus, Injectable } from '@nestjs/common';
|
||||
import { AuthCodeDto } from 'src/model/dto';
|
||||
import { CreateUserDto } from 'src/model/dto/create-user.dto';
|
||||
import { UserRepository } from 'src/model/repositories';
|
||||
@@ -21,7 +21,6 @@ export class AuthService {
|
||||
}
|
||||
|
||||
async registerOrLoginWithAuthCode(auth: AuthCodeDto): Promise<User> {
|
||||
console.log(auth);
|
||||
const body = this.createAuthCodeFormData(auth.code, 'authorization_code');
|
||||
const url = this.configService.get('SSO_TOKEN_URL');
|
||||
return new Promise<User>((resolve) => {
|
||||
@@ -45,7 +44,6 @@ export class AuthService {
|
||||
access_token: string;
|
||||
refresh_token: string;
|
||||
}): Promise<User> {
|
||||
console.log(access_token, refresh_token);
|
||||
const payload: IExternalAccessPayload = this.jwt.decode(access_token);
|
||||
return new Promise<User>(async (resolve) => {
|
||||
let user = await this.userRepo.findByUsername(payload.username);
|
||||
@@ -56,6 +54,9 @@ export class AuthService {
|
||||
externalId: payload.id,
|
||||
});
|
||||
}
|
||||
if (!user.isActive) {
|
||||
throw new HttpException('not active', HttpStatus.FORBIDDEN);
|
||||
}
|
||||
|
||||
user.firstName = payload.firstName;
|
||||
user.lastName = payload.lastName;
|
||||
@@ -82,7 +83,7 @@ export class AuthService {
|
||||
type: 'refresh',
|
||||
};
|
||||
|
||||
user.refreshToken = this.jwt.sign(rPay);
|
||||
user.refreshToken = this.jwt.sign(rPay, { expiresIn: '1w' });
|
||||
}
|
||||
|
||||
private createAuthCodeFormData(
|
||||
@@ -103,4 +104,76 @@ export class AuthService {
|
||||
);
|
||||
return bodyFormData;
|
||||
}
|
||||
|
||||
getUserById(id: string): Promise<User> {
|
||||
return this.userRepo.findById(id);
|
||||
}
|
||||
|
||||
async getNewToken(refresh: string) {
|
||||
try {
|
||||
const payload: IPayload = this.jwt.verify(refresh);
|
||||
const user = await this.getUserById(payload.id);
|
||||
if (!user) {
|
||||
throw new HttpException('not valid', HttpStatus.UNAUTHORIZED);
|
||||
}
|
||||
const s = await this.verifyExternal(user);
|
||||
if (!s) {
|
||||
throw new HttpException('not valid', HttpStatus.UNAUTHORIZED);
|
||||
}
|
||||
this.generateTokens(user);
|
||||
return user;
|
||||
} catch (e) {
|
||||
throw new HttpException('invalid token', HttpStatus.BAD_REQUEST);
|
||||
}
|
||||
}
|
||||
|
||||
verifyExternal(user: User) {
|
||||
if (!user || !user.external) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const url = this.configService.get('SSO_VERIFY_URL');
|
||||
return new Promise((resolve) => {
|
||||
this.http
|
||||
.post(url, { access_token: user.external.accessToken })
|
||||
.subscribe({
|
||||
next: (response) => {
|
||||
const id = response.data.id;
|
||||
if (id == user.external.externalId) {
|
||||
resolve(true);
|
||||
} else {
|
||||
resolve(false);
|
||||
}
|
||||
},
|
||||
error: async (error) => {
|
||||
const data = error.response.data;
|
||||
if (data.message == 'jwt expired') {
|
||||
const s = await resolve(this.refreshExternalAccessToken(user));
|
||||
return resolve(s);
|
||||
}
|
||||
resolve(false);
|
||||
},
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
async refreshExternalAccessToken(user: User): Promise<any> {
|
||||
const bodyFormData = this.createAuthCodeFormData(
|
||||
user.external.refreshToken,
|
||||
'refresh_token',
|
||||
);
|
||||
const url = this.configService.get('SSO_TOKEN_URL');
|
||||
return new Promise((resolve) => {
|
||||
this.http.post<any>(url, bodyFormData).subscribe({
|
||||
next: async (response) => {
|
||||
user.external.accessToken = response.data.access_token;
|
||||
await this.userRepo.save(user);
|
||||
resolve(true);
|
||||
},
|
||||
error: () => {
|
||||
resolve(false);
|
||||
},
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
18
api/src/modules/role/role.controller.spec.ts
Normal file
18
api/src/modules/role/role.controller.spec.ts
Normal file
@@ -0,0 +1,18 @@
|
||||
import { Test, TestingModule } from '@nestjs/testing';
|
||||
import { RoleController } from './role.controller';
|
||||
|
||||
describe('RoleController', () => {
|
||||
let controller: RoleController;
|
||||
|
||||
beforeEach(async () => {
|
||||
const module: TestingModule = await Test.createTestingModule({
|
||||
controllers: [RoleController],
|
||||
}).compile();
|
||||
|
||||
controller = module.get<RoleController>(RoleController);
|
||||
});
|
||||
|
||||
it('should be defined', () => {
|
||||
expect(controller).toBeDefined();
|
||||
});
|
||||
});
|
||||
15
api/src/modules/role/role.controller.ts
Normal file
15
api/src/modules/role/role.controller.ts
Normal file
@@ -0,0 +1,15 @@
|
||||
import { Controller, Get, UseGuards } from '@nestjs/common';
|
||||
import { RoleService } from './role.service';
|
||||
import { AuthGuard } from 'src/core/guards/auth.guard';
|
||||
|
||||
@UseGuards(AuthGuard)
|
||||
@Controller('role')
|
||||
export class RoleController {
|
||||
|
||||
constructor(private readonly rolesService: RoleService) {}
|
||||
|
||||
@Get()
|
||||
getRoles() {
|
||||
return this.rolesService.getRoles();
|
||||
}
|
||||
}
|
||||
12
api/src/modules/role/role.module.ts
Normal file
12
api/src/modules/role/role.module.ts
Normal file
@@ -0,0 +1,12 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
import { RoleController } from './role.controller';
|
||||
import { RoleService } from './role.service';
|
||||
import { DatabaseModule } from 'src/shared/database/database.module';
|
||||
import { AuthModule } from '../auth/auth.module';
|
||||
|
||||
@Module({
|
||||
controllers: [RoleController],
|
||||
providers: [RoleService],
|
||||
imports: [ DatabaseModule, AuthModule ]
|
||||
})
|
||||
export class RoleModule {}
|
||||
18
api/src/modules/role/role.service.spec.ts
Normal file
18
api/src/modules/role/role.service.spec.ts
Normal file
@@ -0,0 +1,18 @@
|
||||
import { Test, TestingModule } from '@nestjs/testing';
|
||||
import { RoleService } from './role.service';
|
||||
|
||||
describe('RoleService', () => {
|
||||
let service: RoleService;
|
||||
|
||||
beforeEach(async () => {
|
||||
const module: TestingModule = await Test.createTestingModule({
|
||||
providers: [RoleService],
|
||||
}).compile();
|
||||
|
||||
service = module.get<RoleService>(RoleService);
|
||||
});
|
||||
|
||||
it('should be defined', () => {
|
||||
expect(service).toBeDefined();
|
||||
});
|
||||
});
|
||||
11
api/src/modules/role/role.service.ts
Normal file
11
api/src/modules/role/role.service.ts
Normal file
@@ -0,0 +1,11 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { RoleRepository } from 'src/model/repositories';
|
||||
|
||||
@Injectable()
|
||||
export class RoleService {
|
||||
constructor(private readonly rolesRepo: RoleRepository) {}
|
||||
|
||||
getRoles() {
|
||||
return this.rolesRepo.find();
|
||||
}
|
||||
}
|
||||
21
api/src/modules/user/user.controller.ts
Normal file
21
api/src/modules/user/user.controller.ts
Normal file
@@ -0,0 +1,21 @@
|
||||
import { Body, Controller, Get, Post, UseGuards } from '@nestjs/common';
|
||||
import { AuthGuard } from 'src/core/guards/auth.guard';
|
||||
import { UserService } from './user.service';
|
||||
import { User } from 'src/model/entitites';
|
||||
import { IUser } from 'src/model/interface';
|
||||
|
||||
@UseGuards(AuthGuard)
|
||||
@Controller('user')
|
||||
export class UserController {
|
||||
constructor(private readonly userService: UserService) {}
|
||||
|
||||
@Get()
|
||||
getUsers(): Promise<User[]> {
|
||||
return this.userService.getAllUsers();
|
||||
}
|
||||
|
||||
@Post()
|
||||
saveUser(@Body() user: IUser) {
|
||||
return this.userService.saveUser(user);
|
||||
}
|
||||
}
|
||||
12
api/src/modules/user/user.module.ts
Normal file
12
api/src/modules/user/user.module.ts
Normal file
@@ -0,0 +1,12 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
import { UserController } from './user.controller';
|
||||
import { UserService } from './user.service';
|
||||
import { AuthModule } from '../auth/auth.module';
|
||||
import { DatabaseModule } from 'src/shared/database/database.module';
|
||||
|
||||
@Module({
|
||||
controllers: [UserController],
|
||||
providers: [UserService],
|
||||
imports: [AuthModule, DatabaseModule],
|
||||
})
|
||||
export class UserModule {}
|
||||
26
api/src/modules/user/user.service.ts
Normal file
26
api/src/modules/user/user.service.ts
Normal file
@@ -0,0 +1,26 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { User } from 'src/model/entitites';
|
||||
import { IUser } from 'src/model/interface';
|
||||
import { RoleRepository, UserRepository } from 'src/model/repositories';
|
||||
|
||||
@Injectable()
|
||||
export class UserService {
|
||||
constructor(
|
||||
private readonly userRepo: UserRepository,
|
||||
private readonly roleRepo: RoleRepository,
|
||||
) {}
|
||||
|
||||
getAllUsers(): Promise<User[]> {
|
||||
return this.userRepo.find({
|
||||
relations: ['role'],
|
||||
where: [{ role: { name: 'user' } }, { role: { name: 'admin' } }],
|
||||
});
|
||||
}
|
||||
|
||||
async saveUser(user: IUser) {
|
||||
if (typeof user.role == 'string') {
|
||||
user.role = await this.roleRepo.findOneBy({ name: user.role });
|
||||
}
|
||||
return this.userRepo.save(user as any);
|
||||
}
|
||||
}
|
||||
@@ -1,10 +1,10 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
import { TypeOrmModule } from '@nestjs/typeorm';
|
||||
import { SSOUser, User } from 'src/model/entitites';
|
||||
import { SsoUserRepository, UserRepository } from 'src/model/repositories';
|
||||
import { Role, SSOUser, User } from 'src/model/entitites';
|
||||
import { RoleRepository, SsoUserRepository, UserRepository } from 'src/model/repositories';
|
||||
|
||||
const ENTITIES = [User, SSOUser];
|
||||
const REPOSITORIES = [UserRepository, SsoUserRepository];
|
||||
const ENTITIES = [User, SSOUser, Role];
|
||||
const REPOSITORIES = [UserRepository, SsoUserRepository, RoleRepository];
|
||||
|
||||
@Module({
|
||||
imports: [
|
||||
|
||||
Reference in New Issue
Block a user