Add user storage and db-based login

keep-around/dc735e80914fa50c9bca8f6c78c100b7ed19408f
Florian Hartwich 2017-03-13 04:12:18 +01:00
parent b880e2d062
commit f1f03c9b69
11 changed files with 114 additions and 43 deletions

View File

@ -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
}
]
}

View File

@ -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'), {

View File

@ -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,

View File

@ -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'];

View File

@ -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<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) {
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);
}
}
}

View File

@ -1 +0,0 @@
export * from "./task.store";

View File

@ -1,6 +0,0 @@
import {Store} from "./generic-store";
import {Task} from "../../models/model-interfaces";
export class TaskStore extends Store<Task> {
}

View File

@ -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;
}
}
}

View File

@ -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/`;