mirror of
https://github.com/GNS3/gns3-web-ui.git
synced 2025-01-22 04:18:08 +00:00
Login component added
This commit is contained in:
parent
5cfda3500a
commit
71077413b7
@ -5,6 +5,7 @@ import { DirectLinkComponent } from './components/direct-link/direct-link.compon
|
|||||||
import { HelpComponent } from './components/help/help.component';
|
import { HelpComponent } from './components/help/help.component';
|
||||||
import { ReportIssueComponent } from './components/help/report-issue/report-issue.component';
|
import { ReportIssueComponent } from './components/help/report-issue/report-issue.component';
|
||||||
import { InstalledSoftwareComponent } from './components/installed-software/installed-software.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 { PageNotFoundComponent } from './components/page-not-found/page-not-found.component';
|
||||||
import { BuiltInPreferencesComponent } from './components/preferences/built-in/built-in-preferences.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';
|
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: '', redirectTo: 'servers', pathMatch: 'full' },
|
||||||
{ path: 'servers', component: ServersComponent },
|
{ path: 'servers', component: ServersComponent },
|
||||||
{ path: 'bundled', component: BundledServerFinderComponent },
|
{ path: 'bundled', component: BundledServerFinderComponent },
|
||||||
|
{ path: 'server/:server_id/login', component: LoginComponent },
|
||||||
{
|
{
|
||||||
path: 'server/:server_id/projects',
|
path: 'server/:server_id/projects',
|
||||||
component: ProjectsComponent,
|
component: ProjectsComponent,
|
||||||
|
@ -269,11 +269,14 @@ import { VpcsService } from './services/vpcs.service';
|
|||||||
import { NonNegativeValidator } from './validators/non-negative-validator';
|
import { NonNegativeValidator } from './validators/non-negative-validator';
|
||||||
import { RotationValidator } from './validators/rotation-validator';
|
import { RotationValidator } from './validators/rotation-validator';
|
||||||
import { MarkedDirective } from './directives/marked.directive';
|
import { MarkedDirective } from './directives/marked.directive';
|
||||||
|
import { LoginComponent } from './components/login/login.component';
|
||||||
|
import { LoginService } from './services/login.service';
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
declarations: [
|
declarations: [
|
||||||
AppComponent,
|
AppComponent,
|
||||||
ProjectMapComponent,
|
ProjectMapComponent,
|
||||||
|
LoginComponent,
|
||||||
ServersComponent,
|
ServersComponent,
|
||||||
AddServerDialogComponent,
|
AddServerDialogComponent,
|
||||||
CreateSnapshotDialogComponent,
|
CreateSnapshotDialogComponent,
|
||||||
@ -549,6 +552,7 @@ import { MarkedDirective } from './directives/marked.directive';
|
|||||||
Title,
|
Title,
|
||||||
ApplianceService,
|
ApplianceService,
|
||||||
UpdatesService,
|
UpdatesService,
|
||||||
|
LoginService
|
||||||
],
|
],
|
||||||
entryComponents: [
|
entryComponents: [
|
||||||
AddServerDialogComponent,
|
AddServerDialogComponent,
|
||||||
|
30
src/app/components/login/login.component.html
Normal file
30
src/app/components/login/login.component.html
Normal 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>
|
31
src/app/components/login/login.component.scss
Normal file
31
src/app/components/login/login.component.scss
Normal 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%;
|
||||||
|
}
|
0
src/app/components/login/login.component.spec.ts
Normal file
0
src/app/components/login/login.component.spec.ts
Normal file
66
src/app/components/login/login.component.ts
Normal file
66
src/app/components/login/login.component.ts
Normal 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']);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
@ -127,7 +127,7 @@ export class TemplateComponent implements OnInit, OnDestroy {
|
|||||||
}
|
}
|
||||||
|
|
||||||
getImageSourceForTemplate(template: Template) {
|
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() {
|
ngOnDestroy() {
|
||||||
|
0
src/app/guards/login-guard.ts
Normal file
0
src/app/guards/login-guard.ts
Normal file
@ -39,4 +39,4 @@
|
|||||||
|
|
||||||
<app-progress></app-progress>
|
<app-progress></app-progress>
|
||||||
|
|
||||||
<footer class="footer mat-app-background">GNS3 Web UI © 2020 - v{{ uiVersion }}</footer>
|
<footer class="footer mat-app-background">GNS3 Web UI © 2021 - v{{ uiVersion }}</footer>
|
||||||
|
4
src/app/models/authResponse.ts
Normal file
4
src/app/models/authResponse.ts
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
export interface AuthResponse {
|
||||||
|
access_token: string;
|
||||||
|
token_type: string;
|
||||||
|
}
|
@ -3,6 +3,7 @@ export type ServerStatus = 'stopped' | 'starting' | 'running';
|
|||||||
export type ServerProtocol = 'http:' | 'https:';
|
export type ServerProtocol = 'http:' | 'https:';
|
||||||
|
|
||||||
export class Server {
|
export class Server {
|
||||||
|
authToken: string;
|
||||||
id: number;
|
id: number;
|
||||||
name: string;
|
name: string;
|
||||||
location: ServerLocation;
|
location: ServerLocation;
|
||||||
|
@ -187,10 +187,9 @@ export class HttpServer {
|
|||||||
options.headers = {};
|
options.headers = {};
|
||||||
}
|
}
|
||||||
|
|
||||||
// if (server.authorization === 'basic') {
|
if (server.authToken) {
|
||||||
// const credentials = btoa(`${server.login}:${server.password}`);
|
options.headers['Authorization'] = `Bearer ${server.authToken}`;
|
||||||
// options.headers['Authorization'] = `Basic ${credentials}`;
|
}
|
||||||
// }
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
url: url,
|
url: url,
|
||||||
|
23
src/app/services/login.service.ts
Normal file
23
src/app/services/login.service.ts
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
@ -5,6 +5,7 @@ import { Node } from '../cartography/models/node';
|
|||||||
import { Server } from '../models/server';
|
import { Server } from '../models/server';
|
||||||
import { Symbol } from '../models/symbol';
|
import { Symbol } from '../models/symbol';
|
||||||
import { HttpServer } from './http-server.service';
|
import { HttpServer } from './http-server.service';
|
||||||
|
import { Template } from '../models/template';
|
||||||
|
|
||||||
const CACHE_SIZE = 1;
|
const CACHE_SIZE = 1;
|
||||||
|
|
||||||
@ -62,6 +63,10 @@ export class SymbolService {
|
|||||||
const encoded_uri = encodeURI(symbol_id);
|
const encoded_uri = encodeURI(symbol_id);
|
||||||
return this.httpServer.getText(server, `/symbols/${encoded_uri}/raw`);
|
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 {
|
class SymbolDimension {
|
||||||
|
Loading…
Reference in New Issue
Block a user