Login component added

This commit is contained in:
piotrpekala7 2021-04-29 17:32:53 +02:00
parent 5cfda3500a
commit 71077413b7
14 changed files with 171 additions and 6 deletions

View File

@ -5,6 +5,7 @@ import { DirectLinkComponent } from './components/direct-link/direct-link.compon
import { HelpComponent } from './components/help/help.component';
import { ReportIssueComponent } from './components/help/report-issue/report-issue.component';
import { InstalledSoftwareComponent } from './components/installed-software/installed-software.component';
import { LoginComponent } from './components/login/login.component';
import { PageNotFoundComponent } from './components/page-not-found/page-not-found.component';
import { BuiltInPreferencesComponent } from './components/preferences/built-in/built-in-preferences.component';
import { CloudNodesAddTemplateComponent } from './components/preferences/built-in/cloud-nodes/cloud-nodes-add-template/cloud-nodes-add-template.component';
@ -63,6 +64,7 @@ const routes: Routes = [
{ path: '', redirectTo: 'servers', pathMatch: 'full' },
{ path: 'servers', component: ServersComponent },
{ path: 'bundled', component: BundledServerFinderComponent },
{ path: 'server/:server_id/login', component: LoginComponent },
{
path: 'server/:server_id/projects',
component: ProjectsComponent,

View File

@ -269,11 +269,14 @@ import { VpcsService } from './services/vpcs.service';
import { NonNegativeValidator } from './validators/non-negative-validator';
import { RotationValidator } from './validators/rotation-validator';
import { MarkedDirective } from './directives/marked.directive';
import { LoginComponent } from './components/login/login.component';
import { LoginService } from './services/login.service';
@NgModule({
declarations: [
AppComponent,
ProjectMapComponent,
LoginComponent,
ServersComponent,
AddServerDialogComponent,
CreateSnapshotDialogComponent,
@ -549,6 +552,7 @@ import { MarkedDirective } from './directives/marked.directive';
Title,
ApplianceService,
UpdatesService,
LoginService
],
entryComponents: [
AddServerDialogComponent,

View File

@ -0,0 +1,30 @@
<div class="wrapper">
<div class="loginCard">
<mat-card class="matCard">
<div class="loginTitle">
<div class="loginIcon">
<mat-icon class="mat-icon-login" svgIcon="gns3"></mat-icon>
<div>
<h1>GNS3</h1>
<h6>v{{version}}</h6>
</div>
</div>
</div>
<form [formGroup]="loginForm">
<mat-form-field>
<input matInput formControlName="username" placeholder="Username" />
<mat-error *ngIf="loginForm.get('username').hasError('required')">You must enter username</mat-error>
</mat-form-field>
<mat-form-field>
<input matInput formControlName="password" placeholder="Password" />
<mat-error *ngIf="loginForm.get('password').hasError('required')">You must enter password</mat-error>
</mat-form-field>
</form>
<div class="buttons-bar">
<button class="loginButton" mat-raised-button color="primary" (click)="login()">Login</button>
</div>
</mat-card>
</div>
</div>

View File

@ -0,0 +1,31 @@
mat-form-field {
width: 100%;
}
.wrapper {
display: flex;
justify-content: center;
}
.loginCard {
width: 540px;
}
.mat-icon-login {
height: 200px!important;
width: 200px!important;
}
.loginTitle {
display: flex;
justify-content: center;
}
.loginIcon {
display: flex;
align-items: center;
}
.loginButton {
width: 100%;
}

View File

@ -0,0 +1,66 @@
import { Component, ComponentFactoryResolver, OnInit, ViewEncapsulation } from '@angular/core';
import { FormControl, FormGroup, Validators } from '@angular/forms';
import { ActivatedRoute, ParamMap, Router } from '@angular/router';
import { Server } from '../../models/server';
import { LoginService } from '../../services/login.service';
import { ServerDatabase } from '../../services/server.database';
import { ServerService } from '../../services/server.service';
import { ToasterService } from '../../services/toaster.service';
import { AuthResponse } from '../../models/authResponse';
import { VersionService } from '../../services/version.service';
import { Version } from '../../models/version';
@Component({
selector: 'app-login',
templateUrl: './login.component.html',
styleUrls: ['./login.component.scss'],
encapsulation: ViewEncapsulation.None,
})
export class LoginComponent implements OnInit {
private server: Server;
public version: string;
loginForm = new FormGroup({
username: new FormControl('', [Validators.required]),
password: new FormControl('', [Validators.required])
});
constructor(
private loginService: LoginService,
private serverService: ServerService,
private serverDatabase: ServerDatabase,
private route: ActivatedRoute,
private router: Router,
private toasterService: ToasterService,
private versionService: VersionService
) {}
async ngOnInit() {
const server_id = this.route.snapshot.paramMap.get('server_id');
this.serverService.get(parseInt(server_id, 10)).then((server: Server) => {
this.server = server;
this.versionService.get(this.server).subscribe((version: Version) => {
this.version = version.version;
});
});
}
public login() {
if (this.loginForm.get('username').invalid || this.loginForm.get('password').invalid) {
this.toasterService.error("Please enter username and password")
return;
}
let username = this.loginForm.get('username').value;
let password = this.loginForm.get('password').value;
this.loginService.login(this.server, username, password).subscribe(async (response: AuthResponse) => {
let server = this.server;
server.authToken = response.access_token;
await this.serverService.update(server);
this.router.navigate(['/server', this.server.id, 'projects']);
});
}
}

View File

@ -127,7 +127,7 @@ export class TemplateComponent implements OnInit, OnDestroy {
}
getImageSourceForTemplate(template: Template) {
return `${this.server.protocol}//${this.server.host}:${this.server.port}/v3/symbols/${template.symbol}/raw`;
return this.symbolService.getSymbolFromTemplate(this.server, template);
}
ngOnDestroy() {

View File

View File

@ -39,4 +39,4 @@
<app-progress></app-progress>
<footer class="footer mat-app-background">GNS3 Web UI &copy; 2020 - v{{ uiVersion }}</footer>
<footer class="footer mat-app-background">GNS3 Web UI &copy; 2021 - v{{ uiVersion }}</footer>

View File

@ -0,0 +1,4 @@
export interface AuthResponse {
access_token: string;
token_type: string;
}

View File

@ -3,6 +3,7 @@ export type ServerStatus = 'stopped' | 'starting' | 'running';
export type ServerProtocol = 'http:' | 'https:';
export class Server {
authToken: string;
id: number;
name: string;
location: ServerLocation;

View File

@ -187,10 +187,9 @@ export class HttpServer {
options.headers = {};
}
// if (server.authorization === 'basic') {
// const credentials = btoa(`${server.login}:${server.password}`);
// options.headers['Authorization'] = `Basic ${credentials}`;
// }
if (server.authToken) {
options.headers['Authorization'] = `Bearer ${server.authToken}`;
}
return {
url: url,

View File

@ -0,0 +1,23 @@
import { HttpHeaders, HttpParams } from '@angular/common/http';
import { Injectable } from '@angular/core';
import 'rxjs/add/operator/map';
import { Server } from '../models/server';
import { HttpServer } from './http-server.service';
import { AuthResponse } from '../models/authResponse';
@Injectable()
export class LoginService {
constructor(private httpServer: HttpServer) {}
login(server: Server, username: string, password: string) {
const payload = new HttpParams()
.set('username', username)
.set('password', password);
const options = {
headers: new HttpHeaders().set('Content-Type', 'application/x-www-form-urlencoded')
};
return this.httpServer.post<AuthResponse>(server, '/users/login', payload, options);
}
}

View File

@ -5,6 +5,7 @@ import { Node } from '../cartography/models/node';
import { Server } from '../models/server';
import { Symbol } from '../models/symbol';
import { HttpServer } from './http-server.service';
import { Template } from '../models/template';
const CACHE_SIZE = 1;
@ -62,6 +63,10 @@ export class SymbolService {
const encoded_uri = encodeURI(symbol_id);
return this.httpServer.getText(server, `/symbols/${encoded_uri}/raw`);
}
getSymbolFromTemplate(server: Server, template: Template) {
return `${server.protocol}//${server.host}:${server.port}/v3/symbols/${template.symbol}/raw`;
}
}
class SymbolDimension {