Commit ae2b0af7 authored by Thodoris Nestoridis's avatar Thodoris Nestoridis

Crud actions with Angular for Boilerplates (simple ui)

parent af011462
This source diff could not be displayed because it is too large. You can view the blob instead.
This diff is collapsed.
from django.urls import path from django.urls import path
from django.conf.urls import url
from .views import user_views, requirements_views, main_req_views, suffix_req_views from .views import user_views, requirements_views, main_req_views, suffix_req_views
......
...@@ -13,6 +13,7 @@ https://docs.djangoproject.com/en/{{ docs_version }}/ref/settings/ ...@@ -13,6 +13,7 @@ https://docs.djangoproject.com/en/{{ docs_version }}/ref/settings/
import os import os
from .environment import env from .environment import env
from datetime import timedelta
# Build paths inside the project like this: os.path.join(BASE_DIR, ...) # Build paths inside the project like this: os.path.join(BASE_DIR, ...)
...@@ -45,6 +46,7 @@ INSTALLED_APPS = [ ...@@ -45,6 +46,7 @@ INSTALLED_APPS = [
"django.contrib.staticfiles", "django.contrib.staticfiles",
# 3rd party apps # 3rd party apps
"rest_framework", "rest_framework",
'corsheaders',
# our apps # our apps
"reqman.apps.common.apps.CommonConfig", "reqman.apps.common.apps.CommonConfig",
"reqman.apps.account.apps.AccountConfig", "reqman.apps.account.apps.AccountConfig",
...@@ -52,6 +54,7 @@ INSTALLED_APPS = [ ...@@ -52,6 +54,7 @@ INSTALLED_APPS = [
] + env.list("REQMAN_DEV_INSTALLED_APPS", default=[]) ] + env.list("REQMAN_DEV_INSTALLED_APPS", default=[])
MIDDLEWARE = [ MIDDLEWARE = [
'corsheaders.middleware.CorsMiddleware',
"django.middleware.security.SecurityMiddleware", "django.middleware.security.SecurityMiddleware",
"django.contrib.sessions.middleware.SessionMiddleware", "django.contrib.sessions.middleware.SessionMiddleware",
"django.middleware.common.CommonMiddleware", "django.middleware.common.CommonMiddleware",
...@@ -59,6 +62,7 @@ MIDDLEWARE = [ ...@@ -59,6 +62,7 @@ MIDDLEWARE = [
"django.contrib.auth.middleware.AuthenticationMiddleware", "django.contrib.auth.middleware.AuthenticationMiddleware",
"django.contrib.messages.middleware.MessageMiddleware", "django.contrib.messages.middleware.MessageMiddleware",
"django.middleware.clickjacking.XFrameOptionsMiddleware", "django.middleware.clickjacking.XFrameOptionsMiddleware",
'django.middleware.common.CommonMiddleware',
] + env.list("REQMAN_DEV_MIDDLEWARE", default=[]) ] + env.list("REQMAN_DEV_MIDDLEWARE", default=[])
ROOT_URLCONF = "reqman.urls" ROOT_URLCONF = "reqman.urls"
...@@ -130,6 +134,31 @@ MEDIA_URL = "/media/" ...@@ -130,6 +134,31 @@ MEDIA_URL = "/media/"
MEDIA_ROOT = rel("media/") MEDIA_ROOT = rel("media/")
REST_FRAMEWORK = { REST_FRAMEWORK = {
'DEFAULT_VERSIONING_CLASS': 'rest_framework.versioning.URLPathVersioning' 'DEFAULT_PERMISSION_CLASSES': (
'rest_framework.permissions.IsAuthenticated',
),
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework_jwt.authentication.JSONWebTokenAuthentication',
#'rest_framework.authentication.SessionAuthentication',
#'rest_framework.authentication.BasicAuthentication',
),
'NON_FIELD_ERRORS_KEY': 'global',
} }
# JWT settings
JWT_AUTH = {
'JWT_ALLOW_REFRESH': True,
'JWT_EXPIRATION_DELTA': timedelta(days=2),
}
CORS_ORIGIN_ALLOW_ALL = True # If this is used then `CORS_ORIGIN_WHITELIST` will not have any effect
CORS_ALLOW_CREDENTIALS = True
CORS_ORIGIN_WHITELIST = [
'http://155.207.131.19:8081',
] # If this is used, then not need to use `CORS_ORIGIN_ALLOW_ALL = True`
#CORS_ORIGIN_REGEX_WHITELIST = [
# 'http://155.207.131.19:8081',
#]
...@@ -16,11 +16,14 @@ Including another URLconf ...@@ -16,11 +16,14 @@ Including another URLconf
from django.contrib import admin from django.contrib import admin
from django.conf import settings from django.conf import settings
from django.urls import path, include, re_path from django.urls import path, include, re_path
from rest_framework_jwt.views import obtain_jwt_token, refresh_jwt_token
urlpatterns = [ urlpatterns = [
path("admin/", admin.site.urls), path("admin/", admin.site.urls),
path('api-auth/', include('reqman.apps.reqtool.rest_api.urls')), path('api-auth/', include('reqman.apps.reqtool.rest_api.urls')),
path('auth/login/', obtain_jwt_token),
path('auth/refresh-token/', refresh_jwt_token),
#re_path(r'api/(?P<version>[v1|v2]+)/', include('reqman.apps.reqtool.rest_api.urls')), #re_path(r'api/(?P<version>[v1|v2]+)/', include('reqman.apps.reqtool.rest_api.urls')),
#path('api/', include('reqman.apps.reqtool.rest_api.urls')) #path('api/', include('reqman.apps.reqtool.rest_api.urls'))
] ]
......
...@@ -66,7 +66,7 @@ pillow==6.1.0 ...@@ -66,7 +66,7 @@ pillow==6.1.0
rdflib==5.0.0 rdflib==5.0.0
sparqlwrapper==1.8.5 sparqlwrapper==1.8.5
django-jsonfield==1.4.1 django-jsonfield==1.4.1
djangorestframework-jwt==1.5.2
# The following packages are considered to be unsafe in a requirements file: # The following packages are considered to be unsafe in a requirements file:
# setuptools==41.2.0 # via ipdb, ipython # setuptools==41.2.0 # via ipdb, ipython
...@@ -1675,6 +1675,14 @@ ...@@ -1675,6 +1675,14 @@
"integrity": "sha512-cxWFQVseBm6O9Gbw1IWb8r6OS4OhSt3hPZLkFApLjM8TEXROBuQGLAH2i2gZpcXdLBIrpXuTDhH7Vbm1iXmNGA==", "integrity": "sha512-cxWFQVseBm6O9Gbw1IWb8r6OS4OhSt3hPZLkFApLjM8TEXROBuQGLAH2i2gZpcXdLBIrpXuTDhH7Vbm1iXmNGA==",
"dev": true "dev": true
}, },
"@types/jwt-decode": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/@types/jwt-decode/-/jwt-decode-3.1.0.tgz",
"integrity": "sha512-tthwik7TKkou3mVnBnvVuHnHElbjtdbM63pdBCbZTirCt3WAdM73Y79mOri7+ljsS99ZVwUFZHLMxJuJnv/z1w==",
"requires": {
"jwt-decode": "*"
}
},
"@types/minimatch": { "@types/minimatch": {
"version": "3.0.3", "version": "3.0.3",
"resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.3.tgz", "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.3.tgz",
...@@ -7160,6 +7168,11 @@ ...@@ -7160,6 +7168,11 @@
} }
} }
}, },
"jwt-decode": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/jwt-decode/-/jwt-decode-3.1.2.tgz",
"integrity": "sha512-UfpWE/VZn0iP50d8cz9NrZLM9lSWhcJ+0Gt/nm4by88UL+J1SiKN8/5dkjMmbEzwL2CAe+67GsegCbIKtbp75A=="
},
"karma": { "karma": {
"version": "5.2.3", "version": "5.2.3",
"resolved": "https://registry.npmjs.org/karma/-/karma-5.2.3.tgz", "resolved": "https://registry.npmjs.org/karma/-/karma-5.2.3.tgz",
...@@ -8024,6 +8037,11 @@ ...@@ -8024,6 +8037,11 @@
"integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==",
"dev": true "dev": true
}, },
"moment": {
"version": "2.29.1",
"resolved": "https://registry.npmjs.org/moment/-/moment-2.29.1.tgz",
"integrity": "sha512-kHmoybcPV8Sqy59DwNDY3Jefr64lK/by/da0ViFcuA4DH0vQg5Q6Ze5VimxkfQNSC+Mls/Kx53s7TjP1RhFEDQ=="
},
"move-concurrently": { "move-concurrently": {
"version": "1.0.1", "version": "1.0.1",
"resolved": "https://registry.npmjs.org/move-concurrently/-/move-concurrently-1.0.1.tgz", "resolved": "https://registry.npmjs.org/move-concurrently/-/move-concurrently-1.0.1.tgz",
......
...@@ -19,6 +19,9 @@ ...@@ -19,6 +19,9 @@
"@angular/platform-browser": "~11.1.2", "@angular/platform-browser": "~11.1.2",
"@angular/platform-browser-dynamic": "~11.1.2", "@angular/platform-browser-dynamic": "~11.1.2",
"@angular/router": "~11.1.2", "@angular/router": "~11.1.2",
"@types/jwt-decode": "^3.1.0",
"jwt-decode": "^3.1.2",
"moment": "^2.29.1",
"rxjs": "~6.6.0", "rxjs": "~6.6.0",
"tslib": "^2.0.0", "tslib": "^2.0.0",
"zone.js": "~0.11.3" "zone.js": "~0.11.3"
......
import { NgModule } from '@angular/core'; import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router'; import { RouterModule, Routes } from '@angular/router';
import { AuthGuard } from './services/auth.service';
import { LoginComponent } from './components/login/login.component';
import { SignupComponent } from './components/signup/signup.component';
import { BoilerplateListComponent } from './components/boilerplate-list/boilerplate-list.component'; import { BoilerplateListComponent } from './components/boilerplate-list/boilerplate-list.component';
import { BoilerplateDetailsComponent } from './components/boilerplate-details/boilerplate-details.component'; import { BoilerplateDetailsComponent } from './components/boilerplate-details/boilerplate-details.component';
import { AddBoilerplateComponent } from './components/add-boilerplate/add-boilerplate.component'; import { AddBoilerplateComponent } from './components/add-boilerplate/add-boilerplate.component';
...@@ -10,10 +15,12 @@ import { PrefixDetailsComponent } from './components/prefix-details/prefix-detai ...@@ -10,10 +15,12 @@ import { PrefixDetailsComponent } from './components/prefix-details/prefix-detai
import { AddPrefixComponent } from './components/add-prefix/add-prefix.component';*/ import { AddPrefixComponent } from './components/add-prefix/add-prefix.component';*/
const routes: Routes = [ const routes: Routes = [
{ path: '', redirectTo: 'boilerplates', pathMatch: 'full' }, { path: '', redirectTo: 'login', pathMatch: 'full' },
{ path: 'boilerplates', component: BoilerplateListComponent }, { path: 'login', component: LoginComponent },
{ path: 'boilerplates/:id', component: BoilerplateDetailsComponent }, { path: 'signup', component: SignupComponent },
{ path: 'add-boilerplate', component: AddBoilerplateComponent } { path: 'boilerplates', component: BoilerplateListComponent, canActivate: [AuthGuard] },
{ path: 'boilerplates/:id', component: BoilerplateDetailsComponent, canActivate: [AuthGuard] },
{ path: 'add-boilerplate', component: AddBoilerplateComponent, canActivate: [AuthGuard] }
/*{ path: '', redirectTo: 'tutorials', pathMatch: 'full' }, /*{ path: '', redirectTo: 'tutorials', pathMatch: 'full' },
{ path: 'prefix', component: PrefixListComponent }, { path: 'prefix', component: PrefixListComponent },
{ path: 'prefix/:id', component: PrefixDetailsComponent }, { path: 'prefix/:id', component: PrefixDetailsComponent },
......
...@@ -5,8 +5,11 @@ import { AppRoutingModule } from './app-routing.module'; ...@@ -5,8 +5,11 @@ import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component'; import { AppComponent } from './app.component';
import { FormsModule } from '@angular/forms'; import { FormsModule } from '@angular/forms';
import { HttpClientModule } from '@angular/common/http'; import { HttpClientModule, HTTP_INTERCEPTORS } from '@angular/common/http';
import { AuthService, AuthInterceptor, AuthGuard } from './services/auth.service';
import { LoginComponent } from './components/login/login.component';
import { SignupComponent } from './components/signup/signup.component';
import { AddBoilerplateComponent } from './components/add-boilerplate/add-boilerplate.component'; import { AddBoilerplateComponent } from './components/add-boilerplate/add-boilerplate.component';
import { BoilerplateDetailsComponent } from './components/boilerplate-details/boilerplate-details.component'; import { BoilerplateDetailsComponent } from './components/boilerplate-details/boilerplate-details.component';
import { BoilerplateListComponent } from './components/boilerplate-list/boilerplate-list.component'; import { BoilerplateListComponent } from './components/boilerplate-list/boilerplate-list.component';
...@@ -15,12 +18,15 @@ import { PrefixDetailsComponent } from './components/prefix-details/prefix-detai ...@@ -15,12 +18,15 @@ import { PrefixDetailsComponent } from './components/prefix-details/prefix-detai
import { PrefixListComponent } from './components/prefix-list/prefix-list.component'; import { PrefixListComponent } from './components/prefix-list/prefix-list.component';
@NgModule({ @NgModule({
declarations: [ declarations: [
AppComponent,
LoginComponent,
SignupComponent,
AddBoilerplateComponent, AddBoilerplateComponent,
BoilerplateDetailsComponent, BoilerplateDetailsComponent,
BoilerplateListComponent, BoilerplateListComponent,
AppComponent,
AddPrefixComponent, AddPrefixComponent,
PrefixDetailsComponent, PrefixDetailsComponent,
PrefixListComponent PrefixListComponent
...@@ -31,7 +37,15 @@ import { PrefixListComponent } from './components/prefix-list/prefix-list.compon ...@@ -31,7 +37,15 @@ import { PrefixListComponent } from './components/prefix-list/prefix-list.compon
FormsModule, FormsModule,
HttpClientModule HttpClientModule
], ],
providers: [], providers: [
AuthService,
AuthGuard,
{
provide: HTTP_INTERCEPTORS,
useClass: AuthInterceptor,
multi: true,
},
],
bootstrap: [AppComponent] bootstrap: [AppComponent]
}) })
export class AppModule { } export class AppModule { }
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
<div class="form-group"> <div class="form-group">
<label for="has_main">Main</label> <label for="has_main">Main</label>
<input <input
type="checkbox"
class="form-control" class="form-control"
id="has_main" id="has_main"
required required
...@@ -27,6 +28,7 @@ ...@@ -27,6 +28,7 @@
<div class="form-group"> <div class="form-group">
<label for="has_suffix">Suffix</label> <label for="has_suffix">Suffix</label>
<input <input
type="checkbox"
class="form-control" class="form-control"
id="has_suffix" id="has_suffix"
required required
......
<p>boilerplate-details works!</p> <div>
<div *ngIf="currentboilerplate.id" class="edit-form">
<h4>Boilerplate</h4>
<form>
<div class="form-group">
<label for="has_prefix">Prefix</label>
<input
type="checkbox"
class="form-control"
id="has_prefix"
[(ngModel)]="currentboilerplate.has_prefix"
name="has_prefix"
/>
</div>
<div class="form-group">
<label for="has_main">Main</label>
<input
type="checkbox"
class="form-control"
id="has_main"
[(ngModel)]="currentboilerplate.has_main"
name="has_main"
/>
</div>
<div class="form-group">
<label for="has_suffix">Suffix</label>
<input
type="checkbox"
class="form-control"
id="has_suffix"
[(ngModel)]="currentboilerplate.has_main"
name="has_suffix"
/>
</div>
</form>
<button class="badge badge-danger mr-2" (click)="deleteBoilerplate()">
Delete
</button>
<button
type="submit"
class="badge badge-success mb-2"
(click)="updateBoilerplate()"
>
Update
</button>
<p>{{ message }}</p>
</div>
<div *ngIf="!currentboilerplate.id">
<br />
<p>Cannot access this Boilerplate...</p>
</div>
</div>
\ No newline at end of file
import { Component, OnInit } from '@angular/core'; import { Component, OnInit } from '@angular/core';
import { ActivatedRoute, Router } from '@angular/router';
import { Boilerplate } from 'src/app/models/boilerplate.model';
import { BoilerplateService } from 'src/app/services/boilerplate.service';
@Component({ @Component({
selector: 'app-boilerplate-details', selector: 'app-boilerplate-details',
...@@ -7,9 +10,57 @@ import { Component, OnInit } from '@angular/core'; ...@@ -7,9 +10,57 @@ import { Component, OnInit } from '@angular/core';
}) })
export class BoilerplateDetailsComponent implements OnInit { export class BoilerplateDetailsComponent implements OnInit {
constructor() { } currentboilerplate: Boilerplate = {
has_prefix: false,
has_main: false,
has_suffix: false
};
message = '';
constructor(
private boilerplateService: BoilerplateService,
private route: ActivatedRoute,
private router: Router) { }
ngOnInit(): void { ngOnInit(): void {
this.message = '';
this.getBoilerplate(this.route.snapshot.params.id);
}
getBoilerplate(id: string): void {
this.boilerplateService.get(id)
.subscribe(
data => {
this.currentboilerplate = data;
console.log(data);
},
error => {
console.log(error);
});
}
updateBoilerplate(): void {
this.boilerplateService.update(this.currentboilerplate.id, this.currentboilerplate)
.subscribe(
response => {
console.log(response);
this.message = response.message;
},
error => {
console.log(error);
});
}
deleteBoilerplate(): void {
this.boilerplateService.delete(this.currentboilerplate.id)
.subscribe(
response => {
console.log(response);
this.router.navigate(['/boilerplates']);
},
error => {
console.log(error);
});
} }
} }
.list {
text-align: left;
max-width: 750px;
margin: auto;
}
\ No newline at end of file
<p>boilerplate-list works!</p> <div class="list row">
<div class="col-md-8">
<div class="input-group mb-3">
<input
type="text"
class="form-control"
placeholder="Search mechanism not working"
[(ngModel)]="boilerplates"
/>
<div class="input-group-append">
<!-- <button
class="btn btn-outline-secondary"
type="button"
(click)=""
>
Search
</button> -->
</div>
</div>
</div>
<div class="col-md-6">
<h4>Boilerplate List</h4>
<ul class="list-group">
<li
class="list-group-item"
*ngFor="let boilerplate of boilerplates; let i = index"
[class.active]="i == currentIndex"
(click)="setActiveBoilerplate(boilerplate, i)"
>
</li>
</ul>
</div>
<div class="col-md-6">
<div *ngIf="currentBoilerplate">
<h4>Boilerplate</h4>
<div>
<label><strong>Prefix:</strong></label>
{{ currentBoilerplate.has_prefix }}
</div>
<div>
<label><strong>Main:</strong></label>
{{ currentBoilerplate.has_main }}
</div>
<div>
<label><strong>Suffix:</strong></label>
{{ currentBoilerplate.has_suffix }}
</div>
<a class="badge badge-warning" routerLink="/boilerplates/{{ currentBoilerplate.id }}">
Edit
</a>
</div>
<div *ngIf="!currentBoilerplate">
<br />
<p>Please click on a Boilerplate...</p>
</div>
</div>
</div>
\ No newline at end of file
import { Component, OnInit } from '@angular/core'; import { Component, OnInit } from '@angular/core';
import { Boilerplate } from 'src/app/models/boilerplate.model';
import { BoilerplateService } from 'src/app/services/boilerplate.service';
@Component({ @Component({
selector: 'app-boilerplate-list', selector: 'app-boilerplate-list',
...@@ -7,9 +9,38 @@ import { Component, OnInit } from '@angular/core'; ...@@ -7,9 +9,38 @@ import { Component, OnInit } from '@angular/core';
}) })
export class BoilerplateListComponent implements OnInit { export class BoilerplateListComponent implements OnInit {
constructor() { } boilerplates?: Boilerplate[];
currentBoilerplate?: Boilerplate;
currentIndex = -1;
//title = '';
constructor(private boilerplateService: BoilerplateService) { }
ngOnInit(): void { ngOnInit(): void {
this.retrieveBoilerplates();
}
retrieveBoilerplates(): void {
this.boilerplateService.getAll()
.subscribe(
data => {
this.boilerplates = data;
console.log(data);
},
error => {
console.log(error);
});
}
refreshList(): void {
this.retrieveBoilerplates();
this.currentBoilerplate = undefined;
this.currentIndex = -1;
}
setActiveBoilerplate(boilerplate: Boilerplate, index: number): void {
this.currentBoilerplate = boilerplate;
this.currentIndex = index;
} }
} }
<div style="text-align:center">
<h1>
Login
</h1>
</div>
<input #username type='text' placeholder='username'>
<input #password type='password' placeholder='password'>
<button (click)="login(username.value, password.value)">login</button>
<p>{{ error?.message }}</p>
<p *ngIf="error">{{ error?.error | json }}</p>
\ No newline at end of file
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { LoginComponent } from './login.component';
describe('LoginComponent', () => {
let component: LoginComponent;
let fixture: ComponentFixture<LoginComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ LoginComponent ]
})
.compileComponents();
});
beforeEach(() => {
fixture = TestBed.createComponent(LoginComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
import { Component, OnInit } from '@angular/core';
import { Router } from '@angular/router';
import { AuthService } from './../../services/auth.service';
@Component({
selector: 'app-login',
templateUrl: './login.component.html',
styleUrls: ['./login.component.css']
})
export class LoginComponent implements OnInit {
error: any;
constructor(
private authService: AuthService,
private router: Router,
) { }
ngOnInit() {
}
login(email: string, password: string) {
this.authService.login(email, password).subscribe(
success => this.router.navigate(['boilerplates']),
error => this.error = error
);
}
}
<div style="text-align:center">
<h1>
Signup
</h1>
</div>
<input #username type='text' placeholder='username'>
<input #email type='text' placeholder='email'>
<input #password1 type='password' placeholder='password1'>
<input #password2 type='password' placeholder='password2'>
<button (click)="signup(username.value, email.value, password1.value, password2.value)">signup</button>
<p>{{ error?.message }}</p>
<p *ngIf="error">{{ error?.error | json }}</p>
\ No newline at end of file
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { SignupComponent } from './signup.component';
describe('SignupComponent', () => {
let component: SignupComponent;
let fixture: ComponentFixture<SignupComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ SignupComponent ]
})
.compileComponents();
});
beforeEach(() => {
fixture = TestBed.createComponent(SignupComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
import { Component, OnInit } from '@angular/core';
@Component({
selector: 'app-signup',
templateUrl: './signup.component.html',
styleUrls: ['./signup.component.css']
})
export class SignupComponent implements OnInit {
error: any;
constructor() { }
ngOnInit() {
}
signup(username: string, email: string, password1: string, password2: string) {
// TODO: call signup
}
}
import { TestBed } from '@angular/core/testing';
import { AuthService } from './auth.service';
describe('AuthService', () => {
let service: AuthService;
beforeEach(() => {
TestBed.configureTestingModule({});
service = TestBed.inject(AuthService);
});
it('should be created', () => {
expect(service).toBeTruthy();
});
});
import { Injectable } from '@angular/core';
import { HttpClient, HttpInterceptor, HttpRequest, HttpHandler, HttpEvent } from '@angular/common/http';
import { CanActivate, Router } from '@angular/router';
import { Observable } from 'rxjs';
import { tap, shareReplay } from 'rxjs/operators';
import jwtDecode from 'jwt-decode';
import * as moment from 'moment';
import { environment } from '../../environments/environment';
@Injectable({
providedIn: 'root'
})
export class AuthService {
private apiRoot = 'http://155.207.131.19:8000/auth/';
constructor(private http: HttpClient) { }
private setSession(authResult: any) {
const token = authResult.token;
const payload = <JWTPayload> jwtDecode(token);
const expiresAt = moment.unix(payload.exp);
localStorage.setItem('token', authResult.token);
localStorage.setItem('expires_at', JSON.stringify(expiresAt.valueOf()));
}
get token(): string {
return JSON.parse(localStorage.getItem('currentUser') || '{}');
}
login(email: string, password: string) {
return this.http.post(
this.apiRoot.concat('login/'),
{ email, password }
).pipe(
tap(response => this.setSession(response)),
shareReplay(),
);
}
signup(username: string, email: string, password1: string, password2: string) {
// TODO: implement signup
}
logout() {
localStorage.removeItem('token');
localStorage.removeItem('expires_at');
}
refreshToken() {
if (moment().isBetween(this.getExpiration().subtract(1, 'days'), this.getExpiration())) {
return this.http.post(
this.apiRoot.concat('refresh-token/'),
{ token: this.token }
).pipe(
tap(response => this.setSession(response)),
shareReplay(),
).subscribe();
}
return
}
getExpiration() {
const expiration = JSON.parse(localStorage.getItem('expires_at') || '{}');
const expiresAt = JSON.parse(expiration);
return moment(expiresAt);
}
isLoggedIn() {
return moment().isBefore(this.getExpiration());
}
isLoggedOut() {
return !this.isLoggedIn();
}
}
@Injectable()
export class AuthInterceptor implements HttpInterceptor {
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
const token = localStorage.getItem('token');
if (token) {
const cloned = req.clone({
headers: req.headers.set('Authorization', 'JWT '.concat(token))
});
return next.handle(cloned);
} else {
return next.handle(req);
}
}
}
@Injectable()
export class AuthGuard implements CanActivate {
constructor(private authService: AuthService, private router: Router) { }
canActivate() {
if (this.authService.isLoggedIn()) {
this.authService.refreshToken();
return true;
} else {
this.authService.logout();
this.router.navigate(['login']);
return false;
}
}
}
interface JWTPayload {
user_id: number;
username: string;
email: string;
exp: number;
}
\ No newline at end of file
...@@ -3,7 +3,7 @@ import { HttpClient } from '@angular/common/http'; ...@@ -3,7 +3,7 @@ import { HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs'; import { Observable } from 'rxjs';
import { Boilerplate } from '../models/boilerplate.model'; import { Boilerplate } from '../models/boilerplate.model';
const baseUrl = 'http://localhost:8080/api-auth/boilerplates'; const baseUrl = 'http://155.207.131.19:8000/api-auth/boilerplates/';
@Injectable({ @Injectable({
providedIn: 'root' providedIn: 'root'
...@@ -17,7 +17,7 @@ export class BoilerplateService { ...@@ -17,7 +17,7 @@ export class BoilerplateService {
} }
get(id: any): Observable<Boilerplate> { get(id: any): Observable<Boilerplate> {
return this.http.get(`${baseUrl}/${id}`); return this.http.get(`${baseUrl}${id}`);
} }
create(data: any): Observable<any> { create(data: any): Observable<any> {
...@@ -25,11 +25,11 @@ export class BoilerplateService { ...@@ -25,11 +25,11 @@ export class BoilerplateService {
} }
update(id: any, data: any): Observable<any> { update(id: any, data: any): Observable<any> {
return this.http.put(`${baseUrl}/${id}`, data); return this.http.put(`${baseUrl}${id}/`, data);
} }
delete(id: any): Observable<any> { delete(id: any): Observable<any> {
return this.http.delete(`${baseUrl}/${id}`); return this.http.delete(`${baseUrl}${id}`);
} }
//In case we want to find by something //In case we want to find by something
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment