Rework (#2)
* spec entfernt * wip * wip * wip * wip * wip * rework * done --------- Co-authored-by: Bastian Wagner <bastian.wagner@softconcis.de>
This commit is contained in:
10
idp/src/application/client/appclient.service.ts
Normal file
10
idp/src/application/client/appclient.service.ts
Normal file
@@ -0,0 +1,10 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { ClientRepository, RedirectRepository } from 'src/model';
|
||||
import { ClientBaseService } from 'src/shared/client/client.base.service';
|
||||
|
||||
@Injectable()
|
||||
export class AppClientService extends ClientBaseService {
|
||||
constructor(clientRepo: ClientRepository, uriRepo: RedirectRepository) {
|
||||
super(clientRepo, uriRepo);
|
||||
}
|
||||
}
|
||||
@@ -1,18 +1,16 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { ConfigService } from '@nestjs/config';
|
||||
import { MailerService } from '@nestjs-modules/mailer';
|
||||
import { ResetPWMailConfig } from '../model/mailconfig.interface';
|
||||
import { IResetPWMailConfig } from 'src/model';
|
||||
|
||||
@Injectable()
|
||||
export class MailService {
|
||||
constructor(
|
||||
private mailerService: MailerService,
|
||||
private readonly configService: ConfigService,
|
||||
) {
|
||||
// this.sendMail();
|
||||
}
|
||||
) {}
|
||||
|
||||
sendResetMail(config: ResetPWMailConfig) {
|
||||
sendResetMail(config: IResetPWMailConfig) {
|
||||
let baseUrl = this.configService.get<string>('CLIENT_URL');
|
||||
if (baseUrl.endsWith('/'))
|
||||
baseUrl = baseUrl.substring(0, baseUrl.length - 1);
|
||||
@@ -20,7 +18,7 @@ export class MailService {
|
||||
baseUrl += '/' + config.url + '?resetcode=' + config.code;
|
||||
|
||||
this.mailerService.sendMail({
|
||||
to: 'mail@bastian-wagner.de',
|
||||
to: config.to,
|
||||
from: this.configService.get<string>('MAILER_FROM'),
|
||||
subject: 'Passwort zurücksetzen',
|
||||
template: './pw-reset',
|
||||
|
||||
@@ -8,18 +8,19 @@ import {
|
||||
Req,
|
||||
UseGuards,
|
||||
} from '@nestjs/common';
|
||||
import { APPUserService } from './user.service';
|
||||
|
||||
import { AppUserService } from './user.service';
|
||||
import { AuthGuard, Roles, RolesGuard } from 'src/shared/secure/guards';
|
||||
import { IAuthenticatedRequest, Client, RedirectUri } from 'src/model';
|
||||
import { CreateClientDto } from 'src/model/dto/create-client.dto';
|
||||
import { ClientService } from 'src/idp/client/client.service';
|
||||
import { AppClientService } from '../client/appclient.service';
|
||||
|
||||
@UseGuards(AuthGuard, RolesGuard)
|
||||
@Controller('app/user')
|
||||
export class UserController {
|
||||
constructor(
|
||||
private userService: APPUserService,
|
||||
private clientService: ClientService,
|
||||
private userService: AppUserService,
|
||||
private clientService: AppClientService,
|
||||
) {}
|
||||
|
||||
@Get()
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
import { UserController } from './user.controller';
|
||||
import { APPUserService } from './user.service';
|
||||
import { AppUserService } from './user.service';
|
||||
import { SharedModule } from 'src/shared/shared.module';
|
||||
import { SecureModule } from 'src/shared/secure/secure.module';
|
||||
import { AppClientService } from '../client/appclient.service';
|
||||
|
||||
@Module({
|
||||
controllers: [UserController],
|
||||
imports: [SecureModule, SharedModule],
|
||||
providers: [APPUserService],
|
||||
providers: [AppUserService, AppClientService],
|
||||
})
|
||||
export class UserModule {}
|
||||
|
||||
@@ -2,7 +2,7 @@ import { Injectable } from '@nestjs/common';
|
||||
import { ClientRepository, LogRepository, User, Client } from 'src/model';
|
||||
|
||||
@Injectable()
|
||||
export class APPUserService {
|
||||
export class AppUserService {
|
||||
constructor(
|
||||
private clientRepository: ClientRepository,
|
||||
private logRepository: LogRepository,
|
||||
|
||||
@@ -19,6 +19,9 @@ export class ActivityLog {
|
||||
@Column({ default: 0, type: 'int' })
|
||||
loginCounter: number;
|
||||
|
||||
@Column({ default: 0, type: 'int', name: 'session_login' })
|
||||
loginWithSessionCounter: number;
|
||||
|
||||
@Column({ default: 0, type: 'int' })
|
||||
applicationLogin: number;
|
||||
|
||||
@@ -47,6 +50,12 @@ export class ActivityLogRepository extends Repository<ActivityLog> {
|
||||
return this.save(entity);
|
||||
}
|
||||
|
||||
async logSavedLogin(): Promise<ActivityLog> {
|
||||
const entity = await this.getTodaysActivityLog();
|
||||
entity.loginWithSessionCounter += 1;
|
||||
return this.save(entity);
|
||||
}
|
||||
|
||||
async logLogin(): Promise<ActivityLog> {
|
||||
const entity = await this.getTodaysActivityLog();
|
||||
entity.loginCounter += 1;
|
||||
|
||||
@@ -1,2 +1,3 @@
|
||||
export * from './authenticated.request';
|
||||
export * from './logger.interface';
|
||||
export * from './mailconfig.interface';
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
export interface ResetPWMailConfig {
|
||||
export interface IResetPWMailConfig {
|
||||
to: string;
|
||||
code: string;
|
||||
url: string;
|
||||
@@ -126,15 +126,12 @@ export class UsersService {
|
||||
if (getUserAccessToken) {
|
||||
user.accessToken = this.createAccessToken(user);
|
||||
user.refreshToken = this.createRefreshToken(user);
|
||||
// this.logger.log(
|
||||
// `User logged in with code on client ${clientId}`,
|
||||
// 'systemlogin',
|
||||
// );
|
||||
return user;
|
||||
}
|
||||
|
||||
const token = await this.createAuthToken(user, client);
|
||||
this.logger.log(`User logged in with code on client ${clientId}`, 'login');
|
||||
this.activityRepo.logSavedLogin();
|
||||
return token;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
<h3 matDialogTitle>Client Redirect-URIs</h3>
|
||||
<div mat-dialog-content class="content">
|
||||
<div class="mat-body" style="margin: 0 4px;">Trage hier alle Redirect URIS ein. Sie müssen mit dem gesendeten Parameter exakt überein stimmen.</div>
|
||||
@for (uri of client.redirectUris; track $index) {
|
||||
<div class="admin__item flex-row">
|
||||
<span class="admin__name">{{ uri.uri }}</span>
|
||||
@if(client.redirectUris.length > 1) {
|
||||
<button mat-raised-button color="warn" class="remove_btn" (click)="removeUri(uri)" ><mat-icon>delete</mat-icon></button>
|
||||
<button mat-button color="warn" class="remove_btn" (click)="removeUri(uri)" ><mat-icon>delete</mat-icon></button>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
|
||||
@@ -17,5 +17,5 @@ mat-icon {
|
||||
|
||||
.remove_btn {
|
||||
min-width: 0;
|
||||
padding: 0 14px;
|
||||
padding: 0 12px;
|
||||
}
|
||||
@@ -34,7 +34,7 @@
|
||||
<button mat-raised-button (click)="create()" [disabled]="createClient.invalid || isSaving">
|
||||
<div class="flex-row">
|
||||
<mat-spinner [diameter]="16" *ngIf="isSaving"></mat-spinner>
|
||||
<div>Next</div>
|
||||
<div>Weiter</div>
|
||||
</div>
|
||||
</button>
|
||||
</mat-step>
|
||||
@@ -44,6 +44,9 @@
|
||||
@if (client && client.admins) {
|
||||
<app-client-admins [client]="client" ></app-client-admins>
|
||||
}
|
||||
<button mat-raised-button mat-dialog-close="" [disabled]="isSaving">
|
||||
Schließen
|
||||
</button>
|
||||
</div>
|
||||
</mat-step>
|
||||
</mat-stepper>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
form {
|
||||
form, .admin_container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 24px;
|
||||
@@ -13,6 +13,7 @@ form {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
mat-dialog-content {
|
||||
mat-dialog-content, app-client-admins {
|
||||
flex: 1 1 auto;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { HttpClient } from '@angular/common/http';
|
||||
import { Component, inject, ViewChild } from '@angular/core';
|
||||
import { Component, EventEmitter, inject, Output, ViewChild } from '@angular/core';
|
||||
import { FormControl, FormGroup, FormsModule, ReactiveFormsModule, Validators } from '@angular/forms';
|
||||
import { MatButtonModule } from '@angular/material/button';
|
||||
import { MatDialogModule } from '@angular/material/dialog';
|
||||
@@ -29,6 +29,8 @@ export class CreateClientComponent {
|
||||
|
||||
@ViewChild('stepper') stepper: MatStepper;
|
||||
|
||||
@Output('oncreate') createdClient = new EventEmitter();
|
||||
|
||||
createClient = new FormGroup({
|
||||
clientName: new FormControl(null, [Validators.required, Validators.minLength(4), Validators.maxLength(200)]),
|
||||
clientSecret: new FormControl(null, [Validators.required, Validators.minLength(4), Validators.maxLength(200)]),
|
||||
@@ -55,11 +57,11 @@ export class CreateClientComponent {
|
||||
)
|
||||
.subscribe({
|
||||
next: data => {
|
||||
console.log(this.stepper)
|
||||
this.client = data;
|
||||
this.createClient.enable();
|
||||
this.stepper.next();
|
||||
this.isSaving = false;
|
||||
this.createdClient.emit();
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
@@ -14,12 +14,13 @@
|
||||
flex-direction: column;
|
||||
}
|
||||
.card-container__list{
|
||||
margin: 0 auto;
|
||||
margin: -12px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 12px;
|
||||
width: 500px;
|
||||
overflow: auto;
|
||||
padding: 12px;
|
||||
}
|
||||
|
||||
.create-container{
|
||||
@@ -70,10 +71,15 @@
|
||||
background-position: center;
|
||||
background-size: 20px;
|
||||
background-repeat: no-repeat;
|
||||
border-radius: 4px;
|
||||
border-radius: 8px;
|
||||
transition: all 0.2s ease-in-out;
|
||||
|
||||
&:hover {
|
||||
background-color: #ccc;
|
||||
background-color: #e0e0e0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.deleting {
|
||||
box-shadow: 0px 2px 4px -1px rgb(255 0 0 / 20%), 0px 4px 5px 0px rgb(255 0 0 / 14%), 0px 1px 10px 0px rgb(255 0 0 / 12%);
|
||||
}
|
||||
@@ -65,9 +65,12 @@ export class DashboardComponent implements OnInit {
|
||||
}
|
||||
|
||||
createClient() {
|
||||
this.dialog.open(CreateClientComponent, {
|
||||
const ref = this.dialog.open(CreateClientComponent, {
|
||||
panelClass: 'create-client__dialog'
|
||||
})
|
||||
ref.componentInstance.createdClient.subscribe(() => {
|
||||
this.load();
|
||||
})
|
||||
}
|
||||
|
||||
openDeleteDialog(client: Client) {
|
||||
|
||||
Reference in New Issue
Block a user