* auth added
This commit is contained in:
parent
7a44ba70d4
commit
03a160dafe
67
deploy.php
Normal file
67
deploy.php
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Deployer;
|
||||||
|
require 'recipe/common.php';
|
||||||
|
|
||||||
|
set('ssh_type', 'native');
|
||||||
|
set('ssh_multiplexing', true);
|
||||||
|
|
||||||
|
// Configuration
|
||||||
|
|
||||||
|
// set('repository', 'git@domain.com:username/repository.git');
|
||||||
|
set('shared_files', []);
|
||||||
|
set('shared_dirs', []);
|
||||||
|
set('writable_dirs', []);
|
||||||
|
set('keep_releases', 3);
|
||||||
|
set('default_stage', 'staging');
|
||||||
|
|
||||||
|
// Servers
|
||||||
|
host('alfheim')
|
||||||
|
->stage('staging')
|
||||||
|
->user('yvan')
|
||||||
|
->forwardAgent()
|
||||||
|
->set('ng_basehref', '/admin/')
|
||||||
|
->set('ng_target', 'production')
|
||||||
|
->set('ng_environment', 'prod')
|
||||||
|
->set('env_vars', 'NODE_ENV=production')
|
||||||
|
->set('deploy_path', '/mnt/apps/granprize/admin');
|
||||||
|
|
||||||
|
host('granprize')
|
||||||
|
->stage('production')
|
||||||
|
->user('edvidan')
|
||||||
|
->forwardAgent()
|
||||||
|
->set('ng_basehref', '/admin/')
|
||||||
|
->set('ng_target', 'production')
|
||||||
|
->set('ng_environment', 'prod')
|
||||||
|
->set('env_vars', 'NODE_ENV=production')
|
||||||
|
->set('deploy_path', '/var/www/granprize.swedishchamber.hu/admin');
|
||||||
|
|
||||||
|
// Tasks
|
||||||
|
desc('Prepare release');
|
||||||
|
task('deploy:ng-prepare', function() {
|
||||||
|
runLocally("ng build --base-href={{ng_basehref}} --target={{ng_target}} --environment={{ng_environment}}");
|
||||||
|
runLocally("tar -cJf dist.tar.xz dist");
|
||||||
|
});
|
||||||
|
|
||||||
|
desc('Upload release');
|
||||||
|
task('deploy:ng-upload', function() {
|
||||||
|
upload("dist.tar.xz", "{{release_path}}/dist.tar.xz");
|
||||||
|
run("tar -C {{release_path}} -xJf {{release_path}}/dist.tar.xz");
|
||||||
|
run("rm -f {{release_path}}/dist.tar.xz");
|
||||||
|
runLocally("rm -rf dist.tar.xz dist");
|
||||||
|
});
|
||||||
|
|
||||||
|
desc('Deploy your project');
|
||||||
|
task('deploy', [
|
||||||
|
'deploy:prepare',
|
||||||
|
'deploy:lock',
|
||||||
|
'deploy:release',
|
||||||
|
'deploy:ng-prepare',
|
||||||
|
'deploy:ng-upload',
|
||||||
|
'deploy:shared',
|
||||||
|
'deploy:clear_paths',
|
||||||
|
'deploy:symlink',
|
||||||
|
'deploy:unlock',
|
||||||
|
'cleanup',
|
||||||
|
]);
|
||||||
|
after('deploy', 'success');
|
||||||
15
package-lock.json
generated
15
package-lock.json
generated
@ -392,6 +392,14 @@
|
|||||||
"tslib": "1.9.0"
|
"tslib": "1.9.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"@auth0/angular-jwt": {
|
||||||
|
"version": "2.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@auth0/angular-jwt/-/angular-jwt-2.0.0.tgz",
|
||||||
|
"integrity": "sha512-RVlXFpcqQ+9uCpzboU7Tm1ubaRVO2FrR5+RYuwHtTT4BXquVMEwOSbAuuaArFud/kMc00XYoGgiP1JkCfOAfpA==",
|
||||||
|
"requires": {
|
||||||
|
"url": "0.11.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"@fortawesome/fontawesome-free-webfonts": {
|
"@fortawesome/fontawesome-free-webfonts": {
|
||||||
"version": "1.0.8",
|
"version": "1.0.8",
|
||||||
"resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-free-webfonts/-/fontawesome-free-webfonts-1.0.8.tgz",
|
"resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-free-webfonts/-/fontawesome-free-webfonts-1.0.8.tgz",
|
||||||
@ -7547,8 +7555,7 @@
|
|||||||
"querystring": {
|
"querystring": {
|
||||||
"version": "0.2.0",
|
"version": "0.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz",
|
||||||
"integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=",
|
"integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA="
|
||||||
"dev": true
|
|
||||||
},
|
},
|
||||||
"querystring-es3": {
|
"querystring-es3": {
|
||||||
"version": "0.2.1",
|
"version": "0.2.1",
|
||||||
@ -9611,7 +9618,6 @@
|
|||||||
"version": "0.11.0",
|
"version": "0.11.0",
|
||||||
"resolved": "https://registry.npmjs.org/url/-/url-0.11.0.tgz",
|
"resolved": "https://registry.npmjs.org/url/-/url-0.11.0.tgz",
|
||||||
"integrity": "sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE=",
|
"integrity": "sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE=",
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
"requires": {
|
||||||
"punycode": "1.3.2",
|
"punycode": "1.3.2",
|
||||||
"querystring": "0.2.0"
|
"querystring": "0.2.0"
|
||||||
@ -9620,8 +9626,7 @@
|
|||||||
"punycode": {
|
"punycode": {
|
||||||
"version": "1.3.2",
|
"version": "1.3.2",
|
||||||
"resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz",
|
"resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz",
|
||||||
"integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=",
|
"integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0="
|
||||||
"dev": true
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@ -22,6 +22,7 @@
|
|||||||
"@angular/platform-browser": "^6.0.0",
|
"@angular/platform-browser": "^6.0.0",
|
||||||
"@angular/platform-browser-dynamic": "^6.0.0",
|
"@angular/platform-browser-dynamic": "^6.0.0",
|
||||||
"@angular/router": "^6.0.0",
|
"@angular/router": "^6.0.0",
|
||||||
|
"@auth0/angular-jwt": "^2.0.0",
|
||||||
"@fortawesome/fontawesome-free-webfonts": "^1.0.8",
|
"@fortawesome/fontawesome-free-webfonts": "^1.0.8",
|
||||||
"core-js": "^2.5.4",
|
"core-js": "^2.5.4",
|
||||||
"rxjs": "^6.0.0",
|
"rxjs": "^6.0.0",
|
||||||
|
|||||||
@ -10,53 +10,61 @@ import { JudgeResolverService } from "./shared/judge-resolver.service";
|
|||||||
import { AwardeeService } from "./shared/awardee.service";
|
import { AwardeeService } from "./shared/awardee.service";
|
||||||
import { AwardeeResolverService } from "./shared/awardee-resolver.service";
|
import { AwardeeResolverService } from "./shared/awardee-resolver.service";
|
||||||
import { YearResolverService } from "./shared/year-resolver.service";
|
import { YearResolverService } from "./shared/year-resolver.service";
|
||||||
|
import { AuthGuardService } from "./auth/auth-guard.service";
|
||||||
|
|
||||||
const routes: Routes = [
|
const routes: Routes = [
|
||||||
{
|
{
|
||||||
path: 'awardees',
|
path: 'awardees',
|
||||||
component: AwardeeListComponent,
|
component: AwardeeListComponent,
|
||||||
resolve: {
|
resolve: {
|
||||||
awardees: AwardeeService,
|
awardees: AwardeeService,
|
||||||
}
|
},
|
||||||
// canActivate: [AuthGuardService, RoleGuardService],
|
canActivate: [AuthGuardService],
|
||||||
}, {
|
}, {
|
||||||
path: 'awardee/new',
|
path: 'awardee/new',
|
||||||
component: AwardeeEditorComponent,
|
component: AwardeeEditorComponent,
|
||||||
resolve: {
|
resolve: {
|
||||||
years: YearResolverService,
|
years: YearResolverService,
|
||||||
}
|
},
|
||||||
// canActivate: [AuthGuardService, RoleGuardService],
|
canActivate: [AuthGuardService],
|
||||||
}, {
|
}, {
|
||||||
path: 'awardee/edit/:id',
|
path: 'awardee/edit/:id',
|
||||||
component: AwardeeEditorComponent,
|
component: AwardeeEditorComponent,
|
||||||
resolve: {
|
resolve: {
|
||||||
awardee: AwardeeResolverService,
|
awardee: AwardeeResolverService,
|
||||||
years: YearResolverService,
|
years: YearResolverService,
|
||||||
}
|
},
|
||||||
// canActivate: [AuthGuardService, RoleGuardService],
|
canActivate: [AuthGuardService],
|
||||||
}, {
|
}, {
|
||||||
path: 'judges',
|
path: 'judges',
|
||||||
component: JudgeListComponent,
|
component: JudgeListComponent,
|
||||||
resolve: {
|
resolve: {
|
||||||
judges: JudgeService,
|
judges: JudgeService,
|
||||||
}
|
},
|
||||||
// canActivate: [AuthGuardService, RoleGuardService],
|
canActivate: [AuthGuardService],
|
||||||
}, {
|
}, {
|
||||||
path: 'judge/new',
|
path: 'judge/new',
|
||||||
component: JudgeEditorComponent,
|
component: JudgeEditorComponent,
|
||||||
// canActivate: [AuthGuardService, RoleGuardService],
|
canActivate: [AuthGuardService],
|
||||||
}, {
|
}, {
|
||||||
path: 'judge/edit/:id',
|
path: 'judge/edit/:id',
|
||||||
component: JudgeEditorComponent,
|
component: JudgeEditorComponent,
|
||||||
resolve: {
|
resolve: {
|
||||||
judge: JudgeResolverService,
|
judge: JudgeResolverService,
|
||||||
}
|
},
|
||||||
// canActivate: [AuthGuardService, RoleGuardService],
|
canActivate: [AuthGuardService],
|
||||||
}
|
}, {
|
||||||
|
path: '',
|
||||||
|
redirectTo: '/awardees',
|
||||||
|
pathMatch: 'full',
|
||||||
|
canActivate: [AuthGuardService]
|
||||||
|
},
|
||||||
|
// {path: '**', component: PageNotFoundComponent},
|
||||||
];
|
];
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
imports: [RouterModule.forRoot(routes)],
|
imports: [RouterModule.forRoot(routes)],
|
||||||
exports: [RouterModule]
|
exports: [RouterModule]
|
||||||
})
|
})
|
||||||
export class AppRoutingModule {}
|
export class AppRoutingModule {
|
||||||
|
}
|
||||||
|
|||||||
@ -1,8 +1,15 @@
|
|||||||
import { Component } from '@angular/core';
|
import { Component } from '@angular/core';
|
||||||
|
import { AuthService } from "./auth/auth.service";
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-root',
|
selector: 'app-root',
|
||||||
templateUrl: './app.component.html',
|
templateUrl: './app.component.html',
|
||||||
styleUrls: ['./app.component.css']
|
styleUrls: ['./app.component.css']
|
||||||
})
|
})
|
||||||
export class AppComponent {}
|
export class AppComponent {
|
||||||
|
constructor(private authService: AuthService) {}
|
||||||
|
|
||||||
|
get loggedIn(): boolean {
|
||||||
|
return this.authService.isLoggedIn;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -34,6 +34,7 @@ import { AwardeeListTableComponent } from './awardee-list-table/awardee-list-tab
|
|||||||
import { AwardeeEditorComponent } from './awardee-editor/awardee-editor.component';
|
import { AwardeeEditorComponent } from './awardee-editor/awardee-editor.component';
|
||||||
import { JudgeEditorComponent } from './judge-editor/judge-editor.component';
|
import { JudgeEditorComponent } from './judge-editor/judge-editor.component';
|
||||||
import { ConfirmDialogComponent } from './confirm-dialog/confirm-dialog.component';
|
import { ConfirmDialogComponent } from './confirm-dialog/confirm-dialog.component';
|
||||||
|
import { AuthModule } from "./auth/auth.module";
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
declarations: [
|
declarations: [
|
||||||
@ -55,7 +56,6 @@ import { ConfirmDialogComponent } from './confirm-dialog/confirm-dialog.componen
|
|||||||
BrowserAnimationsModule,
|
BrowserAnimationsModule,
|
||||||
FormsModule,
|
FormsModule,
|
||||||
HttpClientModule,
|
HttpClientModule,
|
||||||
AppRoutingModule,
|
|
||||||
LayoutModule,
|
LayoutModule,
|
||||||
MatToolbarModule,
|
MatToolbarModule,
|
||||||
MatButtonModule,
|
MatButtonModule,
|
||||||
@ -74,6 +74,9 @@ import { ConfirmDialogComponent } from './confirm-dialog/confirm-dialog.componen
|
|||||||
MatExpansionModule,
|
MatExpansionModule,
|
||||||
MatTooltipModule,
|
MatTooltipModule,
|
||||||
MatDialogModule,
|
MatDialogModule,
|
||||||
|
|
||||||
|
AuthModule,
|
||||||
|
AppRoutingModule,
|
||||||
],
|
],
|
||||||
providers: [],
|
providers: [],
|
||||||
bootstrap: [AppComponent]
|
bootstrap: [AppComponent]
|
||||||
|
|||||||
15
src/app/auth/auth-guard.service.spec.ts
Normal file
15
src/app/auth/auth-guard.service.spec.ts
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
import { TestBed, inject } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { AuthGuardService } from './auth-guard.service';
|
||||||
|
|
||||||
|
describe('AuthGuardService', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
TestBed.configureTestingModule({
|
||||||
|
providers: [AuthGuardService]
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should be created', inject([AuthGuardService], (service: AuthGuardService) => {
|
||||||
|
expect(service).toBeTruthy();
|
||||||
|
}));
|
||||||
|
});
|
||||||
31
src/app/auth/auth-guard.service.ts
Normal file
31
src/app/auth/auth-guard.service.ts
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
import { Injectable } from '@angular/core';
|
||||||
|
import { ActivatedRouteSnapshot, Router, RouterStateSnapshot } from "@angular/router";
|
||||||
|
|
||||||
|
import { AuthService } from "./auth.service";
|
||||||
|
|
||||||
|
@Injectable({
|
||||||
|
providedIn: 'root'
|
||||||
|
})
|
||||||
|
export class AuthGuardService {
|
||||||
|
constructor(private authService: AuthService,
|
||||||
|
private router: Router) {
|
||||||
|
}
|
||||||
|
|
||||||
|
public canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean {
|
||||||
|
let url: string = state.url;
|
||||||
|
return this.checkLogin(url);
|
||||||
|
}
|
||||||
|
|
||||||
|
checkLogin(url: string): boolean {
|
||||||
|
if (this.authService.isLoggedIn) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Store the attempted URL for redirecting
|
||||||
|
this.authService.redirectUrl = url;
|
||||||
|
|
||||||
|
// Navigate to the login page with extras
|
||||||
|
this.router.navigate(['/login']);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
15
src/app/auth/auth-routing.module.ts
Normal file
15
src/app/auth/auth-routing.module.ts
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
import { NgModule } from '@angular/core';
|
||||||
|
import { Routes, RouterModule } from '@angular/router';
|
||||||
|
|
||||||
|
import { AuthComponent } from "./auth/auth.component";
|
||||||
|
|
||||||
|
const routes: Routes = [
|
||||||
|
{path: 'login', component: AuthComponent},
|
||||||
|
{path: 'logout', component: AuthComponent},
|
||||||
|
];
|
||||||
|
|
||||||
|
@NgModule({
|
||||||
|
imports: [RouterModule.forChild(routes)],
|
||||||
|
exports: [RouterModule]
|
||||||
|
})
|
||||||
|
export class AuthRoutingModule { }
|
||||||
13
src/app/auth/auth.module.spec.ts
Normal file
13
src/app/auth/auth.module.spec.ts
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
import { AuthModule } from './auth.module';
|
||||||
|
|
||||||
|
describe('AuthModule', () => {
|
||||||
|
let authModule: AuthModule;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
authModule = new AuthModule();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create an instance', () => {
|
||||||
|
expect(authModule).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
||||||
43
src/app/auth/auth.module.ts
Normal file
43
src/app/auth/auth.module.ts
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
import { NgModule } from '@angular/core';
|
||||||
|
import { CommonModule } from '@angular/common';
|
||||||
|
import { FormsModule } from "@angular/forms";
|
||||||
|
import { JwtModule } from '@auth0/angular-jwt';
|
||||||
|
|
||||||
|
import { AuthRoutingModule } from './auth-routing.module';
|
||||||
|
import { AuthComponent } from './auth/auth.component';
|
||||||
|
import {
|
||||||
|
MatButtonModule,
|
||||||
|
MatCardModule,
|
||||||
|
MatFormFieldModule,
|
||||||
|
MatInputModule
|
||||||
|
} from "@angular/material";
|
||||||
|
|
||||||
|
export function tokenGetterFunctionWrapper() {
|
||||||
|
return localStorage.getItem('token');
|
||||||
|
}
|
||||||
|
|
||||||
|
@NgModule({
|
||||||
|
imports: [
|
||||||
|
JwtModule.forRoot({
|
||||||
|
config: {
|
||||||
|
tokenGetter: tokenGetterFunctionWrapper,
|
||||||
|
whitelistedDomains: [
|
||||||
|
"localhost:8888",
|
||||||
|
"granprize.dev.yvan.hu",
|
||||||
|
"granprize.swedishchamber.hu",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
CommonModule,
|
||||||
|
FormsModule,
|
||||||
|
AuthRoutingModule,
|
||||||
|
|
||||||
|
MatCardModule,
|
||||||
|
MatFormFieldModule,
|
||||||
|
MatInputModule,
|
||||||
|
MatButtonModule,
|
||||||
|
],
|
||||||
|
declarations: [AuthComponent]
|
||||||
|
})
|
||||||
|
export class AuthModule {
|
||||||
|
}
|
||||||
15
src/app/auth/auth.service.spec.ts
Normal file
15
src/app/auth/auth.service.spec.ts
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
import { TestBed, inject } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { AuthService } from './auth.service';
|
||||||
|
|
||||||
|
describe('AuthService', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
TestBed.configureTestingModule({
|
||||||
|
providers: [AuthService]
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should be created', inject([AuthService], (service: AuthService) => {
|
||||||
|
expect(service).toBeTruthy();
|
||||||
|
}));
|
||||||
|
});
|
||||||
79
src/app/auth/auth.service.ts
Normal file
79
src/app/auth/auth.service.ts
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
import { Injectable } from '@angular/core';
|
||||||
|
import { environment } from "../../environments/environment";
|
||||||
|
import { HttpClient } from "@angular/common/http";
|
||||||
|
import { Router } from "@angular/router";
|
||||||
|
import { JwtHelperService } from "@auth0/angular-jwt";
|
||||||
|
|
||||||
|
const TOKEN_LS_NAME = 'token';
|
||||||
|
|
||||||
|
@Injectable({
|
||||||
|
providedIn: 'root'
|
||||||
|
})
|
||||||
|
export class AuthService {
|
||||||
|
private url = environment.apiUrl + '/auth';
|
||||||
|
|
||||||
|
public redirectUrl: string;
|
||||||
|
public isLoading: boolean = false;
|
||||||
|
public hasError: boolean = false;
|
||||||
|
public errorMessage: string = "";
|
||||||
|
|
||||||
|
constructor(private httpService: HttpClient,
|
||||||
|
private jwtHelperService: JwtHelperService,
|
||||||
|
private router: Router) {
|
||||||
|
}
|
||||||
|
|
||||||
|
get token(): string {
|
||||||
|
return localStorage.getItem(TOKEN_LS_NAME);
|
||||||
|
}
|
||||||
|
|
||||||
|
get isLoggedIn(): boolean {
|
||||||
|
try {
|
||||||
|
return !this.jwtHelperService.isTokenExpired(this.token);
|
||||||
|
} catch (ex) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
get tokenData() {
|
||||||
|
return this.jwtHelperService.decodeToken(this.token);
|
||||||
|
}
|
||||||
|
|
||||||
|
public authRedirect() {
|
||||||
|
this.router.navigate(['/login']);
|
||||||
|
}
|
||||||
|
|
||||||
|
public login(login: string, password: string) {
|
||||||
|
this.hasError = false;
|
||||||
|
this.isLoading = true;
|
||||||
|
this.httpService.post<string>(this.url + '/login',{
|
||||||
|
'user': login,
|
||||||
|
'pass': password,
|
||||||
|
}).subscribe(
|
||||||
|
apiResponse => {
|
||||||
|
this.isLoading = false;
|
||||||
|
localStorage.setItem(TOKEN_LS_NAME, apiResponse);
|
||||||
|
this.router.navigate(['/']);
|
||||||
|
},
|
||||||
|
err => {
|
||||||
|
console.log(err);
|
||||||
|
this.hasError = true;
|
||||||
|
this.errorMessage = "Hiba történt bejelentkezés közben.";
|
||||||
|
this.isLoading = false;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public renew() {
|
||||||
|
this.httpService.get<string>(this.url + '/renew')
|
||||||
|
.subscribe(
|
||||||
|
apiResponse => {
|
||||||
|
localStorage.setItem(TOKEN_LS_NAME, apiResponse);
|
||||||
|
},
|
||||||
|
err => console.log(err)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public logout() {
|
||||||
|
localStorage.removeItem(TOKEN_LS_NAME);
|
||||||
|
}
|
||||||
|
}
|
||||||
9
src/app/auth/auth/auth.component.css
Normal file
9
src/app/auth/auth/auth.component.css
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
.mat-card {
|
||||||
|
min-width: 250px;
|
||||||
|
width: 25%;
|
||||||
|
margin: 150px auto auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mat-form-field {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
12
src/app/auth/auth/auth.component.html
Normal file
12
src/app/auth/auth/auth.component.html
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
<mat-card>
|
||||||
|
<h2 mat-card-title="">GranPrize login</h2>
|
||||||
|
<form name="login-form" class="login-form" (ngSubmit)="doSubmit()">
|
||||||
|
<mat-form-field class="full-width">
|
||||||
|
<input name="username" type="text" matInput placeholder="Username" [(ngModel)]="userName">
|
||||||
|
</mat-form-field>
|
||||||
|
<mat-form-field class="full-width">
|
||||||
|
<input name="password" type="password" matInput placeholder="Password" [(ngModel)]="password">
|
||||||
|
</mat-form-field>
|
||||||
|
<button mat-raised-button color="primary" [disabled]="!canLogin">Login</button>
|
||||||
|
</form>
|
||||||
|
</mat-card>
|
||||||
25
src/app/auth/auth/auth.component.spec.ts
Normal file
25
src/app/auth/auth/auth.component.spec.ts
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { AuthComponent } from './auth.component';
|
||||||
|
|
||||||
|
describe('AuthComponent', () => {
|
||||||
|
let component: AuthComponent;
|
||||||
|
let fixture: ComponentFixture<AuthComponent>;
|
||||||
|
|
||||||
|
beforeEach(async(() => {
|
||||||
|
TestBed.configureTestingModule({
|
||||||
|
declarations: [ AuthComponent ]
|
||||||
|
})
|
||||||
|
.compileComponents();
|
||||||
|
}));
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
fixture = TestBed.createComponent(AuthComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
||||||
60
src/app/auth/auth/auth.component.ts
Normal file
60
src/app/auth/auth/auth.component.ts
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
import { Component, OnInit } from '@angular/core';
|
||||||
|
import { AuthService } from "../auth.service";
|
||||||
|
import { Router } from "@angular/router";
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-auth',
|
||||||
|
templateUrl: './auth.component.html',
|
||||||
|
styleUrls: ['./auth.component.css']
|
||||||
|
})
|
||||||
|
export class AuthComponent implements OnInit {
|
||||||
|
|
||||||
|
public userName: string = '';
|
||||||
|
public password: string = '';
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
private authService: AuthService,
|
||||||
|
private router: Router
|
||||||
|
) {
|
||||||
|
switch (this.router.url) {
|
||||||
|
case '/logout':
|
||||||
|
this.authService.logout();
|
||||||
|
this.authService.authRedirect();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnInit() {
|
||||||
|
if (this.authService.isLoggedIn) {
|
||||||
|
this.router.navigate(['/']);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
get canLogin(): boolean {
|
||||||
|
return [
|
||||||
|
this.userName,
|
||||||
|
this.password,
|
||||||
|
].every(field => field.trim().length > 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public doSubmit() {
|
||||||
|
if (this.canLogin) {
|
||||||
|
this.authService.login(
|
||||||
|
this.userName.trim(),
|
||||||
|
this.password.trim()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
get hasError(): boolean {
|
||||||
|
return this.authService.hasError;
|
||||||
|
}
|
||||||
|
|
||||||
|
get isLoading(): boolean {
|
||||||
|
return this.authService.isLoading;
|
||||||
|
}
|
||||||
|
|
||||||
|
get errorMessage(): string {
|
||||||
|
return this.authService.errorMessage;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -33,7 +33,7 @@
|
|||||||
<mat-paginator #paginator
|
<mat-paginator #paginator
|
||||||
[length]="awardees.length"
|
[length]="awardees.length"
|
||||||
[pageIndex]="0"
|
[pageIndex]="0"
|
||||||
[pageSize]="50"
|
[pageSize]="15"
|
||||||
[pageSizeOptions]="[25, 50, 100, 250]">
|
[pageSizeOptions]="[15, 25, 50]">
|
||||||
</mat-paginator>
|
</mat-paginator>
|
||||||
</div>
|
</div>
|
||||||
@ -6,3 +6,7 @@
|
|||||||
width: 200px;
|
width: 200px;
|
||||||
box-shadow: 3px 0 6px rgba(0,0,0,.24);
|
box-shadow: 3px 0 6px rgba(0,0,0,.24);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.nav-logout {
|
||||||
|
margin-top: 3em;
|
||||||
|
}
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
<mat-sidenav-container class="sidenav-container">
|
<mat-sidenav-container class="sidenav-container">
|
||||||
<mat-sidenav
|
<mat-sidenav *ngIf="loggedIn"
|
||||||
#drawer
|
#drawer
|
||||||
class="sidenav"
|
class="sidenav"
|
||||||
fixedInViewport="true"
|
fixedInViewport="true"
|
||||||
@ -8,12 +8,22 @@
|
|||||||
[opened]="!(isHandset | async)!.matches">
|
[opened]="!(isHandset | async)!.matches">
|
||||||
<mat-toolbar color="primary">Menu</mat-toolbar>
|
<mat-toolbar color="primary">Menu</mat-toolbar>
|
||||||
<mat-nav-list>
|
<mat-nav-list>
|
||||||
<a mat-list-item [routerLink]="['judges']">Judges</a>
|
<a mat-list-item [routerLink]="['judges']">
|
||||||
<a mat-list-item [routerLink]="['awardees']">Awardees</a>
|
<mat-icon fontSet="fas" fontIcon="fa-gavel"></mat-icon>
|
||||||
|
Judges
|
||||||
|
</a>
|
||||||
|
<a mat-list-item [routerLink]="['awardees']">
|
||||||
|
<mat-icon fontSet="fas" fontIcon="fa-trophy"></mat-icon>
|
||||||
|
Awardees
|
||||||
|
</a>
|
||||||
|
<a mat-list-item [routerLink]="['logout']" class="nav-logout">
|
||||||
|
<mat-icon fontSet="fas" fontIcon="fa-sign-out-alt"></mat-icon>
|
||||||
|
Logout
|
||||||
|
</a>
|
||||||
</mat-nav-list>
|
</mat-nav-list>
|
||||||
</mat-sidenav>
|
</mat-sidenav>
|
||||||
<mat-sidenav-content>
|
<mat-sidenav-content>
|
||||||
<mat-toolbar color="primary">
|
<mat-toolbar color="primary" *ngIf="loggedIn">
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
aria-label="Toggle sidenav"
|
aria-label="Toggle sidenav"
|
||||||
|
|||||||
@ -2,6 +2,7 @@ import { Component } from '@angular/core';
|
|||||||
import { BreakpointObserver, Breakpoints, BreakpointState } from '@angular/cdk/layout';
|
import { BreakpointObserver, Breakpoints, BreakpointState } from '@angular/cdk/layout';
|
||||||
import { Observable } from 'rxjs';
|
import { Observable } from 'rxjs';
|
||||||
import { Title } from "@angular/platform-browser";
|
import { Title } from "@angular/platform-browser";
|
||||||
|
import { AuthService } from "../auth/auth.service";
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-navigation',
|
selector: 'app-navigation',
|
||||||
@ -12,9 +13,14 @@ export class NavigationComponent {
|
|||||||
isHandset: Observable<BreakpointState> = this.breakpointObserver.observe(Breakpoints.Handset);
|
isHandset: Observable<BreakpointState> = this.breakpointObserver.observe(Breakpoints.Handset);
|
||||||
constructor(
|
constructor(
|
||||||
private breakpointObserver: BreakpointObserver,
|
private breakpointObserver: BreakpointObserver,
|
||||||
private titleService: Title
|
private titleService: Title,
|
||||||
|
private authService: AuthService,
|
||||||
) {}
|
) {}
|
||||||
get title(): string {
|
get title(): string {
|
||||||
return this.titleService.getTitle();
|
return this.titleService.getTitle();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get loggedIn(): boolean {
|
||||||
|
return this.authService.isLoggedIn;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1 +1,6 @@
|
|||||||
/* You can add global styles to this file, and also import other style files */
|
/* You can add global styles to this file, and also import other style files */
|
||||||
|
html,
|
||||||
|
body {
|
||||||
|
height: 100%;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user