1
0
mirror of https://github.com/bpatrik/pigallery2.git synced 2025-01-26 05:27:35 +02:00

implementing routers and user middlewares

This commit is contained in:
Braun Patrik 2016-03-19 17:31:42 +01:00
parent ffc8574b79
commit cb1be3ce4b
18 changed files with 483 additions and 70 deletions

View File

@ -0,0 +1,70 @@
import {UserManager} from "../model/UserManager";
import {NextFunction, Request, Response} from "express";
import {BaseMWs} from "./BaseMWs";
import {Error, ErrorCodes} from "../../common/entities/Error";
import {UserRoles} from "../../common/entities/User";
import {Utils} from "../../common/Utils";
export class AuthenticationMWs extends BaseMWs{
public static authenticate(req:Request, res:Response, next:NextFunction){
if (typeof req.session.user === 'undefined') {
return super.renderError(res,new Error(ErrorCodes.NOT_AUTHENTICATED));
}
return next();
}
public static authorise(role:UserRoles){
return (req:Request, res:Response, next:NextFunction) => {
if (req.session.user.role < role) {
return super.renderError(res, new Error(ErrorCodes.NOT_AUTHORISED));
}
return next();
};
}
public static inverseAuthenticate(req:Request, res:Response, next:NextFunction){
if (typeof req.session.user !== 'undefined') {
return super.renderError(res,new Error(ErrorCodes.ALREADY_AUTHENTICATED));
}
return next();
}
public static login(req:Request, res:Response, next:NextFunction){
//not enough parameter
if ((typeof req.body === 'undefined') || (typeof req.body.logincredential === 'undefined') || (typeof req.body.logincredential.username === 'undefined') ||
(typeof req.body.logincredential.password === 'undefined')) {
return next();
}
//lets find the user
UserManager.findOne({
username: req.body.logincredential.username
}, (err, result) => {
if ((err) || (!result)) {
return super.renderError(res,new Error(ErrorCodes.CREDENTIAL_NOT_FOUND));
}
//check password
if (result.password !== req.body.logincredential.password) {
return super.renderError(res,new Error(ErrorCodes.CREDENTIAL_NOT_FOUND));
}
req.session.user = result;
return next();
});
}
public static renderUser(req:Request, res:Response, next:NextFunction){
let user = Utils.clone(req.session.user);
delete user.password;
super.renderMessage(res,user);
}
}

View File

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

View File

