Merge branch '1.0.0' into #77

This commit is contained in:
Sven Heidemann 2023-02-16 22:02:59 +01:00
commit 065e8b0645
8 changed files with 250 additions and 191 deletions

View File

@ -1,3 +1,4 @@
from datetime import datetime
from typing import Optional from typing import Optional
from bot_api.abc.dto_abc import DtoABC from bot_api.abc.dto_abc import DtoABC
@ -14,6 +15,8 @@ class AuthUserDTO(DtoABC):
password: str = None, password: str = None,
confirmation_id: Optional[str] = None, confirmation_id: Optional[str] = None,
auth_role: AuthRoleEnum = None, auth_role: AuthRoleEnum = None,
created_at: datetime = None,
modified_at: datetime = None,
): ):
DtoABC.__init__(self) DtoABC.__init__(self)
@ -24,6 +27,8 @@ class AuthUserDTO(DtoABC):
self._password = password self._password = password
self._is_confirmed = confirmation_id is None self._is_confirmed = confirmation_id is None
self._auth_role = auth_role self._auth_role = auth_role
self._created_at = created_at
self._modified_at = modified_at
@property @property
def id(self) -> int: def id(self) -> int:
@ -77,6 +82,14 @@ class AuthUserDTO(DtoABC):
def auth_role(self, value: AuthRoleEnum): def auth_role(self, value: AuthRoleEnum):
self._auth_role = value self._auth_role = value
@property
def created_at(self) -> datetime:
return self._created_at
@property
def modified_at(self) -> datetime:
return self._modified_at
def from_dict(self, values: dict): def from_dict(self, values: dict):
self._id = values["id"] self._id = values["id"]
self._first_name = values["firstName"] self._first_name = values["firstName"]
@ -86,6 +99,9 @@ class AuthUserDTO(DtoABC):
self._is_confirmed = values["isConfirmed"] self._is_confirmed = values["isConfirmed"]
self._auth_role = AuthRoleEnum(values["authRole"]) self._auth_role = AuthRoleEnum(values["authRole"])
self._created_at = values["createdAt"]
self._modified_at = values["modifiedAt"]
def to_dict(self) -> dict: def to_dict(self) -> dict:
return { return {
"id": self._id, "id": self._id,
@ -95,4 +111,6 @@ class AuthUserDTO(DtoABC):
"password": self._password, "password": self._password,
"isConfirmed": self._is_confirmed, "isConfirmed": self._is_confirmed,
"authRole": self._auth_role.value, "authRole": self._auth_role.value,
"createdAt": self._created_at,
"modifiedAt": self._modified_at,
} }

View File

@ -1,4 +1,4 @@
from datetime import datetime, timezone from datetime import datetime
from bot_api.abc.transformer_abc import TransformerABC from bot_api.abc.transformer_abc import TransformerABC
from bot_api.model.auth_user_dto import AuthUserDTO from bot_api.model.auth_user_dto import AuthUserDTO
@ -34,4 +34,6 @@ class AuthUserTransformer(TransformerABC):
"" if password is None else password, "" if password is None else password,
db.confirmation_id, db.confirmation_id,
db.auth_role, db.auth_role,
db.created_at,
db.modified_at,
) )

View File

@ -1,11 +1,11 @@
import uuid import uuid
from datetime import datetime from datetime import datetime
from typing import Optional from typing import Optional
from cpl_core.database import TableABC from cpl_core.database import TableABC
from cpl_query.extension import List from cpl_query.extension import List
from bot_data.model.auth_role_enum import AuthRoleEnum from bot_data.model.auth_role_enum import AuthRoleEnum
from bot_data.model.server import Server
from bot_data.model.user import User from bot_data.model.user import User

View File

