feat: Added redirect after login for users. Closes #17
This commit is contained in:
@@ -55,7 +55,7 @@ export class AccountMgmtComponent implements OnInit, AfterViewInit {
|
|||||||
}
|
}
|
||||||
|
|
||||||
openUserCard(id?: string) {
|
openUserCard(id?: string) {
|
||||||
this.dialog.open(UserEditComponent, {data: {id: id, type: id ? "edit" : "new", groups: this.groups}}).afterClosed().subscribe(r => {
|
this.dialog.open<UserEditComponent, UserEditComponent.InputData, UserEditComponent.ReturnData>(UserEditComponent, {data: {id: id, type: id ? "edit" : "new", groups: this.groups}}).afterClosed().subscribe(r => {
|
||||||
if (r) this.ngOnInit()
|
if (r) this.ngOnInit()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,12 +11,17 @@ import { catchError, throwError } from 'rxjs';
|
|||||||
import { Moment } from 'moment';
|
import { Moment } from 'moment';
|
||||||
import * as moment from 'moment';
|
import * as moment from 'moment';
|
||||||
|
|
||||||
|
export namespace UserEditComponent {
|
||||||
|
export type InputData = {type: "new" | "edit", id?: string, groups: Group[]}
|
||||||
|
export type ReturnData = true | undefined
|
||||||
|
}
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-user-edit',
|
selector: 'app-user-edit',
|
||||||
templateUrl: './user-edit.component.html',
|
templateUrl: './user-edit.component.html',
|
||||||
styleUrls: ['./user-edit.component.scss']
|
styleUrls: ['./user-edit.component.scss']
|
||||||
})
|
})
|
||||||
export class UserEditComponent {
|
export class UserEditComponent {
|
||||||
lockout = false;
|
lockout = false;
|
||||||
locked = false;
|
locked = false;
|
||||||
loading = false;
|
loading = false;
|
||||||
@@ -33,7 +38,7 @@ export class UserEditComponent {
|
|||||||
regDate?: Moment;
|
regDate?: Moment;
|
||||||
constructor (
|
constructor (
|
||||||
public dialogRef: MatDialogRef<UserEditComponent>,
|
public dialogRef: MatDialogRef<UserEditComponent>,
|
||||||
@Inject(MAT_DIALOG_DATA) public data: ({type: "edit", id: string} | {type: "new"}) & {groups: Group[]},
|
@Inject(MAT_DIALOG_DATA) public data: UserEditComponent.InputData,
|
||||||
readonly ls: LocalStorageService,
|
readonly ls: LocalStorageService,
|
||||||
readonly acu: AdminCommService,
|
readonly acu: AdminCommService,
|
||||||
private dialog: MatDialog,
|
private dialog: MatDialog,
|
||||||
@@ -42,7 +47,7 @@ export class UserEditComponent {
|
|||||||
this.groups = data.groups
|
this.groups = data.groups
|
||||||
if (data.type == "edit") {
|
if (data.type == "edit") {
|
||||||
this.id = data.id
|
this.id = data.id
|
||||||
this.acu.accs.getUser(data.id).subscribe((r) => {
|
this.acu.accs.getUser(data.id!).subscribe((r) => {
|
||||||
this.regDate = moment(r.regDate)
|
this.regDate = moment(r.regDate)
|
||||||
var flags: Array<number> = []
|
var flags: Array<number> = []
|
||||||
if (r.admin) {
|
if (r.admin) {
|
||||||
|
|||||||
@@ -4,6 +4,6 @@ import { LocalStorageService } from './services/local-storage.service';
|
|||||||
|
|
||||||
export const adminGuard: CanActivateChildFn = (childRoute, state) => {
|
export const adminGuard: CanActivateChildFn = (childRoute, state) => {
|
||||||
const router = inject(Router)
|
const router = inject(Router)
|
||||||
if (inject(LocalStorageService).admin == false) return router.parseUrl('/')
|
if (inject(LocalStorageService).admin == undefined) return router.parseUrl('/')
|
||||||
return true
|
return true
|
||||||
};
|
};
|
||||||
|
|||||||
14
src/app/app-view/personal/extra/extra.component.html
Normal file
14
src/app/app-view/personal/extra/extra.component.html
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
<h1 mat-dialog-title>Dodatkowe ustawienia</h1>
|
||||||
|
<mat-dialog-content>
|
||||||
|
<mat-action-list>
|
||||||
|
@for (link of LINKS; track link) {
|
||||||
|
<button mat-list-item (click)="open(link.component)">
|
||||||
|
<mat-icon matListItemIcon *ngIf="link.icon">{{link.icon}}</mat-icon>
|
||||||
|
<div matListItemTitle>{{link.title}}</div>
|
||||||
|
</button>
|
||||||
|
}
|
||||||
|
</mat-action-list>
|
||||||
|
</mat-dialog-content>
|
||||||
|
<mat-dialog-actions align="end">
|
||||||
|
<button mat-dialog-close mat-button>Zamknij</button>
|
||||||
|
</mat-dialog-actions>
|
||||||
23
src/app/app-view/personal/extra/extra.component.spec.ts
Normal file
23
src/app/app-view/personal/extra/extra.component.spec.ts
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { ExtraComponent } from './extra.component';
|
||||||
|
|
||||||
|
describe('ExtraComponent', () => {
|
||||||
|
let component: ExtraComponent;
|
||||||
|
let fixture: ComponentFixture<ExtraComponent>;
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
await TestBed.configureTestingModule({
|
||||||
|
declarations: [ExtraComponent]
|
||||||
|
})
|
||||||
|
.compileComponents();
|
||||||
|
|
||||||
|
fixture = TestBed.createComponent(ExtraComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
||||||
29
src/app/app-view/personal/extra/extra.component.ts
Normal file
29
src/app/app-view/personal/extra/extra.component.ts
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
import { ComponentType } from '@angular/cdk/portal';
|
||||||
|
import { Component } from '@angular/core';
|
||||||
|
import { Link } from 'src/app/types/link';
|
||||||
|
import { RedirectComponent } from './redirect/redirect.component';
|
||||||
|
import { MatDialog } from '@angular/material/dialog';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-extra',
|
||||||
|
templateUrl: './extra.component.html',
|
||||||
|
styleUrl: './extra.component.scss'
|
||||||
|
})
|
||||||
|
export class ExtraComponent {
|
||||||
|
|
||||||
|
constructor (private dialog: MatDialog) {}
|
||||||
|
|
||||||
|
private readonly _LINKS: (Omit<Link, "href"> & {component: ComponentType<any>})[] = [
|
||||||
|
{ title: "Domyślna strona po logowaniu", component: RedirectComponent, enabled: true, icon: "home" }
|
||||||
|
]
|
||||||
|
|
||||||
|
public get LINKS() {
|
||||||
|
return this._LINKS.filter((v) => {
|
||||||
|
return v.enabled
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
open(component: ComponentType<any>) {
|
||||||
|
this.dialog.open(component)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
<h1>Domyślna strona po logowaniu</h1>
|
||||||
|
<mat-dialog-content>
|
||||||
|
<p>Wpisz link względem /ipwa/ w poniższym polu.</p>
|
||||||
|
<p>Przykład: /app/menu</p>
|
||||||
|
<mat-form-field>
|
||||||
|
<input matInput type="text" [(ngModel)]="redirect">
|
||||||
|
<mat-label>Link</mat-label>
|
||||||
|
</mat-form-field>
|
||||||
|
</mat-dialog-content>
|
||||||
|
<mat-dialog-actions align="end">
|
||||||
|
<button mat-dialog-close mat-button>Anuluj</button>
|
||||||
|
<button (click)="save()" mat-flat-button>Zapisz</button>
|
||||||
|
</mat-dialog-actions>
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { RedirectComponent } from './redirect.component';
|
||||||
|
|
||||||
|
describe('RedirectComponent', () => {
|
||||||
|
let component: RedirectComponent;
|
||||||
|
let fixture: ComponentFixture<RedirectComponent>;
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
await TestBed.configureTestingModule({
|
||||||
|
declarations: [RedirectComponent]
|
||||||
|
})
|
||||||
|
.compileComponents();
|
||||||
|
|
||||||
|
fixture = TestBed.createComponent(RedirectComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
import { Component } from '@angular/core';
|
||||||
|
import { MatDialogRef } from '@angular/material/dialog';
|
||||||
|
import { AuthClient } from 'src/app/services/auth.client';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-redirect',
|
||||||
|
templateUrl: './redirect.component.html',
|
||||||
|
styleUrl: './redirect.component.scss'
|
||||||
|
})
|
||||||
|
export class RedirectComponent {
|
||||||
|
protected redirect = ""
|
||||||
|
constructor (public dialogRef: MatDialogRef<RedirectComponent>, private ac: AuthClient) {
|
||||||
|
this.redirect = ac.redirect
|
||||||
|
}
|
||||||
|
|
||||||
|
protected save() {
|
||||||
|
this.ac.redirect = this.redirect
|
||||||
|
this.dialogRef.close()
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -30,6 +30,10 @@
|
|||||||
<div matListItemTitle>Panel administracyjny</div>
|
<div matListItemTitle>Panel administracyjny</div>
|
||||||
<div matListItemLine>Poprzednio Tryb edycji</div>
|
<div matListItemLine>Poprzednio Tryb edycji</div>
|
||||||
</button>
|
</button>
|
||||||
|
<button mat-list-item (click)="openExtra()">
|
||||||
|
<mat-icon matListItemIcon>settings_applications</mat-icon>
|
||||||
|
<div matListItemTitle>Dodatkowe ustawienia</div>
|
||||||
|
</button>
|
||||||
<button mat-list-item (click)="openAbout()">
|
<button mat-list-item (click)="openAbout()">
|
||||||
<mat-icon matListItemIcon>info</mat-icon>
|
<mat-icon matListItemIcon>info</mat-icon>
|
||||||
<div matListItemTitle>O programie</div>
|
<div matListItemTitle>O programie</div>
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import { LocalStorageService } from 'src/app/services/local-storage.service';
|
|||||||
import { KeyComponent } from './key/key.component';
|
import { KeyComponent } from './key/key.component';
|
||||||
import { CleanComponent } from './clean/clean.component';
|
import { CleanComponent } from './clean/clean.component';
|
||||||
import { AboutComponent } from './about/about.component';
|
import { AboutComponent } from './about/about.component';
|
||||||
|
import { ExtraComponent } from './extra/extra.component';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-personal',
|
selector: 'app-personal',
|
||||||
@@ -63,6 +64,10 @@ export class PersonalComponent {
|
|||||||
this.ac.check()
|
this.ac.check()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected openExtra() {
|
||||||
|
this.dialog.open(ExtraComponent)
|
||||||
|
}
|
||||||
|
|
||||||
protected openAbout() {
|
protected openAbout() {
|
||||||
this.dialog.open(AboutComponent)
|
this.dialog.open(AboutComponent)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -79,6 +79,8 @@ import { AttendenceSummaryComponent } from './admin-view/grades/attendence-summa
|
|||||||
import { HourDisplayComponent } from './admin-view/grades/attendence-summary/hour-display/hour-display.component';
|
import { HourDisplayComponent } from './admin-view/grades/attendence-summary/hour-display/hour-display.component';
|
||||||
import { AboutComponent } from './app-view/personal/about/about.component';
|
import { AboutComponent } from './app-view/personal/about/about.component';
|
||||||
import { environment } from 'src/environments/environment';
|
import { environment } from 'src/environments/environment';
|
||||||
|
import { ExtraComponent } from './app-view/personal/extra/extra.component';
|
||||||
|
import { RedirectComponent } from './app-view/personal/extra/redirect/redirect.component';
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
declarations: [
|
declarations: [
|
||||||
@@ -122,6 +124,8 @@ import { environment } from 'src/environments/environment';
|
|||||||
AttendenceSummaryComponent,
|
AttendenceSummaryComponent,
|
||||||
HourDisplayComponent,
|
HourDisplayComponent,
|
||||||
AboutComponent,
|
AboutComponent,
|
||||||
|
ExtraComponent,
|
||||||
|
RedirectComponent,
|
||||||
],
|
],
|
||||||
imports: [
|
imports: [
|
||||||
BrowserModule,
|
BrowserModule,
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ export class LoginComponent implements OnInit {
|
|||||||
|
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
if (this.ls.loggedIn) {
|
if (this.ls.loggedIn) {
|
||||||
this.router.navigateByUrl('app')
|
this.router.navigateByUrl(this.ac.redirect || 'app')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -33,7 +33,7 @@ export class LoginComponent implements OnInit {
|
|||||||
return throwError(() => new Error(err.message))
|
return throwError(() => new Error(err.message))
|
||||||
})).subscribe((data) => {
|
})).subscribe((data) => {
|
||||||
this.ls.loggedIn = true
|
this.ls.loggedIn = true
|
||||||
this.router.navigateByUrl('app')
|
this.router.navigateByUrl(this.ac.redirect || 'app')
|
||||||
if (data.admin) {
|
if (data.admin) {
|
||||||
this.ls.admin = data.admin
|
this.ls.admin = data.admin
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { HttpClient } from '@angular/common/http';
|
import { HttpClient } from '@angular/common/http';
|
||||||
import { Injectable } from '@angular/core';
|
import { Injectable } from '@angular/core';
|
||||||
import { Router } from '@angular/router';
|
import { Router } from '@angular/router';
|
||||||
import { catchError, EMPTY, throwError } from 'rxjs';
|
import { catchError, EMPTY, tap, throwError } from 'rxjs';
|
||||||
import { environment } from 'src/environments/environment';
|
import { environment } from 'src/environments/environment';
|
||||||
import { LocalStorageService } from './local-storage.service';
|
import { LocalStorageService } from './local-storage.service';
|
||||||
import { Status } from '../types/status';
|
import { Status } from '../types/status';
|
||||||
@@ -12,11 +12,22 @@ import { Status } from '../types/status';
|
|||||||
export class AuthClient {
|
export class AuthClient {
|
||||||
constructor(private http: HttpClient, private router: Router, private ls: LocalStorageService) { }
|
constructor(private http: HttpClient, private router: Router, private ls: LocalStorageService) { }
|
||||||
|
|
||||||
|
private _redirect: string = "";
|
||||||
|
public get redirect(): string {
|
||||||
|
return this._redirect;
|
||||||
|
}
|
||||||
|
public set redirect(value: string) {
|
||||||
|
this._redirect = value;
|
||||||
|
this.putRedirect(value).subscribe()
|
||||||
|
}
|
||||||
|
|
||||||
public login(uname: string, pass: string) {
|
public login(uname: string, pass: string) {
|
||||||
return this.http.post<any>(environment.apiEndpoint + '/auth/login', {
|
return this.http.post<Status & {admin: number, redirect: string}>(environment.apiEndpoint + '/auth/login', {
|
||||||
username: uname,
|
username: uname,
|
||||||
password: pass
|
password: pass
|
||||||
}, {withCredentials: true})
|
}, {withCredentials: true}).pipe(tap((v) => {
|
||||||
|
if (v.redirect) this._redirect = v.redirect
|
||||||
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
public logout() {
|
public logout() {
|
||||||
@@ -24,15 +35,26 @@ export class AuthClient {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public check() {
|
public check() {
|
||||||
this.http.get(environment.apiEndpoint + '/auth/check', {withCredentials: true}).pipe(catchError((err) => {
|
this.http.get<{
|
||||||
|
admin?: number,
|
||||||
|
room?: string,
|
||||||
|
features: number,
|
||||||
|
menu: {
|
||||||
|
defaultItems: {
|
||||||
|
sn: string[];
|
||||||
|
kol: string[];
|
||||||
|
}
|
||||||
|
},
|
||||||
|
vapid: string
|
||||||
|
}>(environment.apiEndpoint + '/auth/check', {withCredentials: true}).pipe(catchError((err) => {
|
||||||
if (err.status == 401 && this.ls.loggedIn) {
|
if (err.status == 401 && this.ls.loggedIn) {
|
||||||
this.ls.logOut()
|
this.ls.logOut()
|
||||||
this.router.navigateByUrl("/login")
|
this.router.navigateByUrl("/login")
|
||||||
return EMPTY
|
return EMPTY
|
||||||
}
|
}
|
||||||
return throwError(() => new Error(err.message))
|
return throwError(() => new Error(err.message))
|
||||||
})).subscribe((data: any)=>{
|
})).subscribe((data)=>{
|
||||||
if (data.admin) { this.ls.admin = data.admin } else { this.ls.admin = false }
|
this.ls.admin = data.admin
|
||||||
if (this.ls.capFlag != data.features) {
|
if (this.ls.capFlag != data.features) {
|
||||||
this.ls.capFlag = data.features
|
this.ls.capFlag = data.features
|
||||||
document.location.reload()
|
document.location.reload()
|
||||||
@@ -48,4 +70,8 @@ export class AuthClient {
|
|||||||
public chpass(oldpass:string,newpass:string) {
|
public chpass(oldpass:string,newpass:string) {
|
||||||
return this.http.post(environment.apiEndpoint + '/auth/chpass', {"oldPass": oldpass, "newPass": newpass}, {withCredentials: true, responseType: "text"})
|
return this.http.post(environment.apiEndpoint + '/auth/chpass', {"oldPass": oldpass, "newPass": newpass}, {withCredentials: true, responseType: "text"})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private putRedirect(redirect: string) {
|
||||||
|
return this.http.put<Status>(environment.apiEndpoint + '/auth/redirect', {redirect: redirect}, {withCredentials: true})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,8 +13,8 @@ export class LocalStorageService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
logOut() {
|
logOut() {
|
||||||
this.loggedIn = false
|
this.loggedIn = undefined
|
||||||
this.admin = false
|
this.admin = undefined
|
||||||
}
|
}
|
||||||
|
|
||||||
public hasRoom() {
|
public hasRoom() {
|
||||||
@@ -26,11 +26,11 @@ export class LocalStorageService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
get room() {
|
get room() {
|
||||||
return localStorage.getItem('room')!
|
return localStorage.getItem('room') ?? undefined
|
||||||
}
|
}
|
||||||
|
|
||||||
set room(value: string) {
|
set room(value: string | undefined) {
|
||||||
if (value == "") {
|
if (!value) {
|
||||||
localStorage.removeItem('room')
|
localStorage.removeItem('room')
|
||||||
} else {
|
} else {
|
||||||
localStorage.setItem('room', value)
|
localStorage.setItem('room', value)
|
||||||
@@ -49,10 +49,10 @@ export class LocalStorageService {
|
|||||||
if (localStorage.getItem("loggedIn")) {
|
if (localStorage.getItem("loggedIn")) {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
return false
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
set loggedIn(is: boolean) {
|
set loggedIn(is: true | undefined) {
|
||||||
if (is) {
|
if (is) {
|
||||||
localStorage.setItem("loggedIn", "true")
|
localStorage.setItem("loggedIn", "true")
|
||||||
} else {
|
} else {
|
||||||
@@ -60,7 +60,7 @@ export class LocalStorageService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
set admin(newInt: number | false) {
|
set admin(newInt: number | undefined) {
|
||||||
if (newInt) {
|
if (newInt) {
|
||||||
localStorage.setItem("admin", newInt.toString())
|
localStorage.setItem("admin", newInt.toString())
|
||||||
} else {
|
} else {
|
||||||
@@ -70,7 +70,7 @@ export class LocalStorageService {
|
|||||||
|
|
||||||
get admin() {
|
get admin() {
|
||||||
var lsa = localStorage.getItem("admin")
|
var lsa = localStorage.getItem("admin")
|
||||||
return lsa ? Number.parseInt(lsa) : false
|
return lsa ? Number.parseInt(lsa) : undefined
|
||||||
}
|
}
|
||||||
|
|
||||||
set amgreg(toggle: boolean) {
|
set amgreg(toggle: boolean) {
|
||||||
|
|||||||
@@ -11,4 +11,5 @@ export default interface User {
|
|||||||
surname?: string;
|
surname?: string;
|
||||||
groups: string[];
|
groups: string[];
|
||||||
regDate: Moment;
|
regDate: Moment;
|
||||||
|
defaultPage?: string;
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user