1
0
mirror of https://github.com/xuthus83/pigallery2.git synced 2025-01-14 14:43:17 +08:00

removing socket.io creating first middlewares

This commit is contained in:
Braun Patrik 2016-03-19 09:58:27 +01:00
parent 87fb346c48
commit 2cc8070065
18 changed files with 182 additions and 133 deletions

View File

@ -0,0 +1,16 @@
import {NextFunction, Request, Response} from "express";
import {Message} from "../../common/entities/Message";
import {Error} from "../../common/entities/Error";
export class BaseMWs {
protected static renderMessage<T>(res:Response, content:T){
let message = new Message<T> ([],content);
res.json(message);
}
protected static renderError(res:Response, error:Error){
let message = new Message<any> ([],null);
res.json(message);
}
}

View File

@ -1,20 +1,22 @@
import {UserManager} from "../model/UserManager"; import {UserManager} from "../model/UserManager";
import {NextFunction, Request, Response} from "express"; import {NextFunction, Request, Response} from "express";
import {BaseMWs} from "./BaseMWs";
import {Error, ErrorCodes} from "../../common/entities/Error";
export class UserMWs { export class UserMWs extends BaseMWs{
public static authenticate(req:Request, res:Response, next:NextFunction){ public static authenticate(req:Request, res:Response, next:NextFunction){
if (typeof req.session.user === 'undefined') { if (typeof req.session.user === 'undefined') {
return res.redirect('/'); return super.renderError(res,new Error(ErrorCodes.NOT_AUTHENTICATED));
} }
return next(); return next();
} }
public static inverseAuthenticate(req:Request, res:Response, next:NextFunction){ public static inverseAuthenticate(req:Request, res:Response, next:NextFunction){
if (typeof req.session.user !== 'undefined') { if (typeof req.session.user !== 'undefined') {
return res.redirect('/'); return super.renderError(res,new Error(ErrorCodes.ALREADY_AUTHENTICATED));
} }
return next(); return next();
} }
@ -54,7 +56,7 @@ export class UserMWs {
public static renderUser(req:Request, res:Response, next:NextFunction){ public static renderUser(req:Request, res:Response, next:NextFunction){
res.json(req.session.user); super.renderMessage(res,req.session.user);
} }

View File

@ -9,7 +9,7 @@ export class UserRouter{
} }
private initLogin() { private initLogin() {
this.app.get("/api/login", this.app.post("/api/login",
UserMWs.inverseAuthenticate, UserMWs.inverseAuthenticate,
UserMWs.login, UserMWs.login,
UserMWs.renderUser UserMWs.renderUser

View File

@ -4,6 +4,7 @@ import * as _express from 'express';
import * as _session from 'express-session'; import * as _session from 'express-session';
import * as _debug from 'debug'; import * as _debug from 'debug';
import * as _http from 'http'; import * as _http from 'http';
import * as _path from 'path';
import {PublicRouter} from "./routes/PublicRouter"; import {PublicRouter} from "./routes/PublicRouter";
import {UserRouter} from "./routes/UserRouter"; import {UserRouter} from "./routes/UserRouter";
@ -42,6 +43,10 @@ export class Server {
new PublicRouter(this.app); new PublicRouter(this.app);
new UserRouter(this.app); new UserRouter(this.app);
var renderIndex = (req: _express.Request, res: _express.Response) => {
res.sendFile(_path.resolve(__dirname, './../frontend/index.html'));
};
this.app.get(['/login',"/gallery"], renderIndex);

View File

@ -1,3 +1,9 @@
export class Error{
export enum ErrorCodes{
NOT_AUTHENTICATED,
ALREADY_AUTHENTICATED
}
export class Error{
constructor(public code:ErrorCodes, public message?:String) {}
} }

View File

@ -1,5 +1,5 @@
import {Error} from "./Error"; import {Error} from "./Error";
export class Message<T>{ export class Message<T>{
constructor(public error:Error,public result:T){} constructor(public errors:Array<Error>,public result:T){}
} }

View File

@ -3,13 +3,13 @@
import { Component } from 'angular2/core'; import { Component } from 'angular2/core';
import { RouteConfig, ROUTER_DIRECTIVES, ROUTER_PROVIDERS } from 'angular2/router'; import { RouteConfig, ROUTER_DIRECTIVES, ROUTER_PROVIDERS } from 'angular2/router';
import {LoginComponent} from "./login/login.component"; import {LoginComponent} from "./login/login.component";
import {NetworkService} from "./model/network.service";
import {LoginService} from "./login/login.service";
import {AuthenticationService} from "./model/authentication.service"; import {AuthenticationService} from "./model/authentication.service";
import {GalleryComponent} from "./gallery/gallery.component"; import {GalleryComponent} from "./gallery/gallery.component";
import {OnInit} from "angular2/core"; import {OnInit} from "angular2/core";
import {User} from "../../common/entities/User"; import {User} from "../../common/entities/User";
import {Router} from "angular2/router"; import {Router, Location} from "angular2/router";
import {HTTP_PROVIDERS} from "angular2/http";
import {UserService} from "./model/user.service";
@ -19,10 +19,10 @@ import {Router} from "angular2/router";
template: `<router-outlet></router-outlet>`, template: `<router-outlet></router-outlet>`,
directives: [ROUTER_DIRECTIVES], directives: [ROUTER_DIRECTIVES],
providers: [ providers: [
HTTP_PROVIDERS,
ROUTER_PROVIDERS, ROUTER_PROVIDERS,
NetworkService, UserService,
AuthenticationService, AuthenticationService
LoginService
] ]
}) })
@RouteConfig([ @RouteConfig([
@ -40,13 +40,15 @@ import {Router} from "angular2/router";
]) ])
export class AppComponent implements OnInit{ export class AppComponent implements OnInit{
constructor(private _router: Router ,private _authenticationService: AuthenticationService){ constructor(private _router: Router, private _location:Location, private _authenticationService: AuthenticationService){
} }
ngOnInit() { ngOnInit() {
this._authenticationService.OnAuthenticated.on((user:User) => this._authenticationService.OnAuthenticated.on((user:User) =>
{ {
this._location.replaceState('/'); // clears browser history so they can't navigate with back button
this._router.navigate(["Gallery"]); this._router.navigate(["Gallery"]);
}); });
} }
} }

View File

@ -1,11 +1,25 @@
///<reference path="../../browser.d.ts"/> ///<reference path="../../browser.d.ts"/>
import { Component } from 'angular2/core'; import {Component, OnInit} from 'angular2/core';
import {AuthenticationService} from "../model/authentication.service";
import {Router,Location} from "angular2/router";
@Component({ @Component({
selector: 'gallery', selector: 'gallery',
templateUrl: 'app/gallery/gallery.component.html' templateUrl: 'app/gallery/gallery.component.html'
}) })
export class GalleryComponent{ export class GalleryComponent implements OnInit{
constructor(private _authService: AuthenticationService, private _router: Router, private _location:Location) {
}
ngOnInit(){
if (!this._authService.isAuthenticated()) {
this._location.replaceState('/'); // clears browser history so they can't navigate with back button
this._router.navigate(['Login']);
}
}
} }

View File

@ -1,13 +1,13 @@
<form> <form name="LoginForm">
<div class="group"> <div class="group">
<input type="text" [(ngModel)]="user.username" required><span class="highlight"></span><span class="bar"></span> <input type="text" [(ngModel)]="loginCredential.username" required><span class="highlight"></span><span class="bar"></span>
<label *ngIf="!user.username">Username (or e-mail)</label> <label *ngIf="!loginCredential.username">Username (or e-mail)</label>
</div> </div>
<div class="group"> <div class="group">
<input type="password" [(ngModel)]="user.password" required><span class="highlight"></span><span class="bar"></span> <input type="password" [(ngModel)]="loginCredential.password" required><span class="highlight"></span><span class="bar"></span>
<label *ngIf="!user.password">Password</label> <label *ngIf="!loginCredential.password">Password</label>
</div> </div>
<button type="button" class="button buttonBlue" (click)="onLogin()">Login <button type="button" class="button buttonBlue" (disabled)="LoginForm.$invalid" (click)="onLogin()">Login
<div class="ripples buttonRipples"><span class="ripplesCircle"></span></div> <div class="ripples buttonRipples"><span class="ripplesCircle"></span></div>
</button> </button>
</form> </form>

View File

@ -1,22 +1,30 @@
///<reference path="../../browser.d.ts"/> ///<reference path="../../browser.d.ts"/>
import { Component, OnInit } from 'angular2/core'; import {Component, OnInit} from 'angular2/core';
import {LoginCredential} from '../../../common/entities/LoginCredential'; import {LoginCredential} from '../../../common/entities/LoginCredential';
import {LoginService} from "./login.service"; import {AuthenticationService} from "../model/authentication.service";
import {Router, Location} from "angular2/router";
@Component({ @Component({
selector: 'login', selector: 'login',
templateUrl: 'app/login/login.component.html', templateUrl: 'app/login/login.component.html',
styleUrls: ['app/login/login.component.css'] styleUrls: ['app/login/login.component.css']
}) })
export class LoginComponent{ export class LoginComponent implements OnInit{
user: LoginCredential; loginCredential: LoginCredential;
constructor(private _loginService: LoginService) { constructor(private _authService: AuthenticationService, private _router: Router, private _location:Location) {
this.user = new LoginCredential(); this.loginCredential = new LoginCredential();
}
ngOnInit(){
if (this._authService.isAuthenticated()) {
this._location.replaceState('/'); // clears browser history so they can't navigate with back button
this._router.navigate(['Gallery']);
}
} }
onLogin(){ onLogin(){
this._loginService.login(this.user); this._authService.login(this.loginCredential);
} }
} }

View File

@ -1,42 +0,0 @@
///<reference path="../../browser.d.ts"/>
import {
it,
inject,
injectAsync,
beforeEachProviders,
TestComponentBuilder
} from 'angular2/testing';
import {Component, provide} from 'angular2/core';
import {BaseRequestOptions, Http} from 'angular2/http';
import {MockBackend} from 'angular2/http/testing';
import {LoginService} from "./login.service";
import {NetworkService} from "../model/network.service";
describe('LoginService', () => {
beforeEachProviders(() => [
provide(NetworkService, {
useFactory: function() {
return {login() {}};
}
}),
LoginService
]);
it('should call Network service login', inject([ LoginService,NetworkService ], (loginService, networkService) => {
spyOn(networkService,"login");
expect(networkService.login).not.toHaveBeenCalled();
loginService.login();
expect(networkService.login).toHaveBeenCalled();
}));
it('should be true', () => {
expect(true).toEqual(true)
});
});

View File

@ -1,22 +0,0 @@
///<reference path="../../browser.d.ts"/>
import {Injectable} from 'angular2/core';
import {NetworkService} from "../model/network.service";
import {OnInit} from "angular2/core";
import {LoginCredential} from "../../../common/entities/LoginCredential";
import {User} from "../../../common/entities/User";
import {Message} from "../../../common/entities/Message";
@Injectable()
export class LoginService {
constructor(private _networkService: NetworkService){
}
public login(credential:LoginCredential) {
this._networkService.login(credential);
}
}

View File

@ -0,0 +1,37 @@
///<reference path="../../browser.d.ts"/>
import {
it,
inject,
injectAsync,
beforeEachProviders,
TestComponentBuilder
} from 'angular2/testing';
import {Component, provide} from 'angular2/core';
import {AuthenticationService} from "../../../frontend/app/model/authentication.service";
import {UserService} from "./user.service";
describe('LoginService', () => {
beforeEachProviders(() => [
provide(UserService, {
useFactory: function() {
return {login() {}};
}
}),
AuthenticationService
]);
it('should call User service login', inject([ AuthenticationService,UserService ], (authService, userService) => {
spyOn(userService,"login");
expect(userService.login).not.toHaveBeenCalled();
authService.login();
expect(userService.login).toHaveBeenCalled();
}));
});

View File

@ -1,28 +1,38 @@
///<reference path="../../browser.d.ts"/> ///<reference path="../../browser.d.ts"/>
import * as io from 'socket.io-client';
import {Injectable} from 'angular2/core'; import {Injectable} from 'angular2/core';
import {OnInit} from "angular2/core";
import {NetworkService} from "./network.service";
import {User} from "../../../common/entities/User"; import {User} from "../../../common/entities/User";
import {Event} from "../../../common/event/Event"; import {Event} from "../../../common/event/Event";
import {UserService} from "./user.service";
import {LoginCredential} from "../../../common/entities/LoginCredential";
import {Message} from "../../../common/entities/Message";
@Injectable() @Injectable()
export class AuthenticationService{ export class AuthenticationService{
private _user:User; private _user:User = null;
public OnAuthenticated:Event<User>; public OnAuthenticated:Event<User>;
constructor(private _networkService: NetworkService){ constructor(private _userService: UserService){
this.OnAuthenticated = new Event(); this.OnAuthenticated = new Event();
this._networkService.OnAuthenticated.on(this.onAuthenticated);
} }
public login(credential:LoginCredential){
private onAuthenticated = (user:User) => { this._userService.login(credential).then( (message:Message<User>) =>{
this._user=user; console.log(message);
this.OnAuthenticated.trigger(this._user); if(message.errors && message.errors.length > 0){
console.log(message.errors);
}else{
this._user = message.result;
this.OnAuthenticated.trigger(this._user);
}
});
} }
public isAuthenticated():boolean{
return this._user && this._user != null;
}
} }

View File

@ -1,39 +1,33 @@
///<reference path="../../browser.d.ts"/> ///<reference path="../../browser.d.ts"/>
import * as io from 'socket.io-client'; import {Http, Headers, RequestOptions, Response} from "angular2/http";
import {Injectable} from 'angular2/core';
import {OnInit} from "angular2/core";
import {LoginCredential} from "../../../common/entities/LoginCredential";
import {MessageTypes} from "../../../common/MessageTypes";
import {Event} from "../../../common/event/Event";
import {User} from "../../../common/entities/User";
import {Message} from "../../../common/entities/Message"; import {Message} from "../../../common/entities/Message";
import "rxjs/Rx";
@Injectable()
export class NetworkService{ export class NetworkService{
private _socketIO: SocketIOClient.Socket; _baseUrl = "/api";
public OnAuthenticated:Event<User>; constructor(protected _http:Http){
constructor(){
this._socketIO = io();
this.OnAuthenticated = new Event();
this._subscribeMessages();
} }
public login(credential:LoginCredential){ protected postJson(url:string, data:any = {}){
this._socketIO.emit(MessageTypes.Client.Login.Authenticate,credential); let body = JSON.stringify({ data });
let headers = new Headers({ 'Content-Type': 'application/json' });
let options = new RequestOptions({ headers: headers });
console.log(this._http.post(this._baseUrl+url, body, options));
return this._http.post(this._baseUrl+url, body, options)
.toPromise()
.then(res => <Message<any>> res.json())
.catch(NetworkService.handleError);
} }
private _subscribeMessages(){ private static handleError (error: any) {
this._socketIO.on(MessageTypes.Server.Login.Authenticated, (message:Message<User>) =>{ // in a real world app, we may send the error to some remote logging infrastructure
if(message.error){ // instead of just logging it to the console
//TODO: Handle error console.error(error);
}else{ return Promise.reject(error.message || error.json().error || 'Server error');
this.OnAuthenticated.trigger(message.result);
}
});
} }
} }

View File

@ -0,0 +1,23 @@
///<reference path="../../browser.d.ts"/>
import {Injectable} from 'angular2/core';
import {LoginCredential} from "../../../common/entities/LoginCredential";
import {Http} from "angular2/http";
import {NetworkService} from "./network.service";
@Injectable()
export class UserService extends NetworkService{
constructor(_http:Http){
super(_http);
}
public login(credential:LoginCredential){
return this.postJson("/login",credential);
}
}

View File

@ -33,8 +33,6 @@
"protractor": "^3.2.0", "protractor": "^3.2.0",
"reflect-metadata": "0.1.2", "reflect-metadata": "0.1.2",
"rxjs": "^5.0.0-beta.2", "rxjs": "^5.0.0-beta.2",
"socket.io": "^1.4.5",
"socket.io-client": "^1.4.5",
"ts-loader": "^0.8.1", "ts-loader": "^0.8.1",
"ts-node": "^0.6.2", "ts-node": "^0.6.2",
"typescript": "^1.8.9", "typescript": "^1.8.9",

View File

@ -8,8 +8,6 @@
"jasmine": "github:DefinitelyTyped/DefinitelyTyped/jasmine/jasmine.d.ts#d22516f9f089de107d7e7d5938566377370631f6", "jasmine": "github:DefinitelyTyped/DefinitelyTyped/jasmine/jasmine.d.ts#d22516f9f089de107d7e7d5938566377370631f6",
"mime": "github:DefinitelyTyped/DefinitelyTyped/mime/mime.d.ts#0d622d857f97d44ea7dcad2b3edec1f23c48fe9e", "mime": "github:DefinitelyTyped/DefinitelyTyped/mime/mime.d.ts#0d622d857f97d44ea7dcad2b3edec1f23c48fe9e",
"node": "github:DefinitelyTyped/DefinitelyTyped/node/node.d.ts#0d622d857f97d44ea7dcad2b3edec1f23c48fe9e", "node": "github:DefinitelyTyped/DefinitelyTyped/node/node.d.ts#0d622d857f97d44ea7dcad2b3edec1f23c48fe9e",
"serve-static": "github:DefinitelyTyped/DefinitelyTyped/serve-static/serve-static.d.ts#0d622d857f97d44ea7dcad2b3edec1f23c48fe9e", "serve-static": "github:DefinitelyTyped/DefinitelyTyped/serve-static/serve-static.d.ts#0d622d857f97d44ea7dcad2b3edec1f23c48fe9e"
"socket.io": "github:DefinitelyTyped/DefinitelyTyped/socket.io/socket.io.d.ts#d22516f9f089de107d7e7d5938566377370631f6",
"socket.io-client": "github:DefinitelyTyped/DefinitelyTyped/socket.io-client/socket.io-client.d.ts#d22516f9f089de107d7e7d5938566377370631f6"
} }
} }