@ -3,61 +3,90 @@ import {UserManager} from "../model/UserManager";
import {NextFunction, Request, Response} from "express";
import {BaseMWs} from "./BaseMWs";
import {Error, ErrorCodes} from "../../common/entities/Error";
import Util = jasmine.Util;
export class UserMWs extends BaseMWs{
public static authenticate(req:Request, res:Response, next:NextFunction){
if (typeof req.session.user === 'undefined') {
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 super.renderError(res,new Error(ErrorCodes.ALREADY_AUTHENTICATED));
}
return next();
}
public static login(req:Request, res:Response, next:NextFunction){
//not enough parameter
/* if ((typeof req.body === 'undefined') || (typeof req.body.email === 'undefined') ||
(typeof req.body.password === 'undefined')) {
public static changePassword(req:Request, res:Response, next:NextFunction){
if ((typeof req.body === 'undefined') || (typeof req.body.userModReq === 'undefined')
|| (typeof req.body.userModReq.id === 'undefined')
|| (typeof req.body.userModReq.oldPassword === 'undefined')
|| (typeof req.body.userModReq.newPassword === 'undefined')) {
return next();
}*/
//lets find the user
UserManager.findOne({
// email: req.body.email
}, function (err, result) {
}
UserManager.changePassword(req.body.userModReq, (err, result) =>{
if ((err) || (!result)) {
// res.tpl.error.push('Your email address is not registered!');
console.log(err);
return next();
return super.renderError(res,new Error(ErrorCodes.GENERAL_ERROR));
}
/* //check password
if (result.password !== req.body.password) {
// res.tpl.error.push('Wrong password!');
return next();
}
*/
//login is ok, save id to session
req.session.user = result;
return next();
});
}
//redirect to / so the app can decide where to go next
// return res.redirect('/');
public static createUser(req:Request, res:Response, next:NextFunction){
if ((typeof req.body === 'undefined') || (typeof req.body.newUser === 'undefined')) {
return next();
}
UserManager.createUser(req.body.newUser, (err, result) =>{
if ((err) || (!result)) {
return super.renderError(res,new Error(ErrorCodes.USER_CREATION_ERROR));
}
return next();
});
}
public static deleteUser(req:Request, res:Response, next:NextFunction){
if ((typeof req.body === 'undefined') || (typeof req.body.newUser === 'undefined')
|| (typeof req.body.userModReq.id === 'undefined')) {
return next();
}
UserManager.deleteUser(req.body.userModReq.id, (err, result) =>{
if ((err) || (!result)) {
return super.renderError(res,new Error(ErrorCodes.GENERAL_ERROR));
}
return next();
});
}
public static changeRole(req:Request, res:Response, next:NextFunction){
if ((typeof req.body === 'undefined') || (typeof req.body.userModReq === 'undefined')
|| (typeof req.body.userModReq.id === 'undefined')
|| (typeof req.body.userModReq.newRole === 'undefined')) {
return next();
}
UserManager.changeRole(req.body.userModReq, (err, result) =>{
if ((err) || (!result)) {
return super.renderError(res,new Error(ErrorCodes.GENERAL_ERROR));
}
return next();
});
}
public static renderUser(req:Request, res:Response, next:NextFunction){
super.renderMessage(res,req.session.user);
public static listUsers(req:Request, res:Response, next:NextFunction){
UserManager.find({}, (err, result) =>{
if ((err) || (!result)) {
return super.renderError(res,new Error(ErrorCodes.GENERAL_ERROR));
}
super.renderMessage(res,result);
});
}
}

View File

@ -0,0 +1,59 @@
import {UserManager} from "../model/UserManager";
import {NextFunction, Request, Response} from "express";
import {BaseMWs} from "./BaseMWs";
import {Error, ErrorCodes} from "../../common/entities/Error";
import {UserRoles} from "../../common/entities/User";
export class UserRequestConstrainsMWs extends BaseMWs{
public static forceSelfRequest(req:Request, res:Response, next:NextFunction){
if ((typeof req.params === 'undefined') || (typeof req.params.id === 'undefined')) {
return next();
}
if(req.session.user.id !== req.params.id){
return super.renderError(res,new Error(ErrorCodes.NOT_AUTHORISED));
}
return next();
}
public static notSelfRequest(req:Request, res:Response, next:NextFunction){
if ((typeof req.params === 'undefined') || (typeof req.params.id === 'undefined')) {
return next();
}
if(req.session.user.id === req.params.id){
return super.renderError(res,new Error(ErrorCodes.NOT_AUTHORISED));
}
return next();
}
public static notSelfRequestOr2Admins(req:Request, res:Response, next:NextFunction){
if ((typeof req.params === 'undefined') || (typeof req.params.id === 'undefined')) {
return next();
}
if(req.session.user.id !== req.params.id){
return next();
}
UserManager.find({minRole:UserRoles.Admin}, (err, result) =>{
if ((err) || (!result)) {
return super.renderError(res,new Error(ErrorCodes.GENERAL_ERROR));
}
if(result.length <= 1) {
return super.renderError(res, new Error(ErrorCodes.GENERAL_ERROR));
}
});
return next();
}
}

View File

@ -1,10 +1,31 @@
import {User} from "../../common/entities/User";
export class UserManager {
private static DummyUser = new User("TestUser","test@test.hu","122345");
private static users = [new User(1,"TestUser","test@test.hu","122345")];
public static findOne(filter,cb:(error: any,result:User) => void){
return cb(null, UserManager.DummyUser);
return cb(null, UserManager.users[0]);
}
public static find(filter,cb:(error: any,result:Array<User>) => void){
return cb(null, UserManager.users);
}
public static createUser(user,cb:(error: any,result:User) => void){
UserManager.users.push(user);
return cb(null, user);
}
public static deleteUser(id:number,cb:(error: any,result:string) => void){
UserManager.users = UserManager.users.filter(u => u.id != id);
return cb(null, "ok");
}
public static changeRole(request:any,cb:(error: any,result:string) => void){
return cb(null,"ok");
}
public static changePassword(request:any,cb:(error: any,result:string) => void){
return cb(null,"ok");
}
}

View File

@ -0,0 +1,33 @@
///<reference path="../../typings/main.d.ts"/>
import {AuthenticationMWs} from "../middlewares/AuthenticationMWs";
import {UserRoles} from "../../common/entities/User";
export class AdminRouter{
constructor(private app) {
this.addResetDB();
this.addIndexGalery();
}
private addResetDB() {
this.app.post("/api/admin/db/reset",
AuthenticationMWs.authenticate,
AuthenticationMWs.authorise(UserRoles.Admin)
//TODO: implement
);
};
private addIndexGalery() {
this.app.post("/api/admin/gallery/index",
AuthenticationMWs.authenticate,
AuthenticationMWs.authorise(UserRoles.Admin)
//TODO: implement
);
};
}

View File

@ -0,0 +1,54 @@
///<reference path="../../typings/main.d.ts"/>
import {AuthenticationMWs} from "../middlewares/AuthenticationMWs";
export class GalleryRouter{
constructor(private app){
this.addDirectoryList();
this.addGetImageThumbnail();
this.addGetImage();
this.addSearch();
this.addAutoComplete();
}
private addDirectoryList() {
this.app.get("/api/gallery/:directory",
AuthenticationMWs.authenticate
//TODO: implement
);
};
private addGetImage() {
this.app.get("/api/gallery/:directory/:image",
AuthenticationMWs.authenticate
//TODO: implement
);
};
private addGetImageThumbnail() {
this.app.get("/api/gallery/:directory/:image/thumbnail",
AuthenticationMWs.authenticate
//TODO: implement
);
};
private addSearch() {
this.app.get("/api/gallery/search",
AuthenticationMWs.authenticate
//TODO: implement
);
};
private addAutoComplete() {
this.app.get("/api/gallery/autocomplete",
AuthenticationMWs.authenticate
//TODO: implement
);
};
}

View File

@ -2,12 +2,18 @@
import * as _express from 'express';
import * as path from 'path';
import * as _path from 'path';
export class PublicRouter{
constructor(private app){
this.app.use(_express.static(path.resolve(__dirname, './../../frontend')));
this.app.use('/node_modules',_express.static(path.resolve(__dirname, './../../node_modules')));
this.app.use(_express.static(_path.resolve(__dirname, './../../frontend')));
this.app.use('/node_modules',_express.static(_path.resolve(__dirname, './../../node_modules')));
var renderIndex = (req: _express.Request, res: _express.Response) => {
res.sendFile(_path.resolve(__dirname, './../frontend/index.html'));
};
this.app.get(['/login',"/gallery"], renderIndex);
}

View File

@ -0,0 +1,33 @@
///<reference path="../../typings/main.d.ts"/>
import {AuthenticationMWs} from "../middlewares/AuthenticationMWs";
import {UserRoles} from "../../common/entities/User";
export class AdminRouter{
constructor(private app) {
this.addGetSharing();
this.addUpdateSharing();
}
private addGetSharing() {
this.app.get("/api/share/:directory",
AuthenticationMWs.authenticate,
AuthenticationMWs.authorise(UserRoles.User)
//TODO: implement
);
};
private addUpdateSharing() {
this.app.update("/api/share/:directory",
AuthenticationMWs.authenticate,
AuthenticationMWs.authorise(UserRoles.User)
//TODO: implement
);
};
}

View File

@ -1,19 +1,78 @@
///<reference path="../../typings/main.d.ts"/>
import {UserMWs} from "../middlewares/UserMWs";
import {UserRoles} from "../../common/entities/User";
import {AuthenticationMWs} from "../middlewares/AuthenticationMWs";
import {UserRequestConstrainsMWs} from "../middlewares/UserRequestConstrainsMWs";
export class UserRouter{
constructor(private app){
this.initLogin();
this.addLogin();
this.addChangePassword();
this.addCreateUser();
this.addDeleteUser();
this.addListUsers();
this.addChangeRole();
}
private initLogin() {
this.app.post("/api/login",
UserMWs.inverseAuthenticate,
UserMWs.login,
UserMWs.renderUser
private addLogin() {
this.app.post("/api/user/login",
AuthenticationMWs.inverseAuthenticate,
AuthenticationMWs.login,
AuthenticationMWs.renderUser
);
};
private addChangePassword() {
this.app.update("/api/user/:id/password",
AuthenticationMWs.authenticate,
UserRequestConstrainsMWs.forceSelfRequest,
UserMWs.changePassword,
UserMWs.renderOK
);
};
private addCreateUser() {
this.app.put("/api/user",
AuthenticationMWs.authenticate,
AuthenticationMWs.authorise(UserRoles.Admin),
UserMWs.createUser,
UserMWs.renderOK
);
};
private addDeleteUser() {
this.app.delete("/api/user/:id",
AuthenticationMWs.authenticate,
AuthenticationMWs.authorise(UserRoles.Admin),
UserRequestConstrainsMWs.notSelfRequest,
UserMWs.deleteUser,
UserMWs.renderOK
);
};
private addListUsers() {
this.app.post("/api/user/list",
AuthenticationMWs.authenticate,
AuthenticationMWs.authorise(UserRoles.Admin),
UserMWs.listUsers
);
};
private addChangeRole() {
this.app.update("/api/user/:id/role",
AuthenticationMWs.authenticate,
AuthenticationMWs.authorise(UserRoles.Admin),
UserRequestConstrainsMWs.notSelfRequestOr2Admins,
UserMWs.changeRole,
UserMWs.renderOK
);
};
}

View File

@ -4,9 +4,10 @@ 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";
import {GalleryRouter} from "./routes/GalleryRouter";
import {AdminRouter} from "./routes/AdminRouter";
export class Server {
@ -42,12 +43,10 @@ export class Server {
new PublicRouter(this.app);
new UserRouter(this.app);
new GalleryRouter(this.app);
new AdminRouter(this.app);
var renderIndex = (req: _express.Request, res: _express.Response) => {
res.sendFile(_path.resolve(__dirname, './../frontend/index.html'));
};
this.app.get(['/login',"/gallery"], renderIndex);
// Get port from environment and store in Express.

View File

@ -1,7 +1,16 @@
export enum ErrorCodes{
NOT_AUTHENTICATED,
ALREADY_AUTHENTICATED
ALREADY_AUTHENTICATED,
NOT_AUTHORISED,
CREDENTIAL_NOT_FOUND,
USER_CREATION_ERROR,
GENERAL_ERROR
}
export class Error{

View File

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

View File

@ -0,0 +1,8 @@
import {UserModificationRequest} from "./UserModificationRequest";
export class PasswordChangeRequest extends UserModificationRequest {
constructor(id:number, public oldPassword:string, public newPassword:string) {
super(id);
}
}

View File

@ -1,3 +1,11 @@
export enum UserRoles{
Guest = 1,
User = 2,
Admin = 3,
Developer = 4
}
export class User {
constructor(public name?:string,public email?:string, public password?:string){}
constructor(public id?:number,public name?:string,public email?:string, public password?:string, public role?:UserRoles){}
}

View File

@ -0,0 +1,3 @@
export class UserModificationRequest{
constructor(public id:number){}
}

View File

@ -11,19 +11,36 @@ export class NetworkService{
constructor(protected _http:Http){
}
protected postJson(url:string, data:any = {}){
private callJson(method:string, 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)
return this._http['method'](this._baseUrl+url, body, options)
.toPromise()
.then(res => <Message<any>> res.json())
.catch(NetworkService.handleError);
}
protected postJson(url:string, data:any = {}){
return this.callJson("post",url,data);
}
protected putJson(url:string, data:any = {}){
return this.callJson("put",url,data);
}
protected getJson(url:string, data:any = {}){
return this.callJson("get",url,data);
}
protected updateJson(url:string, data:any = {}){
return this.callJson("update",url,data);
}
protected deleteJson(url:string, data:any = {}){
return this.callJson("delete",url,data);
}
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

View File

@ -16,7 +16,7 @@ export class UserService extends NetworkService{
public login(credential:LoginCredential){
return this.postJson("/login",credential);
return this.postJson("/user/login",credential);
}