@ -1,6 +1,6 @@
{ {
"name": "kdb-web", "name": "kdb-web",
"version": "0.3.dev89", "version": "0.3.dev78",
"scripts": { "scripts": {
"ng": "ng", "ng": "ng",
"update-version": "ts-node-esm update-version.ts", "update-version": "ts-node-esm update-version.ts",

View File

@ -8,4 +8,6 @@ export interface AuthUserDTO {
password: string | null; password: string | null;
isConfirmed?: boolean isConfirmed?: boolean
authRole?: AuthRoles; authRole?: AuthRoles;
} createdAt?: string;
modifiedAt?: string;
}

View File

@ -1,201 +1,236 @@
<h1> <h1>
{{'admin.auth_users.header' | translate}} {{'admin.auth_users.header' | translate}}
</h1> </h1>
<div class="content-wrapper"> <div class="content-wrapper">
<div class="content"> <div class="content">
<p-table #dt [value]="users" dataKey="id" editMode="row" [rowHover]="true" [rows]="10" <p-table #dt [value]="users" dataKey="id" editMode="row" [rowHover]="true" [rows]="10"
[rowsPerPageOptions]="[10,25,50]" [paginator]="true" [loading]="loading" [totalRecords]="totalRecords" [rowsPerPageOptions]="[10,25,50]" [paginator]="true" [loading]="loading" [totalRecords]="totalRecords"
[lazy]="true" (onLazyLoad)="nextPage($event)"> [lazy]="true" (onLazyLoad)="nextPage($event)">
<ng-template pTemplate="caption"> <ng-template pTemplate="caption">
<div class="table-caption"> <div class="table-caption">
<div class="table-caption-text"> <div class="table-caption-text">
<ng-container *ngIf="!loading">{{users.length}} {{'admin.auth_users.of' | translate}} <ng-container *ngIf="!loading">{{users.length}} {{'admin.auth_users.of' | translate}}
{{dt.totalRecords}} {{dt.totalRecords}}
</ng-container> </ng-container>
{{'admin.auth_users.users' | translate}} {{'admin.auth_users.users' | translate}}
</div> </div>
<div class="table-caption-btn-wrapper btn-wrapper"> <div class="table-caption-btn-wrapper btn-wrapper">
<button pButton label="{{'admin.auth_users.add' | translate}}" class="icon-btn btn" <button pButton label="{{'admin.auth_users.add' | translate}}" class="icon-btn btn"
icon="pi pi-user-plus" (click)="addUser(dt)" [disabled]="isEditingNew"> icon="pi pi-user-plus" (click)="addUser(dt)" [disabled]="isEditingNew">
</button> </button>
<button pButton label="{{'admin.auth_users.reset_filters' | translate}}" icon="pi pi-undo" <button pButton label="{{'admin.auth_users.reset_filters' | translate}}" icon="pi pi-undo"
class="icon-btn btn" (click)="resetFilters(dt)"> class="icon-btn btn" (click)="resetFilters(dt)">
</button> </button>
</div> </div>
</div> </div>
</ng-template> </ng-template>
<ng-template pTemplate="header"> <ng-template pTemplate="header">
<tr> <tr>
<th pSortableColumn="firstName"> <th pSortableColumn="firstName">
<div class="table-header-label"> <div class="table-header-label">
<div class="table-header-text">{{'admin.auth_users.headers.first_name' | translate}}</div> <div class="table-header-text">{{'admin.auth_users.headers.first_name' | translate}}</div>
<p-sortIcon icon="sort" field="firstName" class="table-header-icon"></p-sortIcon> <p-sortIcon icon="sort" field="firstName" class="table-header-icon"></p-sortIcon>
</div> </div>
</th> </th>
<th pSortableColumn="lastName"> <th pSortableColumn="lastName">
<div class="table-header-label"> <div class="table-header-label">
<div class="table-header-text">{{'admin.auth_users.headers.last_name' | translate}}</div> <div class="table-header-text">{{'admin.auth_users.headers.last_name' | translate}}</div>
<p-sortIcon field="lastName" class="table-header-icon"></p-sortIcon> <p-sortIcon field="lastName" class="table-header-icon"></p-sortIcon>
</div> </div>
</th> </th>
<th pSortableColumn="email"> <th pSortableColumn="email">
<div class="table-header-label"> <div class="table-header-label">
<div class="table-header-text">{{'admin.auth_users.headers.e_mail' | translate}}</div> <div class="table-header-text">{{'admin.auth_users.headers.e_mail' | translate}}</div>
<p-sortIcon field="email" class="table-header-icon"></p-sortIcon> <p-sortIcon field="email" class="table-header-icon"></p-sortIcon>
</div> </div>
</th> </th>
<th class="table-header-actions" pSortableColumn="confirmationId"> <th class="table-header-actions" pSortableColumn="confirmationId">
<div class="table-header-label"> <div class="table-header-label">
<div class="table-header-text">{{'admin.auth_users.headers.active' | translate}}</div> <div class="table-header-text">{{'admin.auth_users.headers.active' | translate}}</div>
<p-sortIcon field="confirmationId" class="table-header-icon"></p-sortIcon> <p-sortIcon field="confirmationId" class="table-header-icon"></p-sortIcon>
</div> </div>
</th> </th>
<th class="table-header-small-dropdown" pSortableColumn="authRole"> <th class="table-header-small-dropdown" pSortableColumn="authRole">
<div class="table-header-label"> <div class="table-header-label">
<div class="table-header-text">{{'admin.auth_users.headers.role' | translate}}</div> <div class="table-header-text">{{'admin.auth_users.headers.role' | translate}}</div>
<p-sortIcon field="authRole" class="table-header-icon"></p-sortIcon> <p-sortIcon field="authRole" class="table-header-icon"></p-sortIcon>
</div> </div>
</th> </th>
<th> <th>
<div class="table-header-label"> <div class="table-header-label">
<div class="table-header-text">{{'admin.auth_users.headers.password' | translate}}</div> <div class="table-header-text">{{'admin.auth_users.headers.password' | translate}}</div>
</div> </div>
</th> </th>
<th class="table-header-actions"> <th class="table-header-small-dropdown">
<div class="table-header-label"> <div class="table-header-label">
<div class="table-header-text">{{'admin.auth_users.headers.actions' | translate}}</div> <div class="table-header-text">{{'admin.auth_users.headers.created_at' | translate}}</div>
</div> </div>
</th> </th>
</tr>
<tr>
<th>
<form [formGroup]="filterForm">
<input type="text" pInputText formControlName="firstName" placeholder="{{'admin.auth_users.headers.first_name' | translate}}">
</form>
</th>
<th>
<form [formGroup]="filterForm">
<input type="text" pInputText formControlName="lastName" placeholder="{{'admin.auth_users.headers.last_name' | translate}}">
</form>
</th>
<th>
<form [formGroup]="filterForm">
<input type="email" pInputText formControlName="email" placeholder="{{'admin.auth_users.headers.e_mail' | translate}}">
</form>
</th>
<th></th>
<th>
<form [formGroup]="filterForm">
<p-dropdown formControlName="authRole" [options]="authRoles"></p-dropdown>
</form>
</th>
<th></th>
<th></th>
</tr>
</ng-template>
<ng-template pTemplate="body" let-user let-editing="editing" let-ri="rowIndex"> <th class="table-header-small-dropdown">
<tr [pEditableRow]="user"> <div class="table-header-label">
<td> <div class="table-header-text">{{'admin.auth_users.headers.modified_at' | translate}}</div>
<p-cellEditor> </div>
<ng-template pTemplate="input"> </th>
<input class="table-edit-input" pInputText type="text" [(ngModel)]="user.firstName"
[ngClass]="{ 'invalid-feedback-input': isFirstNameInvalid}">
</ng-template>
<ng-template pTemplate="output">
{{user.firstName}}
</ng-template>
</p-cellEditor>
</td>
<td>
<p-cellEditor>
<ng-template pTemplate="input">
<input class="table-edit-input" pInputText type="text" [(ngModel)]="user.lastName"
[ngClass]="{ 'invalid-feedback-input': isLastNameInvalid}">
</ng-template>
<ng-template pTemplate="output">
{{user.lastName}}
</ng-template>
</p-cellEditor>
</td>
<td>
<p-cellEditor>
<ng-template pTemplate="input">
<input class="table-edit-input" pInputText type="email" [(ngModel)]="user.email"
[ngClass]="{ 'invalid-feedback-input': isEMailInvalid}">
</ng-template>
<ng-template pTemplate="output">
{{user.email}}
</ng-template>
</p-cellEditor>
</td>
<td>
<p-cellEditor>
<ng-template pTemplate="input">
<p-checkbox [binary]="true" [(ngModel)]="user.isConfirmed"
[ngClass]="{ 'invalid-feedback-input': isEMailInvalid}" [disabled]="isEditingNew">
</p-checkbox>
</ng-template>
<ng-template pTemplate="output">
<p-checkbox [binary]="true" [ngModel]="user.isConfirmed" [disabled]="true">
</p-checkbox>
</ng-template>
</p-cellEditor>
</td>
<td>
<p-cellEditor>
<ng-template pTemplate="input">
<p-dropdown [options]="authRoles" [(ngModel)]="user.authRole"
[disabled]="user.email == loggedInUserEMail"></p-dropdown>
</ng-template>
<ng-template pTemplate="output">
{{user.authRole | authRole}}
</ng-template>
</p-cellEditor>
</td>
<td>
<p-cellEditor>
<ng-template pTemplate="input">
<input class="table-edit-input" pInputText type="password" [(ngModel)]="user.password"
[ngClass]="{ 'invalid-feedback-input': isPasswordInvalid}">
</ng-template>
<ng-template pTemplate="output">
</ng-template>
</p-cellEditor>
</td>
<td>
<div class="btn-wrapper">
<button *ngIf="!editing" pButton pInitEditableRow class="btn icon-btn" icon="pi pi-pencil"
(click)="onRowEditInit(dt, user, ri)"></button>
<button *ngIf="!editing" pButton class="btn icon-btn danger-icon-btn" icon="pi pi-trash"
(click)="deleteUser(user)"></button>
<button *ngIf="editing" pButton pSaveEditableRow class="btn icon-btn" <th class="table-header-actions">
icon="pi pi-check-circle" (click)="onRowEditSave(dt, user, ri)"></button> <div class="table-header-label">
<button *ngIf="editing" pButton pCancelEditableRow class="btn icon-btn danger-icon-btn" <div class="table-header-text">{{'admin.auth_users.headers.actions' | translate}}</div>
icon="pi pi-times-circle" (click)="onRowEditCancel(user, ri)"></button> </div>
</div> </th>
</td>
</tr>
</ng-template>
<ng-template pTemplate="Invalidmessage"> </tr>
<tr> <tr>
<td colspan="7">{{'admin.auth_users.no_entries_found' | translate}}</td> <th>
</tr> <form [formGroup]="filterForm">
</ng-template> <input type="text" pInputText formControlName="firstName" placeholder="{{'admin.auth_users.headers.first_name' | translate}}">
</form>
</th>
<th>
<form [formGroup]="filterForm">
<input type="text" pInputText formControlName="lastName" placeholder="{{'admin.auth_users.headers.last_name' | translate}}">
</form>
</th>
<th>
<form [formGroup]="filterForm">
<input type="email" pInputText formControlName="email" placeholder="{{'admin.auth_users.headers.e_mail' | translate}}">
</form>
</th>
<th></th>
<th>
<form [formGroup]="filterForm">
<p-dropdown formControlName="authRole" [options]="authRoles"></p-dropdown>
</form>
</th>
<th></th>
<th></th>
<th></th>
<th></th>
</tr>
</ng-template>
<ng-template pTemplate="paginatorleft"> <ng-template pTemplate="body" let-user let-editing="editing" let-ri="rowIndex">
</ng-template> <tr [pEditableRow]="user">
</p-table> <td>
</div> <p-cellEditor>
</div> <ng-template pTemplate="input">
<input class="table-edit-input" pInputText type="text" [(ngModel)]="user.firstName"
[ngClass]="{ 'invalid-feedback-input': isFirstNameInvalid}">
</ng-template>
<ng-template pTemplate="output">
{{user.firstName}}
</ng-template>
</p-cellEditor>
</td>
<td>
<p-cellEditor>
<ng-template pTemplate="input">
<input class="table-edit-input" pInputText type="text" [(ngModel)]="user.lastName"
[ngClass]="{ 'invalid-feedback-input': isLastNameInvalid}">
</ng-template>
<ng-template pTemplate="output">
{{user.lastName}}
</ng-template>
</p-cellEditor>
</td>
<td>
<p-cellEditor>
<ng-template pTemplate="input">
<input class="table-edit-input" pInputText type="email" [(ngModel)]="user.email"
[ngClass]="{ 'invalid-feedback-input': isEMailInvalid}">
</ng-template>
<ng-template pTemplate="output">
{{user.email}}
</ng-template>
</p-cellEditor>
</td>
<td>
<p-cellEditor>
<ng-template pTemplate="input">
<p-checkbox [binary]="true" [(ngModel)]="user.isConfirmed"
[ngClass]="{ 'invalid-feedback-input': isEMailInvalid}" [disabled]="isEditingNew">
</p-checkbox>
</ng-template>
<ng-template pTemplate="output">
<p-checkbox [binary]="true" [ngModel]="user.isConfirmed" [disabled]="true">
</p-checkbox>
</ng-template>
</p-cellEditor>
</td>
<td>
<p-cellEditor>
<ng-template pTemplate="input">
<p-dropdown [options]="authRoles" [(ngModel)]="user.authRole"
[disabled]="user.email == loggedInUserEMail"></p-dropdown>
</ng-template>
<ng-template pTemplate="output">
{{user.authRole | authRole}}
</ng-template>
</p-cellEditor>
</td>
<td>
<p-cellEditor>
<ng-template pTemplate="input">
<input class="table-edit-input" pInputText type="password" [(ngModel)]="user.password"
[ngClass]="{ 'invalid-feedback-input': isPasswordInvalid}">
</ng-template>
<ng-template pTemplate="output">
</ng-template>
</p-cellEditor>
</td>
<td>
<p-cellEditor>
<ng-template pTemplate="input">
{{user.createdAt}}
</ng-template>
<ng-template pTemplate="output">
{{user.createdAt | date:'dd.MM.yy HH:mm'}}
</ng-template>
</p-cellEditor>
</td>
<td>
<p-cellEditor>
<ng-template pTemplate="input">
{{user.modifiedAt}}
</ng-template>
<ng-template pTemplate="output">
{{user.modifiedAt | date:'dd.MM.yy HH:mm'}}
</ng-template>
</p-cellEditor>
</td>
<td>
<div class="btn-wrapper">
<button *ngIf="!editing" pButton pInitEditableRow class="btn icon-btn" icon="pi pi-pencil"
(click)="onRowEditInit(dt, user, ri)"></button>
<button *ngIf="!editing" pButton class="btn icon-btn danger-icon-btn" icon="pi pi-trash"
(click)="deleteUser(user)"></button>
<button *ngIf="editing" pButton pSaveEditableRow class="btn icon-btn"
icon="pi pi-check-circle" (click)="onRowEditSave(dt, user, ri)"></button>
<button *ngIf="editing" pButton pCancelEditableRow class="btn icon-btn danger-icon-btn"
icon="pi pi-times-circle" (click)="onRowEditCancel(user, ri)"></button>
</div>
</td>
</tr>
</ng-template>
<ng-template pTemplate="Invalidmessage">
<tr>
<td colspan="7">{{'admin.auth_users.no_entries_found' | translate}}</td>
</tr>
</ng-template>
<ng-template pTemplate="paginatorleft">
</ng-template>
</p-table>
</div>
</div>

View File

@ -3,7 +3,7 @@
"WebVersion": { "WebVersion": {
"Major": "0", "Major": "0",
"Minor": "3", "Minor": "3",
"Micro": "dev89" "Micro": "dev78"
}, },
"Themes": [ "Themes": [
{ {

View File

@ -64,7 +64,9 @@
"active": "Aktiv", "active": "Aktiv",
"role": "Rolle", "role": "Rolle",
"password": "Passwort", "password": "Passwort",
"actions": "Aktionen" "actions": "Aktionen",
"created_at": "Erstellt am",
"modified_at": "Bearbeitet am"
}, },
"no_entries_found": "Keine Einträge gefunden", "no_entries_found": "Keine Einträge gefunden",
"message": { "message": {