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
88 changes: 36 additions & 52 deletions src/app/auth/auth.component.ts
Original file line number Diff line number Diff line change
@@ -1,28 +1,27 @@
import {
AuthResponseData,
AuthService
} from '../core/_services/access/auth.service';
import { environment } from './../../environments/environment';
import { Component, Inject, OnInit } from '@angular/core';
import { Router } from '@angular/router';
import { NgForm } from '@angular/forms';
import { Observable } from 'rxjs';

import { LocalStorageService } from '../core/_services/storage/local-storage.service';
import { UnsubscribeService } from '../core/_services/unsubscribe.service';
import { ConfigService } from '../core/_services/shared/config.service';
import { UISettingsUtilityClass } from '../shared/utils/config';
import { UIConfig } from '../core/_models/config-ui.model';
import { Component, OnInit } from '@angular/core';
import { OnDestroy } from '@angular/core';
import { FormGroup } from '@angular/forms';
import { FormControl } from '@angular/forms';
import { Validators } from '@angular/forms';
import { OnDestroy } from '@angular/core';
import { NgZone } from '@angular/core';

import { UIConfig } from '@models/config-ui.model';

import { AuthResponseData, AuthService } from '@services/access/auth.service';
import { AlertService } from '@services/shared/alert.service';
import { ConfigService } from '@services/shared/config.service';
import { LocalStorageService } from '@services/storage/local-storage.service';
import { UnsubscribeService } from '@services/unsubscribe.service';

import { UISettingsUtilityClass } from '@src/app/shared/utils/config';
import { environment } from '@src/environments/environment';
import { HeaderConfig } from '@src/config/default/app/config.model';

