From 2cc8070065738108359338631a1a59cfadd54e09 Mon Sep 17 00:00:00 2001 From: Braun Patrik Date: Sat, 19 Mar 2016 09:58:27 +0100 Subject: [PATCH] removing socket.io creating first middlewares --- backend/middlewares/BaseMWs.ts | 16 +++++++ backend/middlewares/UserMWs.ts | 10 +++-- backend/routes/UserRouter.ts | 2 +- backend/server.ts | 5 +++ common/entities/Error.ts | 8 +++- common/entities/Message.ts | 2 +- frontend/app/app.component.ts | 16 ++++--- frontend/app/gallery/gallery.component.ts | 18 +++++++- frontend/app/login/login.component.html | 12 ++--- frontend/app/login/login.component.ts | 22 +++++++--- frontend/app/login/login.service.spec.ts | 42 ------------------ frontend/app/login/login.service.ts | 22 ---------- .../app/model/autehentication.service.spec.ts | 37 ++++++++++++++++ frontend/app/model/authentication.service.ts | 30 ++++++++----- frontend/app/model/network.service.ts | 44 ++++++++----------- frontend/app/model/user.service.ts | 23 ++++++++++ package.json | 2 - typings.json | 4 +- 18 files changed, 182 insertions(+), 133 deletions(-) create mode 100644 backend/middlewares/BaseMWs.ts delete mode 100644 frontend/app/login/login.service.spec.ts delete mode 100644 frontend/app/login/login.service.ts create mode 100644 frontend/app/model/autehentication.service.spec.ts create mode 100644 frontend/app/model/user.service.ts diff --git a/backend/middlewares/BaseMWs.ts b/backend/middlewares/BaseMWs.ts new file mode 100644 index 00000000..164e7262 --- /dev/null +++ b/backend/middlewares/BaseMWs.ts @@ -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(res:Response, content:T){ + let message = new Message ([],content); + res.json(message); + } + protected static renderError(res:Response, error:Error){ + let message = new Message ([],null); + res.json(message); + } +} \ No newline at end of file diff --git a/backend/middlewares/UserMWs.ts b/backend/middlewares/UserMWs.ts index d09f6eb3..65467149 100644 --- a/backend/middlewares/UserMWs.ts +++ b/backend/middlewares/UserMWs.ts @@ -1,20 +1,22 @@ import {UserManager} from "../model/UserManager"; 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){ if (typeof req.session.user === 'undefined') { - return res.redirect('/'); + return super.renderError(res,new Error(ErrorCodes.NOT_AUTHENTICATED)); } return next(); } public static inverseAuthenticate(req:Request, res:Response, next:NextFunction){ if (typeof req.session.user !== 'undefined') { - return res.redirect('/'); + return super.renderError(res,new Error(ErrorCodes.ALREADY_AUTHENTICATED)); } return next(); } @@ -54,7 +56,7 @@ export class UserMWs { public static renderUser(req:Request, res:Response, next:NextFunction){ - res.json(req.session.user); + super.renderMessage(res,req.session.user); } diff --git a/backend/routes/UserRouter.ts b/backend/routes/UserRouter.ts index 7200dcda..2f01a093 100644 --- a/backend/routes/UserRouter.ts +++ b/backend/routes/UserRouter.ts @@ -9,7 +9,7 @@ export class UserRouter{ } private initLogin() { - this.app.get("/api/login", + this.app.post("/api/login", UserMWs.inverseAuthenticate, UserMWs.login, UserMWs.renderUser diff --git a/backend/server.ts b/backend/server.ts index ce4842c6..bdccc042 100644 --- a/backend/server.ts +++ b/backend/server.ts @@ -4,6 +4,7 @@ import * as _express from 'express'; import * as _session from 'express-session'; import * as _debug from 'debug'; import * as _http from 'http'; +import * as _path from 'path'; import {PublicRouter} from "./routes/PublicRouter"; import {UserRouter} from "./routes/UserRouter"; @@ -42,6 +43,10 @@ export class Server { new PublicRouter(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); diff --git a/common/entities/Error.ts b/common/entities/Error.ts index d6129cba..ed348760 100644 --- a/common/entities/Error.ts +++ b/common/entities/Error.ts @@ -1,3 +1,9 @@ -export class Error{ +export enum ErrorCodes{ + NOT_AUTHENTICATED, + ALREADY_AUTHENTICATED +} + +export class Error{ + constructor(public code:ErrorCodes, public message?:String) {} } \ No newline at end of file diff --git a/common/entities/Message.ts b/common/entities/Message.ts index 47871d11..a1ecc184 100644 --- a/common/entities/Message.ts +++ b/common/entities/Message.ts @@ -1,5 +1,5 @@ import {Error} from "./Error"; export class Message{ - constructor(public error:Error,public result:T){} + constructor(public errors:Array,public result:T){} } \ No newline at end of file diff --git a/frontend/app/app.component.ts b/frontend/app/app.component.ts index ad1d99d1..7cc2aa8c 100644 --- a/frontend/app/app.component.ts +++ b/frontend/app/app.component.ts @@ -3,13 +3,13 @@ import { Component } from 'angular2/core'; import { RouteConfig, ROUTER_DIRECTIVES, ROUTER_PROVIDERS } from 'angular2/router'; 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 {GalleryComponent} from "./gallery/gallery.component"; import {OnInit} from "angular2/core"; 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: ``, directives: [ROUTER_DIRECTIVES], providers: [ + HTTP_PROVIDERS, ROUTER_PROVIDERS, - NetworkService, - AuthenticationService, - LoginService + UserService, + AuthenticationService ] }) @RouteConfig([ @@ -40,13 +40,15 @@ import {Router} from "angular2/router"; ]) export class AppComponent implements OnInit{ - constructor(private _router: Router ,private _authenticationService: AuthenticationService){ + constructor(private _router: Router, private _location:Location, private _authenticationService: AuthenticationService){ } ngOnInit() { this._authenticationService.OnAuthenticated.on((user:User) => { + this._location.replaceState('/'); // clears browser history so they can't navigate with back button this._router.navigate(["Gallery"]); }); + } } \ No newline at end of file diff --git a/frontend/app/gallery/gallery.component.ts b/frontend/app/gallery/gallery.component.ts index ac3f3803..63ef5fd1 100644 --- a/frontend/app/gallery/gallery.component.ts +++ b/frontend/app/gallery/gallery.component.ts @@ -1,11 +1,25 @@ /// -import { Component } from 'angular2/core'; +import {Component, OnInit} from 'angular2/core'; +import {AuthenticationService} from "../model/authentication.service"; +import {Router,Location} from "angular2/router"; @Component({ selector: 'gallery', 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']); + } + } + } diff --git a/frontend/app/login/login.component.html b/frontend/app/login/login.component.html index 71bf3ea7..26edf893 100644 --- a/frontend/app/login/login.component.html +++ b/frontend/app/login/login.component.html @@ -1,13 +1,13 @@ -
+
- - + +
- - + +
-
\ No newline at end of file diff --git a/frontend/app/login/login.component.ts b/frontend/app/login/login.component.ts index ccb4c7de..a1b54b4e 100644 --- a/frontend/app/login/login.component.ts +++ b/frontend/app/login/login.component.ts @@ -1,22 +1,30 @@ /// -import { Component, OnInit } from 'angular2/core'; +import {Component, OnInit} from 'angular2/core'; import {LoginCredential} from '../../../common/entities/LoginCredential'; -import {LoginService} from "./login.service"; +import {AuthenticationService} from "../model/authentication.service"; +import {Router, Location} from "angular2/router"; @Component({ selector: 'login', templateUrl: 'app/login/login.component.html', styleUrls: ['app/login/login.component.css'] }) -export class LoginComponent{ - user: LoginCredential; - constructor(private _loginService: LoginService) { - this.user = new LoginCredential(); +export class LoginComponent implements OnInit{ + loginCredential: LoginCredential; + constructor(private _authService: AuthenticationService, private _router: Router, private _location:Location) { + 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(){ - this._loginService.login(this.user); + this._authService.login(this.loginCredential); } } diff --git a/frontend/app/login/login.service.spec.ts b/frontend/app/login/login.service.spec.ts deleted file mode 100644 index e91d6097..00000000 --- a/frontend/app/login/login.service.spec.ts +++ /dev/null @@ -1,42 +0,0 @@ -/// - -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) - }); - -}); diff --git a/frontend/app/login/login.service.ts b/frontend/app/login/login.service.ts deleted file mode 100644 index ed07336c..00000000 --- a/frontend/app/login/login.service.ts +++ /dev/null @@ -1,22 +0,0 @@ -/// - -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); - } - - - -} \ No newline at end of file diff --git a/frontend/app/model/autehentication.service.spec.ts b/frontend/app/model/autehentication.service.spec.ts new file mode 100644 index 00000000..15beb580 --- /dev/null +++ b/frontend/app/model/autehentication.service.spec.ts @@ -0,0 +1,37 @@ +/// + +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(); + })); + + +}); diff --git a/frontend/app/model/authentication.service.ts b/frontend/app/model/authentication.service.ts index 96b9d5b6..891b021d 100644 --- a/frontend/app/model/authentication.service.ts +++ b/frontend/app/model/authentication.service.ts @@ -1,28 +1,38 @@ /// -import * as io from 'socket.io-client'; import {Injectable} from 'angular2/core'; -import {OnInit} from "angular2/core"; -import {NetworkService} from "./network.service"; import {User} from "../../../common/entities/User"; import {Event} from "../../../common/event/Event"; +import {UserService} from "./user.service"; +import {LoginCredential} from "../../../common/entities/LoginCredential"; +import {Message} from "../../../common/entities/Message"; @Injectable() export class AuthenticationService{ - private _user:User; + private _user:User = null; public OnAuthenticated:Event; - constructor(private _networkService: NetworkService){ + constructor(private _userService: UserService){ this.OnAuthenticated = new Event(); - this._networkService.OnAuthenticated.on(this.onAuthenticated); } - - private onAuthenticated = (user:User) => { - this._user=user; - this.OnAuthenticated.trigger(this._user); + public login(credential:LoginCredential){ + this._userService.login(credential).then( (message:Message) =>{ + console.log(message); + 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; + } + + } diff --git a/frontend/app/model/network.service.ts b/frontend/app/model/network.service.ts index 28fad967..996fa2c4 100644 --- a/frontend/app/model/network.service.ts +++ b/frontend/app/model/network.service.ts @@ -1,39 +1,33 @@ /// -import * as io from 'socket.io-client'; -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 {Http, Headers, RequestOptions, Response} from "angular2/http"; import {Message} from "../../../common/entities/Message"; +import "rxjs/Rx"; -@Injectable() export class NetworkService{ - private _socketIO: SocketIOClient.Socket; + _baseUrl = "/api"; - public OnAuthenticated:Event; - - constructor(){ - this._socketIO = io(); - this.OnAuthenticated = new Event(); - this._subscribeMessages(); + constructor(protected _http:Http){ } + - public login(credential:LoginCredential){ - this._socketIO.emit(MessageTypes.Client.Login.Authenticate,credential); + protected postJson(url:string, data:any = {}){ + 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 => > res.json()) + .catch(NetworkService.handleError); } - private _subscribeMessages(){ - this._socketIO.on(MessageTypes.Server.Login.Authenticated, (message:Message) =>{ - if(message.error){ - //TODO: Handle error - }else{ - this.OnAuthenticated.trigger(message.result); - } - }); + private static handleError (error: any) { + // in a real world app, we may send the error to some remote logging infrastructure + // instead of just logging it to the console + console.error(error); + return Promise.reject(error.message || error.json().error || 'Server error'); } } diff --git a/frontend/app/model/user.service.ts b/frontend/app/model/user.service.ts new file mode 100644 index 00000000..49f660dc --- /dev/null +++ b/frontend/app/model/user.service.ts @@ -0,0 +1,23 @@ +/// + +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); + } + + +} diff --git a/package.json b/package.json index a0624249..992e2809 100644 --- a/package.json +++ b/package.json @@ -33,8 +33,6 @@ "protractor": "^3.2.0", "reflect-metadata": "0.1.2", "rxjs": "^5.0.0-beta.2", - "socket.io": "^1.4.5", - "socket.io-client": "^1.4.5", "ts-loader": "^0.8.1", "ts-node": "^0.6.2", "typescript": "^1.8.9", diff --git a/typings.json b/typings.json index e3b39215..2802c5e2 100644 --- a/typings.json +++ b/typings.json @@ -8,8 +8,6 @@ "jasmine": "github:DefinitelyTyped/DefinitelyTyped/jasmine/jasmine.d.ts#d22516f9f089de107d7e7d5938566377370631f6", "mime": "github:DefinitelyTyped/DefinitelyTyped/mime/mime.d.ts#0d622d857f97d44ea7dcad2b3edec1f23c48fe9e", "node": "github:DefinitelyTyped/DefinitelyTyped/node/node.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" + "serve-static": "github:DefinitelyTyped/DefinitelyTyped/serve-static/serve-static.d.ts#0d622d857f97d44ea7dcad2b3edec1f23c48fe9e" } }