New Http wrapper, updated components, minor API change
The new Http wrapper automatically handles updates to the JWT during server communication and redirects to login on unauthenticated calls.
This commit is contained in:
parent
c2938c9c38
commit
823daf740c
@ -74,7 +74,7 @@ class Auth extends BaseController {
|
||||
return $response->withStatus(401);
|
||||
}
|
||||
|
||||
$jwt = self::createJwt($payload->uid);
|
||||
$jwt = self::createJwt($payload->uid, (int) $payload->mul);
|
||||
$user->active_token = $jwt;
|
||||
$user->save();
|
||||
|
||||
@ -117,7 +117,7 @@ class Auth extends BaseController {
|
||||
return $this->jsonResponse($response, 401);
|
||||
}
|
||||
|
||||
$jwt = self::createJwt($user->id);
|
||||
$jwt = self::createJwt($user->id, ($data->remember ? 200 : 1));
|
||||
$user = new User($this->container, $user->id);
|
||||
|
||||
$user->active_token = $jwt;
|
||||
@ -199,10 +199,12 @@ class Auth extends BaseController {
|
||||
return $payload;
|
||||
}
|
||||
|
||||
private static function createJwt($userId) {
|
||||
private static function createJwt($userId, $mult = 1) {
|
||||
// If 'remember me' feature is desired, set the multiplier higher
|
||||
return JWT::encode(array(
|
||||
'exp' => time() + (60 * 30), // 30 minutes
|
||||
'uid' => $userId
|
||||
'exp' => time() + (60 * 30) * $mult, // 30 minutes * $mult
|
||||
'uid' => $userId,
|
||||
'mul' => $mult
|
||||
), Auth::getJwtKey());
|
||||
}
|
||||
|
||||
|
@ -50,10 +50,7 @@ abstract class BaseController {
|
||||
return 403;
|
||||
}
|
||||
|
||||
$token = new stdClass();
|
||||
$token->jwt = (string) $response->getBody();
|
||||
|
||||
$this->apiJson->addData($token);
|
||||
$this->apiJson->addData((string) $response->getBody());
|
||||
|
||||
return $status;
|
||||
}
|
||||
|
@ -15,8 +15,8 @@ import {
|
||||
})
|
||||
export class Login {
|
||||
version: string;
|
||||
username: string;
|
||||
password: string;
|
||||
username: string = '';
|
||||
password: string = '';
|
||||
remember: boolean;
|
||||
isSubmitted: boolean = false;
|
||||
|
||||
@ -26,6 +26,12 @@ export class Login {
|
||||
}
|
||||
|
||||
login(): void {
|
||||
if (this.username === '' || this.password === '') {
|
||||
this.notes.add(new Notification('error',
|
||||
'Username and password are required.'));
|
||||
return;
|
||||
}
|
||||
|
||||
this.isSubmitted = true;
|
||||
|
||||
this.authService.login(this.username, this.password, this.remember)
|
||||
|
@ -5,7 +5,7 @@ import { enableProdMode } from '@angular/core';
|
||||
|
||||
import { AppComponent } from './app.component';
|
||||
import { APP_ROUTER_PROVIDERS } from './app.routes';
|
||||
import { NotificationsService } from './shared/index';
|
||||
import { NotificationsService, API_HTTP_PROVIDERS } from './shared/index';
|
||||
import { Constants } from './shared/constants';
|
||||
|
||||
// enableProdMode();
|
||||
@ -16,6 +16,7 @@ bootstrap(AppComponent,
|
||||
disableDeprecatedForms(),
|
||||
provideForms(),
|
||||
APP_ROUTER_PROVIDERS,
|
||||
API_HTTP_PROVIDERS,
|
||||
Constants,
|
||||
NotificationsService
|
||||
]
|
||||
|
@ -43,7 +43,6 @@ export class UserSettings {
|
||||
.changePassword(this.changePassword.current,
|
||||
this.changePassword.newPass)
|
||||
.subscribe((response: ApiResponse) => {
|
||||
console.log(response);
|
||||
response.alerts.forEach(msg => {
|
||||
this.notes.add(new Notification(msg.type, msg.text));
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { Http, Response, Headers } from '@angular/http';
|
||||
import { Router } from '@angular/router';
|
||||
|
||||
import { Observable } from 'rxjs/Observable';
|
||||
import 'rxjs/add/observable/of';
|
||||
@ -20,11 +21,10 @@ interface UpdateUser extends User {
|
||||
@Injectable()
|
||||
export class UserSettingsService {
|
||||
activeUser: User = null;
|
||||
jwtKey: string;
|
||||
|
||||
constructor(auth: AuthService, constants: Constants, private http: Http) {
|
||||
constructor(auth: AuthService, constants: Constants,
|
||||
private http: Http, private router: Router) {
|
||||
this.activeUser = auth.activeUser;
|
||||
this.jwtKey = constants.TOKEN;
|
||||
}
|
||||
|
||||
changePassword(oldPass: string, newPass: string): Observable<ApiResponse> {
|
||||
@ -33,30 +33,16 @@ export class UserSettingsService {
|
||||
updateUser.old_password = oldPass;
|
||||
|
||||
let json = JSON.stringify(updateUser);
|
||||
let headers = this.getHeaders();
|
||||
|
||||
return this.http.post('api/users/' + this.activeUser.id, json,
|
||||
{ headers: headers })
|
||||
return this.http.post('api/users/' + this.activeUser.id, json)
|
||||
.map(res => {
|
||||
let response: ApiResponse = res.json();
|
||||
|
||||
return response;
|
||||
})
|
||||
.catch((res, caught) => {
|
||||
let response: ApiResponse = res.json();
|
||||
|
||||
return Observable.of(response);
|
||||
});
|
||||
}
|
||||
|
||||
private getHeaders(): Headers {
|
||||
let token = localStorage.getItem(this.jwtKey);
|
||||
let headers = new Headers();
|
||||
|
||||
headers.append('Content-Type', 'application/json');
|
||||
headers.append('Authorization', token);
|
||||
|
||||
return headers;
|
||||
}
|
||||
}
|
||||
|
||||
|
102
src/app/shared/auth-http.provider.ts
Normal file
102
src/app/shared/auth-http.provider.ts
Normal file
@ -0,0 +1,102 @@
|
||||
import { provide } from '@angular/core';
|
||||
import {
|
||||
Http,
|
||||
Request,
|
||||
RequestOptionsArgs,
|
||||
Response,
|
||||
XHRBackend,
|
||||
RequestOptions,
|
||||
ConnectionBackend,
|
||||
Headers
|
||||
} from '@angular/http';
|
||||
import { Router } from '@angular/router';
|
||||
|
||||
import { Observable } from 'rxjs/Observable';
|
||||
import 'rxjs/add/observable/throw';
|
||||
|
||||
import { ApiResponse } from './index';
|
||||
|
||||
export const API_HTTP_PROVIDERS = [
|
||||
provide(Http, {
|
||||
useFactory: (xhrBackend: XHRBackend, requestOptions: RequestOptions,
|
||||
router: Router) => new ApiHttp(xhrBackend, requestOptions, router),
|
||||
deps: [XHRBackend, RequestOptions, Router]
|
||||
})
|
||||
];
|
||||
|
||||
export class ApiHttp extends Http {
|
||||
private JWT_KEY = 'taskboard.jwt';
|
||||
|
||||
constructor(backend: ConnectionBackend,
|
||||
defaultOptions: RequestOptions,
|
||||
private router: Router) {
|
||||
super(backend, defaultOptions);
|
||||
}
|
||||
|
||||
request(url: string | Request,
|
||||
options?: RequestOptionsArgs): Observable<Response> {
|
||||
return this.intercept(super.request(url, options));
|
||||
}
|
||||
|
||||
get(url: string, options?: RequestOptionsArgs): Observable<Response> {
|
||||
return this.intercept(super.get(url, options));
|
||||
}
|
||||
|
||||
post(url: string, body: string,
|
||||
options?: RequestOptionsArgs): Observable<Response> {
|
||||
return this.intercept(super.post(url, body,
|
||||
this.getRequestOptionArgs(options)));
|
||||
}
|
||||
|
||||
put(url: string, body: string,
|
||||
options?: RequestOptionsArgs): Observable<Response> {
|
||||
return this.intercept(super.put(url, body,
|
||||
this.getRequestOptionArgs(options)));
|
||||
}
|
||||
|
||||
delete(url: string, options?: RequestOptionsArgs): Observable<Response> {
|
||||
return this.intercept(super.delete(url, options));
|
||||
}
|
||||
|
||||
getRequestOptionArgs(options?: RequestOptionsArgs) : RequestOptionsArgs {
|
||||
if (options == null) {
|
||||
options = new RequestOptions();
|
||||
}
|
||||
|
||||
if (options.headers == null) {
|
||||
options.headers = new Headers();
|
||||
}
|
||||
|
||||
options.headers.append('Content-Type', 'application/json');
|
||||
|
||||
let jwt = localStorage.getItem(this.JWT_KEY);
|
||||
if (jwt) {
|
||||
options.headers.append('Authorization', jwt);
|
||||
}
|
||||
|
||||
return options;
|
||||
}
|
||||
|
||||
intercept(observable: Observable<Response>): Observable<Response> {
|
||||
return observable
|
||||
.map((res: Response) => {
|
||||
let response: ApiResponse = res.json();
|
||||
console.log(response);
|
||||
|
||||
localStorage.setItem(this.JWT_KEY, response.data[0]);
|
||||
|
||||
return res;
|
||||
})
|
||||
.catch((err, source) => {
|
||||
console.log(err);
|
||||
|
||||
if (err.status === 401 && err.url.indexOf('login') === -1) {
|
||||
this.router.navigate(['']);
|
||||
localStorage.removeItem(this.JWT_KEY);
|
||||
}
|
||||
|
||||
return Observable.throw(err);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { Http, Response, Headers } from '@angular/http';
|
||||
import { Http, Response } from '@angular/http';
|
||||
import { Router } from '@angular/router';
|
||||
|
||||
import { Observable } from 'rxjs/Observable';
|
||||
@ -12,92 +12,54 @@ import { Constants } from '../constants';
|
||||
@Injectable()
|
||||
export class AuthService {
|
||||
activeUser: User = null;
|
||||
jwtKey: string;
|
||||
|
||||
constructor(constants: Constants, private http: Http,
|
||||
private router: Router) {
|
||||
this.jwtKey = constants.TOKEN;
|
||||
}
|
||||
|
||||
authenticate(): Observable<boolean> {
|
||||
let headers = this.getHeaders();
|
||||
|
||||
return this.http.post('api/authenticate', null, { headers: headers })
|
||||
return this.http.post('api/authenticate', null)
|
||||
.map(res => {
|
||||
this.checkStatus(res);
|
||||
let response: ApiResponse = res.json();
|
||||
this.activeUser = response.data[1];
|
||||
|
||||
return this.activeUser !== null;
|
||||
})
|
||||
.catch((res, caught) => {
|
||||
this.checkStatus(res);
|
||||
|
||||
return Observable.of(false);
|
||||
});
|
||||
}
|
||||
|
||||
login(username: string, password: string,
|
||||
remember: boolean): Observable<ApiResponse> {
|
||||
// TODO Add remember flag to API
|
||||
let json = JSON.stringify({
|
||||
username: username,
|
||||
password: password
|
||||
password: password,
|
||||
remember: remember
|
||||
});
|
||||
|
||||
return this.http.post('api/login', json)
|
||||
.map(res => {
|
||||
let response: ApiResponse = res.json();
|
||||
this.checkStatus(res);
|
||||
this.activeUser = response.data[1];
|
||||
|
||||
return response;
|
||||
})
|
||||
.catch((res, caught) => {
|
||||
let response: ApiResponse = res.json();
|
||||
this.checkStatus(res);
|
||||
this.activeUser = null;
|
||||
|
||||
return Observable.of(response);
|
||||
});
|
||||
}
|
||||
|
||||
logout(): Observable<ApiResponse> {
|
||||
let headers = this.getHeaders();
|
||||
|
||||
this.clearData();
|
||||
|
||||
return this.http.post('api/logout', null, { headers: headers })
|
||||
return this.http.post('api/logout', null)
|
||||
.map(res => {
|
||||
let response: ApiResponse = res.json();
|
||||
|
||||
return response;
|
||||
});
|
||||
}
|
||||
|
||||
private clearData(): void {
|
||||
this.activeUser = null;
|
||||
localStorage.removeItem(this.jwtKey);
|
||||
|
||||
this.router.navigate(['']);
|
||||
}
|
||||
|
||||
private checkStatus(response: Response): void {
|
||||
if (response.status === 200) {
|
||||
let apiResponse: ApiResponse = response.json();
|
||||
|
||||
this.activeUser = apiResponse.data[1];
|
||||
localStorage.setItem(this.jwtKey, apiResponse.data[0])
|
||||
}
|
||||
|
||||
if (response.status === 401) {
|
||||
this.clearData();
|
||||
}
|
||||
}
|
||||
|
||||
private getHeaders(): Headers {
|
||||
let token = localStorage.getItem(this.jwtKey);
|
||||
let headers = new Headers();
|
||||
|
||||
headers.append('Content-Type', 'application/json');
|
||||
headers.append('Authorization', token);
|
||||
|
||||
return headers;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3,4 +3,5 @@ export * from './auth/index';
|
||||
export * from './models/index';
|
||||
export * from './notifications/index';
|
||||
export * from './constants';
|
||||
export * from './auth-http.provider';
|
||||
|
||||
|
Reference in New Issue
Block a user