Add user storage and db-based login
parent
b880e2d062
commit
f1f03c9b69
|
@ -29,17 +29,29 @@
|
||||||
"assignee": {},
|
"assignee": {},
|
||||||
"id": 5,
|
"id": 5,
|
||||||
"state": "IN_PROGRESS"
|
"state": "IN_PROGRESS"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"users": [
|
||||||
|
{
|
||||||
|
"id": 301,
|
||||||
|
"name": "admin",
|
||||||
|
"password": "admin",
|
||||||
|
"edit_tasks": true,
|
||||||
|
"change_settings": true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"assignee": {
|
"id" : 302,
|
||||||
"name": "hardi",
|
"name": "user_edit",
|
||||||
"email": "hardi@noarch.de"
|
"password": "secret",
|
||||||
},
|
"edit_tasks": true,
|
||||||
"tags": [],
|
"change_settings": false
|
||||||
"state": "IN_PROGRESS",
|
},
|
||||||
"title": "Testplan schreiben",
|
{
|
||||||
"description": "Testplan für dieses Projekt anlegen",
|
"id" : 303,
|
||||||
"id": 6
|
"name": "user",
|
||||||
|
"password": "secret",
|
||||||
|
"edit_tasks": false,
|
||||||
|
"change_settings": false
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
|
@ -65,7 +65,7 @@ if (secured) {
|
||||||
var password = req.body.password;
|
var password = req.body.password;
|
||||||
var user = {
|
var user = {
|
||||||
name: req.body.name,
|
name: req.body.name,
|
||||||
passowrd: req.body.password
|
password: req.body.password
|
||||||
};
|
};
|
||||||
if (password === "s3cret") {
|
if (password === "s3cret") {
|
||||||
var token = jwt.sign(user, server.get('superSecret'), {
|
var token = jwt.sign(user, server.get('superSecret'), {
|
||||||
|
|
|
@ -6,7 +6,8 @@ import {HttpModule} from '@angular/http';
|
||||||
import {AppComponent} from './app.component';
|
import {AppComponent} from './app.component';
|
||||||
import {TaskService} from "./services/task-service/task.service";
|
import {TaskService} from "./services/task-service/task.service";
|
||||||
import {LoginService} from "./services/login-service/login-service";
|
import {LoginService} from "./services/login-service/login-service";
|
||||||
import {TaskStore} from './services/stores/task.store';
|
import {UserStore} from "./services/stores/user.store";
|
||||||
|
import {TaskStore} from "./services/stores/task.store";
|
||||||
import {ShowErrorComponent} from './show-error/show-error.component';
|
import {ShowErrorComponent} from './show-error/show-error.component';
|
||||||
import {APPLICATION_VALIDATORS} from './models/app-validators';
|
import {APPLICATION_VALIDATORS} from './models/app-validators';
|
||||||
import {appRouting, routingComponents, routingProviders} from './app.routing';
|
import {appRouting, routingComponents, routingProviders} from './app.routing';
|
||||||
|
@ -28,6 +29,7 @@ const enableAuthentication = !environment.e2eMode;
|
||||||
@NgModule({
|
@NgModule({
|
||||||
imports: [BrowserModule, FormsModule, ReactiveFormsModule, appRouting, HttpModule],
|
imports: [BrowserModule, FormsModule, ReactiveFormsModule, appRouting, HttpModule],
|
||||||
providers: [LoginService,
|
providers: [LoginService,
|
||||||
|
UserStore,
|
||||||
TaskService,
|
TaskService,
|
||||||
TaskStore,
|
TaskStore,
|
||||||
Title,
|
Title,
|
||||||
|
@ -43,4 +45,4 @@ const enableAuthentication = !environment.e2eMode;
|
||||||
bootstrap: [AppComponent]
|
bootstrap: [AppComponent]
|
||||||
})
|
})
|
||||||
export class AppModule {
|
export class AppModule {
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,14 @@
|
||||||
|
export interface User {
|
||||||
|
id?: number;
|
||||||
|
name?: string;
|
||||||
|
password?: string;
|
||||||
|
edit_tasks?: boolean;
|
||||||
|
change_settings?: boolean;
|
||||||
|
}
|
||||||
export interface Tag {
|
export interface Tag {
|
||||||
label: string;
|
label: string;
|
||||||
}
|
}
|
||||||
export interface User {
|
export interface Assignee {
|
||||||
name?: string;
|
name?: string;
|
||||||
email?: string;
|
email?: string;
|
||||||
}
|
}
|
||||||
|
@ -12,7 +19,7 @@ export interface Task {
|
||||||
tags?: Tag[];
|
tags?: Tag[];
|
||||||
favorite?: boolean;
|
favorite?: boolean;
|
||||||
state?: string;
|
state?: string;
|
||||||
assignee?: User;
|
assignee?: Assignee;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const states = ['BACKLOG', 'IN_PROGRESS', 'TEST', 'COMPLETED'];
|
export const states = ['BACKLOG', 'IN_PROGRESS', 'TEST', 'COMPLETED'];
|
||||||
|
|
|
@ -1,23 +1,48 @@
|
||||||
import {Inject, Optional} from '@angular/core'
|
import {Injectable, Inject, Optional} from '@angular/core';
|
||||||
import {AUTH_ENABLED} from '../../app.tokens';
|
import {User} from '../../models/model-interfaces';
|
||||||
|
import {Http, URLSearchParams, RequestMethod, RequestOptions} from '@angular/http';
|
||||||
|
import {Observable} from 'rxjs/Observable';
|
||||||
|
import {BehaviorSubject} from 'rxjs/BehaviorSubject';
|
||||||
|
import {LOAD, ADD, EDIT, REMOVE, UserStore} from '../stores/user.store';
|
||||||
|
import {SOCKET_IO, AUTH_ENABLED} from '../../app.tokens';
|
||||||
|
|
||||||
|
const BASE_URL = `http://localhost:3000/api/users`;
|
||||||
|
|
||||||
|
const WEB_SOCKET_URL = 'http://localhost:3001';
|
||||||
|
|
||||||
const CURRENT_USER = 'currentUser';
|
const CURRENT_USER = 'currentUser';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
export class LoginService {
|
export class LoginService {
|
||||||
|
|
||||||
USERS = [
|
socket: SocketIOClient.Socket;
|
||||||
{name: 'admin', password: 'admin', rights: ['edit_tasks', 'change_settings'] },
|
|
||||||
{name: 'user', password: 'secret', rights: ['edit_tasks'] }
|
|
||||||
];
|
|
||||||
|
|
||||||
constructor(@Optional() @Inject(AUTH_ENABLED) public authEnabled = false) {
|
users$: Observable<User[]>;
|
||||||
|
|
||||||
|
results$: User[];
|
||||||
|
|
||||||
|
constructor(@Optional() @Inject(AUTH_ENABLED) public authEnabled = false, private http: Http, private userStore: UserStore,
|
||||||
|
@Inject(SOCKET_IO) socketIO) {
|
||||||
|
this.users$ = userStore.items$;
|
||||||
|
this.socket = socketIO(WEB_SOCKET_URL);
|
||||||
|
Observable.fromEvent(this.socket, 'user_saved')
|
||||||
|
.subscribe((action) => {
|
||||||
|
this.userStore.dispatch(action);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
getUser(name: string) : User[]{
|
||||||
|
this.http.get(BASE_URL + "?name=" + name).subscribe(result => this.results$ = result.json());
|
||||||
|
return this.results$;
|
||||||
}
|
}
|
||||||
|
|
||||||
login(name, password) {
|
login(name, password) {
|
||||||
const [user] = this.USERS.filter(user => user.name == name);
|
if (this.getUser(name)) {
|
||||||
if (user && user.password === password) {
|
let user = this.results$[0];
|
||||||
localStorage.setItem(CURRENT_USER, JSON.stringify(user));
|
if (user && user.password === password) {
|
||||||
return true;
|
localStorage.setItem(CURRENT_USER, JSON.stringify(user));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -29,11 +54,4 @@ export class LoginService {
|
||||||
return !this.authEnabled || localStorage.getItem(CURRENT_USER) != null;
|
return !this.authEnabled || localStorage.getItem(CURRENT_USER) != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
getUser() {
|
|
||||||
const userString = localStorage.getItem(CURRENT_USER);
|
|
||||||
if (userString) {
|
|
||||||
return JSON.parse(userString);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1 +0,0 @@
|
||||||
export * from "./task.store";
|
|
|
@ -1,6 +0,0 @@
|
||||||
import {Store} from "./generic-store";
|
|
||||||
import {Task} from "../../models/model-interfaces";
|
|
||||||
|
|
||||||
export class TaskStore extends Store<Task> {
|
|
||||||
|
|
||||||
}
|
|
|
@ -36,4 +36,4 @@ export class TaskStore {
|
||||||
return tasks;
|
return tasks;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,39 @@
|
||||||
|
import {BehaviorSubject} from 'rxjs/BehaviorSubject';
|
||||||
|
import {User} from '../../models/model-interfaces';
|
||||||
|
|
||||||
|
export const LOAD = 'LOAD';
|
||||||
|
export const ADD = 'ADD';
|
||||||
|
export const EDIT = 'EDIT';
|
||||||
|
export const REMOVE = 'REMOVE';
|
||||||
|
|
||||||
|
export class UserStore {
|
||||||
|
private users: User[] = [];
|
||||||
|
items$ = new BehaviorSubject<User[]>([]);
|
||||||
|
|
||||||
|
dispatch(action) {
|
||||||
|
console.log("dispatched")
|
||||||
|
this.users = this._reduce(this.users, action);
|
||||||
|
this.items$.next(this.users);
|
||||||
|
}
|
||||||
|
|
||||||
|
_reduce(users: User[], action) {
|
||||||
|
switch (action.type) {
|
||||||
|
case LOAD:
|
||||||
|
return [...action.data];
|
||||||
|
case ADD:
|
||||||
|
return [...users, action.data];
|
||||||
|
case EDIT:
|
||||||
|
return users.map(user => {
|
||||||
|
const editedUser = action.data;
|
||||||
|
if (user.id !== editedUser.id){
|
||||||
|
return user;
|
||||||
|
}
|
||||||
|
return editedUser;
|
||||||
|
});
|
||||||
|
case REMOVE:
|
||||||
|
return users.filter(user => user.id !== action.data.id);
|
||||||
|
default:
|
||||||
|
return users;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -87,4 +87,4 @@ describe('Task-Service', () => {
|
||||||
expect(dispatchedAction.data.title).toEqual('Task 1');
|
expect(dispatchedAction.data.title).toEqual('Task 1');
|
||||||
}));
|
}));
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
|
@ -3,7 +3,7 @@ import {Task} from '../../models/model-interfaces';
|
||||||
import {Http, URLSearchParams, RequestMethod, RequestOptions} from '@angular/http';
|
import {Http, URLSearchParams, RequestMethod, RequestOptions} from '@angular/http';
|
||||||
import {Observable} from 'rxjs/Observable';
|
import {Observable} from 'rxjs/Observable';
|
||||||
import {BehaviorSubject} from 'rxjs/BehaviorSubject';
|
import {BehaviorSubject} from 'rxjs/BehaviorSubject';
|
||||||
import {LOAD, ADD, EDIT, REMOVE, TaskStore} from '../stores/index';
|
import {LOAD, ADD, EDIT, REMOVE, TaskStore} from '../stores/task.store';
|
||||||
import {SOCKET_IO} from '../../app.tokens';
|
import {SOCKET_IO} from '../../app.tokens';
|
||||||
|
|
||||||
const BASE_URL = `http://localhost:3000/api/tasks/`;
|
const BASE_URL = `http://localhost:3000/api/tasks/`;
|
||||||
|
|
Loading…
Reference in New Issue