From f1f03c9b69706872542d6f871f559d919d8c0c9a Mon Sep 17 00:00:00 2001 From: Florian Hartwich Date: Mon, 13 Mar 2017 04:12:18 +0100 Subject: [PATCH] Add user storage and db-based login --- project-manager/projects-server/db.json | 32 +++++++---- project-manager/projects-server/server.js | 2 +- project-manager/src/app/app.module.ts | 6 ++- .../src/app/models/model-interfaces.ts | 11 +++- .../services/login-service/login-service.ts | 54 ++++++++++++------- .../src/app/services/stores/index.ts | 1 - .../src/app/services/stores/stores.ts | 6 --- .../src/app/services/stores/task.store.ts | 2 +- .../src/app/services/stores/user.store.ts | 39 ++++++++++++++ .../task-service/task.service.spec.ts | 2 +- .../app/services/task-service/task.service.ts | 2 +- 11 files changed, 114 insertions(+), 43 deletions(-) delete mode 100644 project-manager/src/app/services/stores/index.ts delete mode 100644 project-manager/src/app/services/stores/stores.ts create mode 100644 project-manager/src/app/services/stores/user.store.ts diff --git a/project-manager/projects-server/db.json b/project-manager/projects-server/db.json index abf0717..af75b01 100644 --- a/project-manager/projects-server/db.json +++ b/project-manager/projects-server/db.json @@ -29,17 +29,29 @@ "assignee": {}, "id": 5, "state": "IN_PROGRESS" + } + ], + "users": [ + { + "id": 301, + "name": "admin", + "password": "admin", + "edit_tasks": true, + "change_settings": true }, { - "assignee": { - "name": "hardi", - "email": "hardi@noarch.de" - }, - "tags": [], - "state": "IN_PROGRESS", - "title": "Testplan schreiben", - "description": "Testplan für dieses Projekt anlegen", - "id": 6 + "id" : 302, + "name": "user_edit", + "password": "secret", + "edit_tasks": true, + "change_settings": false + }, + { + "id" : 303, + "name": "user", + "password": "secret", + "edit_tasks": false, + "change_settings": false } ] -} \ No newline at end of file +} diff --git a/project-manager/projects-server/server.js b/project-manager/projects-server/server.js index 48fddb0..e9c0985 100644 --- a/project-manager/projects-server/server.js +++ b/project-manager/projects-server/server.js @@ -65,7 +65,7 @@ if (secured) { var password = req.body.password; var user = { name: req.body.name, - passowrd: req.body.password + password: req.body.password }; if (password === "s3cret") { var token = jwt.sign(user, server.get('superSecret'), { diff --git a/project-manager/src/app/app.module.ts b/project-manager/src/app/app.module.ts index d4931f5..eac06a3 100644 --- a/project-manager/src/app/app.module.ts +++ b/project-manager/src/app/app.module.ts @@ -6,7 +6,8 @@ import {HttpModule} from '@angular/http'; import {AppComponent} from './app.component'; import {TaskService} from "./services/task-service/task.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 {APPLICATION_VALIDATORS} from './models/app-validators'; import {appRouting, routingComponents, routingProviders} from './app.routing'; @@ -28,6 +29,7 @@ const enableAuthentication = !environment.e2eMode; @NgModule({ imports: [BrowserModule, FormsModule, ReactiveFormsModule, appRouting, HttpModule], providers: [LoginService, + UserStore, TaskService, TaskStore, Title, @@ -43,4 +45,4 @@ const enableAuthentication = !environment.e2eMode; bootstrap: [AppComponent] }) export class AppModule { -} \ No newline at end of file +} diff --git a/project-manager/src/app/models/model-interfaces.ts b/project-manager/src/app/models/model-interfaces.ts index 560d320..8cb80ca 100644 --- a/project-manager/src/app/models/model-interfaces.ts +++ b/project-manager/src/app/models/model-interfaces.ts @@ -1,7 +1,14 @@ +export interface User { + id?: number; + name?: string; + password?: string; + edit_tasks?: boolean; + change_settings?: boolean; +} export interface Tag { label: string; } -export interface User { +export interface Assignee { name?: string; email?: string; } @@ -12,7 +19,7 @@ export interface Task { tags?: Tag[]; favorite?: boolean; state?: string; - assignee?: User; + assignee?: Assignee; } export const states = ['BACKLOG', 'IN_PROGRESS', 'TEST', 'COMPLETED']; diff --git a/project-manager/src/app/services/login-service/login-service.ts b/project-manager/src/app/services/login-service/login-service.ts index 31143b1..f5cb318 100644 --- a/project-manager/src/app/services/login-service/login-service.ts +++ b/project-manager/src/app/services/login-service/login-service.ts @@ -1,23 +1,48 @@ -import {Inject, Optional} from '@angular/core' -import {AUTH_ENABLED} from '../../app.tokens'; +import {Injectable, Inject, Optional} from '@angular/core'; +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'; +@Injectable() export class LoginService { - USERS = [ - {name: 'admin', password: 'admin', rights: ['edit_tasks', 'change_settings'] }, - {name: 'user', password: 'secret', rights: ['edit_tasks'] } - ]; + socket: SocketIOClient.Socket; - constructor(@Optional() @Inject(AUTH_ENABLED) public authEnabled = false) { + users$: Observable; + + 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) { - const [user] = this.USERS.filter(user => user.name == name); - if (user && user.password === password) { - localStorage.setItem(CURRENT_USER, JSON.stringify(user)); - return true; + if (this.getUser(name)) { + let user = this.results$[0]; + if (user && user.password === password) { + localStorage.setItem(CURRENT_USER, JSON.stringify(user)); + return true; + } } } @@ -29,11 +54,4 @@ export class LoginService { return !this.authEnabled || localStorage.getItem(CURRENT_USER) != null; } - getUser() { - const userString = localStorage.getItem(CURRENT_USER); - if (userString) { - return JSON.parse(userString); - } - } - } diff --git a/project-manager/src/app/services/stores/index.ts b/project-manager/src/app/services/stores/index.ts deleted file mode 100644 index b2a4ed7..0000000 --- a/project-manager/src/app/services/stores/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from "./task.store"; \ No newline at end of file diff --git a/project-manager/src/app/services/stores/stores.ts b/project-manager/src/app/services/stores/stores.ts deleted file mode 100644 index 655942a..0000000 --- a/project-manager/src/app/services/stores/stores.ts +++ /dev/null @@ -1,6 +0,0 @@ -import {Store} from "./generic-store"; -import {Task} from "../../models/model-interfaces"; - -export class TaskStore extends Store { - -} \ No newline at end of file diff --git a/project-manager/src/app/services/stores/task.store.ts b/project-manager/src/app/services/stores/task.store.ts index 71cc4f2..7177943 100644 --- a/project-manager/src/app/services/stores/task.store.ts +++ b/project-manager/src/app/services/stores/task.store.ts @@ -36,4 +36,4 @@ export class TaskStore { return tasks; } } -} \ No newline at end of file +} diff --git a/project-manager/src/app/services/stores/user.store.ts b/project-manager/src/app/services/stores/user.store.ts new file mode 100644 index 0000000..262e61f --- /dev/null +++ b/project-manager/src/app/services/stores/user.store.ts @@ -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([]); + + 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; + } + } +} diff --git a/project-manager/src/app/services/task-service/task.service.spec.ts b/project-manager/src/app/services/task-service/task.service.spec.ts index 92ac0de..85a6bd9 100644 --- a/project-manager/src/app/services/task-service/task.service.spec.ts +++ b/project-manager/src/app/services/task-service/task.service.spec.ts @@ -87,4 +87,4 @@ describe('Task-Service', () => { expect(dispatchedAction.data.title).toEqual('Task 1'); })); -}); \ No newline at end of file +}); diff --git a/project-manager/src/app/services/task-service/task.service.ts b/project-manager/src/app/services/task-service/task.service.ts index f556ce2..34a593a 100644 --- a/project-manager/src/app/services/task-service/task.service.ts +++ b/project-manager/src/app/services/task-service/task.service.ts @@ -3,7 +3,7 @@ import {Task} 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, TaskStore} from '../stores/index'; +import {LOAD, ADD, EDIT, REMOVE, TaskStore} from '../stores/task.store'; import {SOCKET_IO} from '../../app.tokens'; const BASE_URL = `http://localhost:3000/api/tasks/`;