@Component({
selector: 'app-login',
templateUrl: './auth.component.html',
standalone: false
selector: 'app-login',
templateUrl: './auth.component.html',
standalone: false
})
export class AuthComponent implements OnInit, OnDestroy {
/** Form group for the new SuperHashlist. */
Expand All @@ -32,7 +31,7 @@ export class AuthComponent implements OnInit, OnDestroy {

protected uiSettings: UISettingsUtilityClass;
public isVisible = true;
headerConfig: any;
headerConfig: HeaderConfig;
isDarkMode = false;

/** on loggin loading */
Expand All @@ -43,8 +42,7 @@ export class AuthComponent implements OnInit, OnDestroy {
private storage: LocalStorageService<UIConfig>,
private configService: ConfigService,
private authService: AuthService,
private ngZone: NgZone,
private router: Router
private alertService: AlertService
) {
this.headerConfig = environment.config.header;
this.uiSettings = new UISettingsUtilityClass(this.storage);
Expand Down Expand Up @@ -77,17 +75,14 @@ export class AuthComponent implements OnInit, OnDestroy {
*/
buildForm(): void {
this.loginForm = new FormGroup({
username: new FormControl(null, [
Validators.required,
Validators.minLength(2)
]),
password: new FormControl(null, [
Validators.required,
Validators.minLength(3)
])
username: new FormControl(null, [Validators.required, Validators.minLength(2)]),
password: new FormControl(null, [Validators.required, Validators.minLength(3)])
});
}

/**
* Handle login, when user submits the login form.
*/
onSubmit() {
if (this.loginForm.invalid) {
return;
Expand All @@ -97,43 +92,32 @@ export class AuthComponent implements OnInit, OnDestroy {

this.isLoading = true; // Show spinner

let authObs: Observable<AuthResponseData>;
authObs = this.authService.logIn(username, password);
const authObs: Observable<AuthResponseData> = this.authService.logIn(username, password);

const authSubscription$ = authObs.subscribe(
(resData) => {
this.handleSuccessfulLogin(resData);
const authSubscription$ = authObs.subscribe({
next: () => {
this.loginForm.reset();
},
(error) => {
error: () => {
this.isLoading = false;
this.handleError('An error occurred. Please try again later.');
},
() => {
complete: () => {
this.isLoading = false; // Hide spinner after attempting to log in
}
);
});

this.unsubscribeService.add(authSubscription$);
}

private handleSuccessfulLogin(resData: AuthResponseData): void {
if (this.authService.redirectUrl) {
const redirectUrl = this.authService.redirectUrl;
this.authService.redirectUrl = '';
this.authService.setUserLoggedIn(true);
this.router.navigate([redirectUrl]);
} else {
this.router.navigate(['/']);
}
}

/**
* Show and log specified error message
* @param errorMessage Message to log/display
* @private
*/
private handleError(errorMessage: string): void {
this.errorRes = errorMessage;
console.log(this.errorRes);
}

onHandleError() {
this.errorRes = null;
this.alertService.showErrorMessage(errorMessage);
}
}
7 changes: 7 additions & 0 deletions src/app/core/_services/access/auth.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { AuthData, AuthUser } from '@models/auth-user.model';
import { PermissionService } from '@services/permission/permission.service';
import { ConfigService } from '@services/shared/config.service';
import { LocalStorageService } from '@services/storage/local-storage.service';
import { LoginRedirectService } from '@services/access/login-redirect.service';

export interface AuthResponseData {
token: string;
Expand Down Expand Up @@ -93,6 +94,12 @@ export class AuthService {
this.userAuthChanged(true);
const permissionService = this.injector.get(PermissionService);
return permissionService.loadPermissions();
}),
tap(() => {
const redirectService = this.injector.get(LoginRedirectService);
const redirectUrl = this.redirectUrl;
redirectService.handlePostLoginRedirect(this.userId, redirectUrl);
this.redirectUrl = '';
})
);
}
Expand Down
37 changes: 37 additions & 0 deletions src/app/core/_services/access/login-redirect.service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import { Injectable } from '@angular/core';
import { Router } from '@angular/router';

import { LocalStorageService } from '@services/storage/local-storage.service';

/**
* This service redirects the user to the dashboard, if current logged-in user is another user then the last logged in
* user and uses LocalStorageService to keep track of current and last logged-in user.
*
* The service is meant to be used after successful login in the login workflow.
*/
@Injectable({ providedIn: 'root' })
export class LoginRedirectService {
private readonly LAST_USER_KEY = 'lastLoggedInUser';

constructor(
private router: Router,
private localStorage: LocalStorageService<string>
) {}

/**
* Redirect to redirect URL, if current and last user are the same, otherwise redirect to dashboard
* @param userId ID of current user
* @param redirectUrl Redirect URL used if current user is the same as the last logged-in user
*/
handlePostLoginRedirect(userId: string, redirectUrl: string): void {
const lastUser = this.localStorage.getItem(this.LAST_USER_KEY);

this.localStorage.setItem(this.LAST_USER_KEY, userId, 0);

if (lastUser === userId && redirectUrl) {
void this.router.navigate([redirectUrl]);
} else {
void this.router.navigate(['/']);
}
}
}
3 changes: 2 additions & 1 deletion src/app/core/_services/storage/local-storage.service.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { Injectable } from '@angular/core';
import { BaseStorageService, StorageWrapper } from './base-storage.service';

import { BaseStorageService, StorageWrapper } from '@services/storage/base-storage.service';

/**
* A storage service implementation that uses browser's local storage to store and retrieve data
Expand Down
48 changes: 48 additions & 0 deletions src/config/default/app/config.model.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
// Interfaces for app config

export interface BrandConfig {
logo: string;
logored: string;
name: string;
height: string;
width: string;
heightred: string;
widthred: string;
}

export interface HeaderConfig {
brand: BrandConfig;
}

export interface FooterConfig {
copyright: string;
footer_link_one: FooterLink;
footer_link_two: FooterLink;
footer_link_three: FooterLink;
}

export interface FooterLink {
link: string;
name: string;
}

export interface Config {
prodApiEndpoint: string;
prodApiMaxResults: number;
agentURL: string;
agentdownloadURL: string;
appName: string;
favicon: string;
header: HeaderConfig;
footer: FooterConfig;
agents: {
statusOrderBy: string;
statusOrderByName: string;
};
tasks: {
priority: number;
maxAgents: number;
chunkSize: number;
};
chunkSizeTUS: number;
}
20 changes: 11 additions & 9 deletions src/config/default/app/main.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
export const DEFAULT_CONFIG = {
import { Config } from '@src/config/default/app/config.model';

export const DEFAULT_CONFIG: Config = {
prodApiEndpoint: 'http://localhost:8080/api/v2',
prodApiMaxResults: 3000,
agentURL: '/server.php',
Expand All @@ -13,10 +15,10 @@ export const DEFAULT_CONFIG = {
height: '60',
width: '60',
heightred: '60',
widthred: '60',
},
widthred: '60'
}
},
footer:{
footer: {
copyright: 's3in!c Hashtopolis: 0.14.3',
footer_link_one: {
link: 'https://github.com/hashtopolis',
Expand All @@ -31,15 +33,15 @@ export const DEFAULT_CONFIG = {
name: 'Hashtopolis'
}
},
agents:{
agents: {
statusOrderBy: 'asc',
statusOrderByName: 'agentName',
statusOrderByName: 'agentName'
},
tasks:{
tasks: {
priority: 0,
maxAgents: 0,
chunkSize: 0,
chunkSize: 0
},
// File settings 10 * 1024 *1024 (5.24mb)
chunkSizeTUS: 5242880,
chunkSizeTUS: 5242880
};