backend
This commit is contained in:
@@ -13,4 +13,15 @@ JWT_EXPIRES_IN=10m
|
|||||||
JWT_REFRESH_EXPIRES_IN=1w
|
JWT_REFRESH_EXPIRES_IN=1w
|
||||||
SESSION_SECRET=MYSESSIONSECRET2024
|
SESSION_SECRET=MYSESSIONSECRET2024
|
||||||
|
|
||||||
APPLICATIONPORT=5000
|
APPLICATIONPORT=5000
|
||||||
|
|
||||||
|
# Mail
|
||||||
|
MAILER_HOST=smtp.smtp.de
|
||||||
|
MAILER_PORT=465
|
||||||
|
MAILER_SECURE=true
|
||||||
|
MAILER_USERNAME=xxxx
|
||||||
|
MAILER_PASSWORD=xxxxx
|
||||||
|
MAILER_FROM='"No Reply" <noreply@example.com>'
|
||||||
|
|
||||||
|
# Client
|
||||||
|
CLIENT_URL=http://localhost:4200
|
||||||
2444
idp/package-lock.json
generated
2444
idp/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -20,6 +20,7 @@
|
|||||||
"test:e2e": "jest --config ./test/jest-e2e.json"
|
"test:e2e": "jest --config ./test/jest-e2e.json"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@nestjs-modules/mailer": "^2.0.2",
|
||||||
"@nestjs/common": "^10.0.0",
|
"@nestjs/common": "^10.0.0",
|
||||||
"@nestjs/config": "^3.2.3",
|
"@nestjs/config": "^3.2.3",
|
||||||
"@nestjs/core": "^10.0.0",
|
"@nestjs/core": "^10.0.0",
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import { LoggerModule } from './core/logger.module';
|
|||||||
import { SessionMiddleware } from './core/session.middleware';
|
import { SessionMiddleware } from './core/session.middleware';
|
||||||
import { ClientModule } from './client/client.module';
|
import { ClientModule } from './client/client.module';
|
||||||
import { ApplicationModule } from './application/application.module';
|
import { ApplicationModule } from './application/application.module';
|
||||||
|
import { MailModule } from './application/mail/mail.module';
|
||||||
@Module({
|
@Module({
|
||||||
imports: [
|
imports: [
|
||||||
AuthModule,
|
AuthModule,
|
||||||
@@ -37,6 +38,7 @@ import { ApplicationModule } from './application/application.module';
|
|||||||
}),
|
}),
|
||||||
}),
|
}),
|
||||||
ApplicationModule,
|
ApplicationModule,
|
||||||
|
MailModule,
|
||||||
// TypeOrmModule.forRoot({
|
// TypeOrmModule.forRoot({
|
||||||
// type: 'mysql',
|
// type: 'mysql',
|
||||||
// host: '85.215.137.185', // MySQL Hostname
|
// host: '85.215.137.185', // MySQL Hostname
|
||||||
|
|||||||
@@ -3,10 +3,11 @@ import { ApplicationController } from './application.controller';
|
|||||||
import { UserModule } from './user/user.module';
|
import { UserModule } from './user/user.module';
|
||||||
import { LoggerModule } from 'src/core/logger.module';
|
import { LoggerModule } from 'src/core/logger.module';
|
||||||
import { SecureModule } from 'src/core/secure/secure.module';
|
import { SecureModule } from 'src/core/secure/secure.module';
|
||||||
|
import { MailModule } from './mail/mail.module';
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
controllers: [ApplicationController],
|
controllers: [ApplicationController],
|
||||||
providers: [],
|
providers: [],
|
||||||
imports: [LoggerModule, UserModule, SecureModule],
|
imports: [LoggerModule, UserModule, SecureModule, MailModule],
|
||||||
})
|
})
|
||||||
export class ApplicationModule {}
|
export class ApplicationModule {}
|
||||||
|
|||||||
41
idp/src/application/mail/mail.module.ts
Normal file
41
idp/src/application/mail/mail.module.ts
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
import { Module } from '@nestjs/common';
|
||||||
|
import { DatabaseModule } from 'src/core/database/database.module';
|
||||||
|
import { MailerModule } from '@nestjs-modules/mailer';
|
||||||
|
import { join } from 'path';
|
||||||
|
import { ConfigModule, ConfigService } from '@nestjs/config';
|
||||||
|
import { HandlebarsAdapter } from '@nestjs-modules/mailer/dist/adapters/handlebars.adapter';
|
||||||
|
import { MailService } from './mail.service';
|
||||||
|
|
||||||
|
@Module({
|
||||||
|
imports: [
|
||||||
|
DatabaseModule,
|
||||||
|
MailerModule.forRootAsync({
|
||||||
|
imports: [ConfigModule],
|
||||||
|
inject: [ConfigService],
|
||||||
|
useFactory: async (config: ConfigService) => ({
|
||||||
|
transport: {
|
||||||
|
host: config.get('MAILER_HOST'),
|
||||||
|
secure: config.get('MAILER_SECURE'),
|
||||||
|
port: config.get('MAILER_PORT'),
|
||||||
|
auth: {
|
||||||
|
user: config.get('MAILER_USERNAME'),
|
||||||
|
pass: config.get('MAILER_PASSWORD'),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
defaults: {
|
||||||
|
from: config.get('MAILER_FROM'),
|
||||||
|
},
|
||||||
|
template: {
|
||||||
|
dir: join(__dirname, '../../../templates'),
|
||||||
|
adapter: new HandlebarsAdapter(), // or new PugAdapter() or new EjsAdapter()
|
||||||
|
options: {
|
||||||
|
strict: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
providers: [MailService],
|
||||||
|
exports: [MailService],
|
||||||
|
})
|
||||||
|
export class MailModule {}
|
||||||
18
idp/src/application/mail/mail.service.spec.ts
Normal file
18
idp/src/application/mail/mail.service.spec.ts
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
import { Test, TestingModule } from '@nestjs/testing';
|
||||||
|
import { MailService } from './mail.service';
|
||||||
|
|
||||||
|
describe('MailService', () => {
|
||||||
|
let service: MailService;
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
const module: TestingModule = await Test.createTestingModule({
|
||||||
|
providers: [MailService],
|
||||||
|
}).compile();
|
||||||
|
|
||||||
|
service = module.get<MailService>(MailService);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should be defined', () => {
|
||||||
|
expect(service).toBeDefined();
|
||||||
|
});
|
||||||
|
});
|
||||||
33
idp/src/application/mail/mail.service.ts
Normal file
33
idp/src/application/mail/mail.service.ts
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
import { Injectable } from '@nestjs/common';
|
||||||
|
import { ConfigService } from '@nestjs/config';
|
||||||
|
import { MailerService } from '@nestjs-modules/mailer';
|
||||||
|
import { ResetPWMailConfig } from '../model/mailconfig.interface';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class MailService {
|
||||||
|
constructor(
|
||||||
|
private mailerService: MailerService,
|
||||||
|
private readonly configService: ConfigService,
|
||||||
|
) {
|
||||||
|
// this.sendMail();
|
||||||
|
}
|
||||||
|
|
||||||
|
sendResetMail(config: ResetPWMailConfig) {
|
||||||
|
let baseUrl = this.configService.get<string>('CLIENT_URL');
|
||||||
|
if (baseUrl.endsWith('/'))
|
||||||
|
baseUrl = baseUrl.substring(0, baseUrl.length - 1);
|
||||||
|
|
||||||
|
baseUrl += '/' + config.url + '?resetcode=' + config.code;
|
||||||
|
|
||||||
|
this.mailerService.sendMail({
|
||||||
|
to: 'mail@bastian-wagner.de',
|
||||||
|
from: this.configService.get<string>('MAILER_FROM'),
|
||||||
|
subject: 'Passwort zurücksetzen',
|
||||||
|
template: './pw-reset',
|
||||||
|
context: {
|
||||||
|
name: config.name,
|
||||||
|
resetLink: baseUrl,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
6
idp/src/application/model/mailconfig.interface.ts
Normal file
6
idp/src/application/model/mailconfig.interface.ts
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
export interface ResetPWMailConfig {
|
||||||
|
to: string;
|
||||||
|
code: string;
|
||||||
|
url: string;
|
||||||
|
name: string;
|
||||||
|
}
|
||||||
@@ -1,11 +1,20 @@
|
|||||||
import { Controller, Get, UseGuards } from '@nestjs/common';
|
import { Controller, Get, Req, UseGuards } from '@nestjs/common';
|
||||||
import { AuthGuard } from 'src/core/auth.guard';
|
import { UserService } from './user.service';
|
||||||
|
import { AuthGuard, Roles, RolesGuard } from 'src/core/secure/guards';
|
||||||
|
|
||||||
@UseGuards(AuthGuard)
|
@UseGuards(AuthGuard, RolesGuard)
|
||||||
@Controller('app/user')
|
@Controller('app/user')
|
||||||
export class UserController {
|
export class UserController {
|
||||||
|
constructor(private userService: UserService) {}
|
||||||
|
|
||||||
@Get()
|
@Get()
|
||||||
getIt() {
|
getIt() {
|
||||||
return 'secure';
|
return 'secure';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Roles('admin')
|
||||||
|
@Get('clients')
|
||||||
|
getClients(@Req() req: any) {
|
||||||
|
return this.userService.getUserClients(req['user']);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,12 @@
|
|||||||
import { Module } from '@nestjs/common';
|
import { Module } from '@nestjs/common';
|
||||||
import { UserController } from './user.controller';
|
import { UserController } from './user.controller';
|
||||||
import { SecureModule } from 'src/core/secure/secure.module';
|
import { SecureModule } from 'src/core/secure/secure.module';
|
||||||
|
import { UserService } from './user.service';
|
||||||
|
import { ClientRepository } from 'src/model/client.entity';
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
controllers: [UserController],
|
controllers: [UserController],
|
||||||
imports: [SecureModule],
|
imports: [SecureModule],
|
||||||
|
providers: [UserService, ClientRepository],
|
||||||
})
|
})
|
||||||
export class UserModule {}
|
export class UserModule {}
|
||||||
|
|||||||
18
idp/src/application/user/user.service.spec.ts
Normal file
18
idp/src/application/user/user.service.spec.ts
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
import { Test, TestingModule } from '@nestjs/testing';
|
||||||
|
import { UserService } from './user.service';
|
||||||
|
|
||||||
|
describe('UserService', () => {
|
||||||
|
let service: UserService;
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
const module: TestingModule = await Test.createTestingModule({
|
||||||
|
providers: [UserService],
|
||||||
|
}).compile();
|
||||||
|
|
||||||
|
service = module.get<UserService>(UserService);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should be defined', () => {
|
||||||
|
expect(service).toBeDefined();
|
||||||
|
});
|
||||||
|
});
|
||||||
13
idp/src/application/user/user.service.ts
Normal file
13
idp/src/application/user/user.service.ts
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
import { Injectable } from '@nestjs/common';
|
||||||
|
import { ClientRepository } from 'src/model/client.entity';
|
||||||
|
import { User } from 'src/model/user.entity';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class UserService {
|
||||||
|
constructor(private clientRepository: ClientRepository) {}
|
||||||
|
|
||||||
|
getUserClients(user: User) {
|
||||||
|
console.log(user.id);
|
||||||
|
return this.clientRepository.find();
|
||||||
|
}
|
||||||
|
}
|
||||||
26
idp/src/core/database/database.module.ts
Normal file
26
idp/src/core/database/database.module.ts
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
import { Module } from '@nestjs/common';
|
||||||
|
import { TypeOrmModule } from '@nestjs/typeorm';
|
||||||
|
import {
|
||||||
|
AuthorizationCode,
|
||||||
|
AuthorizationCodeRepository,
|
||||||
|
} from 'src/model/auth-code.entity';
|
||||||
|
import { Client, ClientRepository } from 'src/model/client.entity';
|
||||||
|
import { RedirectUri } from 'src/model/redirect-uri.entity';
|
||||||
|
import { SessionKey, SessionKeyRepository } from 'src/model/session-key.entity';
|
||||||
|
import { User, UserRepository } from 'src/model/user.entity';
|
||||||
|
|
||||||
|
const ENTITIES = [User, Client, RedirectUri, AuthorizationCode, SessionKey];
|
||||||
|
const REPOSITORIES = [
|
||||||
|
UserRepository,
|
||||||
|
ClientRepository,
|
||||||
|
AuthorizationCodeRepository,
|
||||||
|
SessionKeyRepository,
|
||||||
|
];
|
||||||
|
|
||||||
|
@Module({
|
||||||
|
imports: [TypeOrmModule.forFeature(ENTITIES)],
|
||||||
|
controllers: [],
|
||||||
|
providers: [...REPOSITORIES],
|
||||||
|
exports: [...REPOSITORIES],
|
||||||
|
})
|
||||||
|
export class DatabaseModule {}
|
||||||
@@ -2,11 +2,12 @@ import { Module } from '@nestjs/common';
|
|||||||
import { Log } from 'src/model/log.entity';
|
import { Log } from 'src/model/log.entity';
|
||||||
import { CustomLogger } from './custom.logger';
|
import { CustomLogger } from './custom.logger';
|
||||||
import { TypeOrmModule } from '@nestjs/typeorm';
|
import { TypeOrmModule } from '@nestjs/typeorm';
|
||||||
|
import { DatabaseModule } from './database/database.module';
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
providers: [CustomLogger],
|
providers: [CustomLogger],
|
||||||
controllers: [],
|
controllers: [],
|
||||||
imports: [TypeOrmModule.forFeature([Log])],
|
imports: [TypeOrmModule.forFeature([Log]), DatabaseModule],
|
||||||
exports: [CustomLogger],
|
exports: [CustomLogger],
|
||||||
})
|
})
|
||||||
export class LoggerModule {}
|
export class LoggerModule {}
|
||||||
|
|||||||
3
idp/src/core/secure/guards/index.ts
Normal file
3
idp/src/core/secure/guards/index.ts
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
export * from './role.decorator';
|
||||||
|
export * from './auth.guard';
|
||||||
|
export * from './roles.guard';
|
||||||
3
idp/src/core/secure/guards/role.decorator.ts
Normal file
3
idp/src/core/secure/guards/role.decorator.ts
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
import { SetMetadata } from '@nestjs/common';
|
||||||
|
|
||||||
|
export const Roles = (...roles: string[]) => SetMetadata('roles', roles);
|
||||||
18
idp/src/core/secure/guards/roles.guard.ts
Normal file
18
idp/src/core/secure/guards/roles.guard.ts
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
import { Injectable, CanActivate, ExecutionContext } from '@nestjs/common';
|
||||||
|
import { Reflector } from '@nestjs/core';
|
||||||
|
import { User } from 'src/model/user.entity';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class RolesGuard implements CanActivate {
|
||||||
|
constructor(private reflector: Reflector) {}
|
||||||
|
|
||||||
|
canActivate(context: ExecutionContext): boolean {
|
||||||
|
const roles = this.reflector.get<string[]>('roles', context.getHandler());
|
||||||
|
if (!roles) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
const request = context.switchToHttp().getRequest();
|
||||||
|
const user: User = request.user;
|
||||||
|
return roles.includes(user.role.name);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,20 +1,13 @@
|
|||||||
import { Module } from '@nestjs/common';
|
import { Module } from '@nestjs/common';
|
||||||
import { ConfigModule, ConfigService } from '@nestjs/config';
|
import { ConfigModule, ConfigService } from '@nestjs/config';
|
||||||
import { JwtModule } from '@nestjs/jwt';
|
import { JwtModule } from '@nestjs/jwt';
|
||||||
import { TypeOrmModule } from '@nestjs/typeorm';
|
|
||||||
import { NestjsFormDataModule } from 'nestjs-form-data';
|
import { NestjsFormDataModule } from 'nestjs-form-data';
|
||||||
import { ClientService } from 'src/client/client.service';
|
import { ClientService } from 'src/client/client.service';
|
||||||
import {
|
|
||||||
AuthorizationCode,
|
|
||||||
AuthorizationCodeRepository,
|
|
||||||
} from 'src/model/auth-code.entity';
|
|
||||||
import { Client, ClientRepository } from 'src/model/client.entity';
|
|
||||||
import { RedirectUri } from 'src/model/redirect-uri.entity';
|
|
||||||
import { SessionKey, SessionKeyRepository } from 'src/model/session-key.entity';
|
|
||||||
import { User, UserRepository } from 'src/model/user.entity';
|
|
||||||
import { UsersService } from 'src/users/users.service';
|
import { UsersService } from 'src/users/users.service';
|
||||||
import { AuthGuard } from '../auth.guard';
|
|
||||||
import { LoggerModule } from '../logger.module';
|
import { LoggerModule } from '../logger.module';
|
||||||
|
import { AuthGuard } from './guards/auth.guard';
|
||||||
|
import { DatabaseModule } from '../database/database.module';
|
||||||
|
import { RolesGuard } from './guards/roles.guard';
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
imports: [
|
imports: [
|
||||||
@@ -27,24 +20,10 @@ import { LoggerModule } from '../logger.module';
|
|||||||
}),
|
}),
|
||||||
}),
|
}),
|
||||||
NestjsFormDataModule,
|
NestjsFormDataModule,
|
||||||
TypeOrmModule.forFeature([
|
DatabaseModule,
|
||||||
User,
|
|
||||||
Client,
|
|
||||||
RedirectUri,
|
|
||||||
AuthorizationCode,
|
|
||||||
SessionKey,
|
|
||||||
]),
|
|
||||||
LoggerModule,
|
LoggerModule,
|
||||||
],
|
],
|
||||||
providers: [
|
providers: [UsersService, ClientService, AuthGuard, RolesGuard],
|
||||||
UsersService,
|
exports: [JwtModule, UsersService, AuthGuard, RolesGuard],
|
||||||
ClientService,
|
|
||||||
UserRepository,
|
|
||||||
ClientRepository,
|
|
||||||
AuthorizationCodeRepository,
|
|
||||||
SessionKeyRepository,
|
|
||||||
AuthGuard,
|
|
||||||
],
|
|
||||||
exports: [JwtModule, UsersService, AuthGuard],
|
|
||||||
})
|
})
|
||||||
export class SecureModule {}
|
export class SecureModule {}
|
||||||
|
|||||||
88
idp/templates/pw-reset.hbs
Normal file
88
idp/templates/pw-reset.hbs
Normal file
@@ -0,0 +1,88 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<title>Passwort zurücksetzen</title>
|
||||||
|
<style>
|
||||||
|
body {
|
||||||
|
font-family: Arial, sans-serif;
|
||||||
|
background-color: #f4f4f4;
|
||||||
|
color: #333;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
.container {
|
||||||
|
max-width: 600px;
|
||||||
|
margin: 20px auto;
|
||||||
|
background: #fff;
|
||||||
|
padding: 20px;
|
||||||
|
border-radius: 8px;
|
||||||
|
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
|
||||||
|
}
|
||||||
|
.header {
|
||||||
|
background: #007bff;
|
||||||
|
color: #fff;
|
||||||
|
padding: 20px;
|
||||||
|
text-align: center;
|
||||||
|
border-radius: 8px 8px 0 0;
|
||||||
|
}
|
||||||
|
.header h1 {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
.content {
|
||||||
|
padding: 20px;
|
||||||
|
}
|
||||||
|
.content p {
|
||||||
|
line-height: 1.6;
|
||||||
|
}
|
||||||
|
.btn {
|
||||||
|
display: inline-block;
|
||||||
|
padding: 10px 20px;
|
||||||
|
margin: 20px 0;
|
||||||
|
font-size: 16px;
|
||||||
|
color: #fff;
|
||||||
|
background-color: #007bff;
|
||||||
|
text-decoration: none;
|
||||||
|
border-radius: 5px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
.link {
|
||||||
|
word-break: break-all;
|
||||||
|
color: #007bff;
|
||||||
|
}
|
||||||
|
.footer {
|
||||||
|
text-align: center;
|
||||||
|
font-size: 0.9em;
|
||||||
|
color: #666;
|
||||||
|
margin-top: 20px;
|
||||||
|
padding-top: 10px;
|
||||||
|
border-top: 1px solid #ddd;
|
||||||
|
}
|
||||||
|
.social-icons {
|
||||||
|
margin: 10px 0;
|
||||||
|
}
|
||||||
|
.social-icons img {
|
||||||
|
width: 30px;
|
||||||
|
height: 30px;
|
||||||
|
margin: 0 5px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="container">
|
||||||
|
<div class="header">
|
||||||
|
<h1>Passwort zurücksetzen</h1>
|
||||||
|
</div>
|
||||||
|
<div class="content">
|
||||||
|
<p>Hallo {{name}},</p>
|
||||||
|
<p>du hast eine Anfrage zum Zurücksetzen deines Passworts gestellt. Bitte klicke auf den folgenden Button, um dein Passwort zurückzusetzen:</p>
|
||||||
|
<p style="text-align: center;">
|
||||||
|
<a href="{{resetLink}}" class="btn">Passwort zurücksetzen</a>
|
||||||
|
</p>
|
||||||
|
<p style="margin-top: 12px;">Falls der Button nicht funktioniert, kannst du auch den folgenden Link in deinen Browser kopieren:</p>
|
||||||
|
<p class="link">{{resetLink}}</p>
|
||||||
|
<p>Dieser Link ist 24 Stunden gültig. Wenn du diese Anfrage nicht gestellt hast, ignoriere diese E-Mail bitte. Dein Passwort bleibt unverändert.</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -2,9 +2,10 @@ import { ApplicationConfig, provideZoneChangeDetection } from '@angular/core';
|
|||||||
import { provideRouter } from '@angular/router';
|
import { provideRouter } from '@angular/router';
|
||||||
|
|
||||||
import { routes } from './app.routes';
|
import { routes } from './app.routes';
|
||||||
import { provideHttpClient } from '@angular/common/http';
|
import { provideHttpClient, withInterceptors } from '@angular/common/http';
|
||||||
import { provideHotToastConfig } from '@ngxpert/hot-toast';
|
import { provideHotToastConfig } from '@ngxpert/hot-toast';
|
||||||
|
import { authInterceptor } from './core/interceptor/auth.interceptor';
|
||||||
|
|
||||||
export const appConfig: ApplicationConfig = {
|
export const appConfig: ApplicationConfig = {
|
||||||
providers: [provideZoneChangeDetection({ eventCoalescing: true }), provideRouter(routes), provideHttpClient(), provideHotToastConfig(),]
|
providers: [provideZoneChangeDetection({ eventCoalescing: true }), provideRouter(routes), provideHttpClient(withInterceptors([authInterceptor])), provideHotToastConfig(),]
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -7,6 +7,6 @@ import { SessionKeyGuard } from './core/guards/session-key.guard';
|
|||||||
export const routes: Routes = [
|
export const routes: Routes = [
|
||||||
{ path: 'login', component: LoginComponent, canActivate: [SessionKeyGuard] },
|
{ path: 'login', component: LoginComponent, canActivate: [SessionKeyGuard] },
|
||||||
{ path: 'register', component: RegisterComponent },
|
{ path: 'register', component: RegisterComponent },
|
||||||
{ path: 'dashboard', component: DashboardComponent },
|
{ path: 'dashboard', component: DashboardComponent, canActivate: [SessionKeyGuard] },
|
||||||
{ path: '', component: LoginComponent, canActivate: [SessionKeyGuard] },
|
{ path: '', component: LoginComponent, canActivate: [SessionKeyGuard] },
|
||||||
];
|
];
|
||||||
|
|||||||
@@ -19,6 +19,8 @@ export class SessionKeyGuard {
|
|||||||
private client_id;
|
private client_id;
|
||||||
async canActivate(route: ActivatedRouteSnapshot):
|
async canActivate(route: ActivatedRouteSnapshot):
|
||||||
Promise<boolean> {
|
Promise<boolean> {
|
||||||
|
|
||||||
|
if (this.userService.user) { return true; }
|
||||||
this.isLoading = true;
|
this.isLoading = true;
|
||||||
|
|
||||||
const success = await this.loginWithSessionId(route);
|
const success = await this.loginWithSessionId(route);
|
||||||
@@ -68,7 +70,7 @@ export class SessionKeyGuard {
|
|||||||
}
|
}
|
||||||
} else if (data["id"] != null) {
|
} else if (data["id"] != null) {
|
||||||
this.userService.user = data as User;
|
this.userService.user = data as User;
|
||||||
resolve(false);
|
resolve(true);
|
||||||
this.navigateToDashboard();
|
this.navigateToDashboard();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
20
idp_client/src/app/core/interceptor/auth.interceptor.ts
Normal file
20
idp_client/src/app/core/interceptor/auth.interceptor.ts
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
import { HttpInterceptorFn, HttpRequest, HttpHandlerFn, HttpEvent } from "@angular/common/http";
|
||||||
|
import { inject } from "@angular/core";
|
||||||
|
import { Observable } from "rxjs";
|
||||||
|
import { UserService } from "../../auth/user.service";
|
||||||
|
|
||||||
|
export const authInterceptor: HttpInterceptorFn = (
|
||||||
|
req: HttpRequest<any>,
|
||||||
|
next: HttpHandlerFn
|
||||||
|
): Observable<HttpEvent<any>> => {
|
||||||
|
const userService = inject(UserService);
|
||||||
|
const token = userService.user?.accessToken;
|
||||||
|
if (token) {
|
||||||
|
const cloned = req.clone({
|
||||||
|
headers: req.headers.set('Authorization', `Bearer ${token}`),
|
||||||
|
});
|
||||||
|
return next(cloned);
|
||||||
|
} else {
|
||||||
|
return next(req);
|
||||||
|
}
|
||||||
|
};
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
import { Component, inject, OnInit } from '@angular/core';
|
import { Component, inject, OnInit } from '@angular/core';
|
||||||
import { UserService } from '../auth/user.service';
|
import { UserService } from '../auth/user.service';
|
||||||
import { Router } from '@angular/router';
|
import { Router } from '@angular/router';
|
||||||
|
import { HttpClient } from '@angular/common/http';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-dashboard',
|
selector: 'app-dashboard',
|
||||||
@@ -13,12 +14,24 @@ export class DashboardComponent implements OnInit {
|
|||||||
|
|
||||||
private userService: UserService = inject(UserService);
|
private userService: UserService = inject(UserService);
|
||||||
private router: Router = inject(Router);
|
private router: Router = inject(Router);
|
||||||
|
private http: HttpClient = inject(HttpClient);
|
||||||
|
|
||||||
|
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
|
console.log("ONINIT")
|
||||||
if (!this.userService.user) {
|
if (!this.userService.user) {
|
||||||
|
console.log("REDIRECT")
|
||||||
this.router.navigateByUrl("/login");
|
this.router.navigateByUrl("/login");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.load();
|
||||||
|
}
|
||||||
|
|
||||||
|
load() {
|
||||||
|
this.http.get('api/app/user/clients').subscribe(res => {
|
||||||
|
console.log(res)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user