Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
896 changes: 894 additions & 2 deletions MiniKmsClient/package-lock.json

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions MiniKmsClient/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,12 @@
"private": true,
"dependencies": {
"@angular/animations": "^17.0.0",
"@angular/cdk": "^17.3.10",
"@angular/common": "^17.0.0",
"@angular/compiler": "^17.0.0",
"@angular/core": "^17.0.0",
"@angular/forms": "^17.0.0",
"@angular/material": "^17.3.10",
"@angular/platform-browser": "^17.0.0",
"@angular/platform-browser-dynamic": "^17.0.0",
"@angular/router": "^17.0.0",
Expand Down
22 changes: 21 additions & 1 deletion MiniKmsClient/src/app/app-routing.module.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,27 @@
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { authGuard } from './auth/auth.guard';
import { ManageKeysComponent } from './manage-keys/manage-keys.component';
import { LoginComponent } from './login/login.component';
import { CryptoComponent } from './crypto/crypto.component';

const routes: Routes = [];
const routes: Routes = [
{ path: '', redirectTo: '/login', pathMatch: 'full' },
{ path: 'login', component: LoginComponent },
{
path: 'manage-keys',
component: ManageKeysComponent,
canActivate: [authGuard],
data: { roles: ['manager'] }
},
{
path: 'crypto',
component: CryptoComponent,
canActivate: [authGuard],
data: { roles: ['manager', 'user'] }
},
{ path: '**', redirectTo: '/login' }
];

@NgModule({
imports: [RouterModule.forRoot(routes)],
Expand Down
371 changes: 35 additions & 336 deletions MiniKmsClient/src/app/app.component.html

Large diffs are not rendered by default.

19 changes: 17 additions & 2 deletions MiniKmsClient/src/app/app.component.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,25 @@
import { Component } from '@angular/core';
import { AuthService } from './auth/auth.service';

@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrl: './app.component.scss'
styleUrl: './app.component.css'
})
export class AppComponent {
title = 'MiniKmsClient';
title = 'mini-kms-client';

constructor(public authService: AuthService) {}

isManager(): boolean {
return this.authService.hasRole('manager');
}

isAuthenticated(): boolean {
return this.authService.isAuthenticated();
}

logout(): void {
this.authService.logout();
}
}
19 changes: 17 additions & 2 deletions MiniKmsClient/src/app/app.module.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,31 @@
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { ReactiveFormsModule, FormsModule } from '@angular/forms';
import { HttpClientModule } from '@angular/common/http';

import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { LoginComponent } from './login/login.component';
import { ManageKeysComponent } from './manage-keys/manage-keys.component';
import { CryptoComponent } from './crypto/crypto.component';
import { MaterialModule } from './common/material/material.module';

@NgModule({
declarations: [
AppComponent
AppComponent,
LoginComponent,
ManageKeysComponent,
CryptoComponent
],
imports: [
BrowserModule,
AppRoutingModule
BrowserAnimationsModule,
ReactiveFormsModule,
FormsModule,
HttpClientModule,
AppRoutingModule,
MaterialModule
],
providers: [],
bootstrap: [AppComponent]
Expand Down
111 changes: 61 additions & 50 deletions MiniKmsClient/src/app/login/login.component.html
Original file line number Diff line number Diff line change
@@ -1,52 +1,63 @@
<div class="login-container">
<mat-card class="login-card">
<mat-card-header>
<mat-card-title>Mini KMS Login</mat-card-title>
<mat-card-subtitle>Sign in to your account</mat-card-subtitle>
</mat-card-header>

<mat-card-content>
<form [formGroup]="loginForm" (ngSubmit)="onSubmit()" class="login-form">
<mat-form-field appearance="outline" class="full-width">
<mat-label>Username</mat-label>
<input matInput
formControlName="username"
autocomplete="username">
<mat-icon matSuffix>person</mat-icon>
<mat-error *ngIf="loginForm.get('username')?.invalid && loginForm.get('username')?.touched">
{{ getErrorMessage('username') }}
</mat-error>
</mat-form-field>

<mat-form-field appearance="outline" class="full-width">
<mat-label>Password</mat-label>
<input matInput
[type]="hidePassword ? 'password' : 'text'"
formControlName="password"
autocomplete="current-password">
<button mat-icon-button
matSuffix
(click)="hidePassword = !hidePassword"
type="button"
[disabled]="loading">
<mat-icon>{{ hidePassword ? 'visibility_off' : 'visibility' }}</mat-icon>
</button>
<mat-error *ngIf="loginForm.get('password')?.invalid && loginForm.get('password')?.touched">
{{ getErrorMessage('password') }}
</mat-error>
</mat-form-field>

<button mat-raised-button
color="primary"
type="submit"
class="full-width login-button"
[disabled]="loginForm.invalid || loading">
<div class="button-content">
<body>
<div class="login-container">
<div class="login-card">
<div class="login-header">
<h1>Mini KMS</h1>
<p>Sign in to your account</p>
</div>

<form [formGroup]="loginForm" (ngSubmit)="onSubmit()" class="login-form">
<div class="input-group">
<label class="input-label" for="username">Username</label>
<div class="input-wrapper">
<mat-icon class="input-icon">person</mat-icon>
<input
id="username"
name="username"
class="custom-input"
formControlName="username"
autocomplete="username"
placeholder="Enter your username">
</div>
<div class="error-message" *ngIf="loginForm.get('username')?.invalid && loginForm.get('username')?.touched">
{{ getErrorMessage('username') }}
</div>
</div>

<div class="input-group">
<label class="input-label" for="password">Password</label>
<div class="input-wrapper">
<mat-icon class="input-icon">lock</mat-icon>
<input
id="password"
name="password"
class="custom-input"
[type]="hidePassword ? 'password' : 'text'"
formControlName="password"
autocomplete="current-password"
placeholder="Enter your password">
<button
type="button"
class="visibility-toggle"
(click)="hidePassword = !hidePassword"
[disabled]="loading">
<mat-icon>{{ hidePassword ? 'visibility_off' : 'visibility' }}</mat-icon>
</button>
</div>
<div class="error-message" *ngIf="loginForm.get('password')?.invalid && loginForm.get('password')?.touched">
{{ getErrorMessage('password') }}
</div>
</div>

<button
type="submit"
class="login-button"
[disabled]="loginForm.invalid || loading"
[class.loading]="loading">
<mat-spinner *ngIf="loading" diameter="20"></mat-spinner>
<span>{{ loading ? 'Signing in...' : 'Sign In' }}</span>
</div>
</button>
</form>
</mat-card-content>
</mat-card>
</div>
</button>
</form>
</div>
</div>
</body>
Loading
Loading