feat: add pseudo-authorization with code word
All checks were successful
continuous-integration/drone/push Build is passing
All checks were successful
continuous-integration/drone/push Build is passing
User must enter code word "пупырка" to access the app. Auth state persisted in localStorage. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@ -1,14 +1,116 @@
|
|||||||
import { Component } from '@angular/core';
|
import { Component, signal } from '@angular/core';
|
||||||
|
import { FormsModule } from '@angular/forms';
|
||||||
import { ToastModule } from 'primeng/toast';
|
import { ToastModule } from 'primeng/toast';
|
||||||
import { AppLayoutComponent } from './components/app-layout/app-layout.component';
|
import { AppLayoutComponent } from './components/app-layout/app-layout.component';
|
||||||
|
|
||||||
|
const AUTH_KEY = 'test-x6-auth';
|
||||||
|
const CODE_WORD = 'пупырка';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-root',
|
selector: 'app-root',
|
||||||
standalone: true,
|
standalone: true,
|
||||||
imports: [ToastModule, AppLayoutComponent],
|
imports: [FormsModule, ToastModule, AppLayoutComponent],
|
||||||
template: `
|
template: `
|
||||||
|
@if (authorized()) {
|
||||||
<p-toast />
|
<p-toast />
|
||||||
<app-layout />
|
<app-layout />
|
||||||
|
} @else {
|
||||||
|
<div class="login-wrapper">
|
||||||
|
<div class="login-card">
|
||||||
|
<h2>Детальная схема связей</h2>
|
||||||
|
<p>Введите кодовое слово для входа</p>
|
||||||
|
<input
|
||||||
|
type="password"
|
||||||
|
[(ngModel)]="inputValue"
|
||||||
|
(keydown.enter)="tryLogin()"
|
||||||
|
placeholder="Кодовое слово"
|
||||||
|
[class.error]="showError()"
|
||||||
|
autofocus
|
||||||
|
/>
|
||||||
|
@if (showError()) {
|
||||||
|
<span class="error-text">Неверное кодовое слово</span>
|
||||||
|
}
|
||||||
|
<button (click)="tryLogin()">Войти</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
`,
|
||||||
|
styles: `
|
||||||
|
.login-wrapper {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
height: 100vh;
|
||||||
|
background: #f5f5f5;
|
||||||
|
}
|
||||||
|
.login-card {
|
||||||
|
background: #fff;
|
||||||
|
border-radius: 8px;
|
||||||
|
padding: 32px;
|
||||||
|
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.12);
|
||||||
|
text-align: center;
|
||||||
|
width: 320px;
|
||||||
|
}
|
||||||
|
.login-card h2 {
|
||||||
|
margin: 0 0 8px;
|
||||||
|
font-size: 18px;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
.login-card p {
|
||||||
|
margin: 0 0 20px;
|
||||||
|
color: #888;
|
||||||
|
font-size: 13px;
|
||||||
|
}
|
||||||
|
.login-card input {
|
||||||
|
width: 100%;
|
||||||
|
padding: 10px 12px;
|
||||||
|
border: 1px solid #d9d9d9;
|
||||||
|
border-radius: 6px;
|
||||||
|
font-size: 14px;
|
||||||
|
outline: none;
|
||||||
|
box-sizing: border-box;
|
||||||
|
transition: border-color 0.2s;
|
||||||
|
}
|
||||||
|
.login-card input:focus {
|
||||||
|
border-color: #4096ff;
|
||||||
|
}
|
||||||
|
.login-card input.error {
|
||||||
|
border-color: #ff4d4f;
|
||||||
|
}
|
||||||
|
.error-text {
|
||||||
|
display: block;
|
||||||
|
color: #ff4d4f;
|
||||||
|
font-size: 12px;
|
||||||
|
margin-top: 6px;
|
||||||
|
}
|
||||||
|
.login-card button {
|
||||||
|
margin-top: 16px;
|
||||||
|
width: 100%;
|
||||||
|
padding: 10px;
|
||||||
|
background: #4096ff;
|
||||||
|
color: #fff;
|
||||||
|
border: none;
|
||||||
|
border-radius: 6px;
|
||||||
|
font-size: 14px;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: background 0.2s;
|
||||||
|
}
|
||||||
|
.login-card button:hover {
|
||||||
|
background: #1677ff;
|
||||||
|
}
|
||||||
`,
|
`,
|
||||||
})
|
})
|
||||||
export class AppComponent {}
|
export class AppComponent {
|
||||||
|
authorized = signal(localStorage.getItem(AUTH_KEY) === 'true');
|
||||||
|
showError = signal(false);
|
||||||
|
inputValue = '';
|
||||||
|
|
||||||
|
tryLogin() {
|
||||||
|
if (this.inputValue.trim().toLowerCase() === CODE_WORD) {
|
||||||
|
localStorage.setItem(AUTH_KEY, 'true');
|
||||||
|
this.authorized.set(true);
|
||||||
|
} else {
|
||||||
|
this.showError.set(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user