Skip to content

Commit 04691f5

Browse files
committed
add Request Map
1 parent ef2b468 commit 04691f5

22 files changed

+937
-43
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,4 @@
11
*.log
22
node_modules
3+
package-lock.json
4+
yarn.lock

config/config.json

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
{
2+
"development": {
3+
"username": "vidy",
4+
"password": "password",
5+
"database": "simple_blog",
6+
"host": "127.0.0.1",
7+
"dialect": "mysql"
8+
},
9+
"test": {
10+
"username": "root",
11+
"password": null,
12+
"database": "database_test",
13+
"host": "127.0.0.1",
14+
"dialect": "mysql"
15+
},
16+
"production": {
17+
"username": "root",
18+
"password": null,
19+
"database": "database_test",
20+
"host": "127.0.0.1",
21+
"dialect": "mysql"
22+
}
23+
}

config/development.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,4 +14,5 @@
1414
"maxAge": 14400,
1515
"issuer": "vidy"
1616
}
17-
}
17+
}
18+

package.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,10 @@
2222
"pg": "7.6.0",
2323
"reflect-metadata": "0.1.12",
2424
"sequelize": "4.41.0",
25+
"sequelize-cli": "^5.3.0",
2526
"sequelize-typescript": "0.6.6",
2627
"ts-node": "7.0.1",
28+
"validate.js": "^0.12.0",
2729
"winston": "2.3.1"
2830
},
2931
"devDependencies": {
@@ -32,9 +34,7 @@
3234
"@types/express": "4.0.36",
3335
"@types/node": "8.0.17",
3436
"@types/pg": "6.1.43",
37+
"@types/winston": "^2.4.4",
3538
"typescript": "3.1.3"
36-
},
37-
"engines": {
38-
"node": "6.11.1"
3939
}
4040
}

sandbox/nodemon.json

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{
2+
"watch": ["./"],
3+
"ext": "ts",
4+
"ignore": ["src/**/*.spec.ts"],
5+
"exec": "ts-node ./test.ts"
6+
}

sandbox/test.ts

Lines changed: 175 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,175 @@
1+
import { Request } from "express";
2+
import * as validate from 'validate.js';
3+
import { request } from "http";
4+
5+
function constructObjectFromRefUrl (refUrl){
6+
console.log('refUrl', refUrl)
7+
let obj = {};
8+
let pathIndex = -1;
9+
for (let idx=0; idx<refUrl.length; idx++){
10+
const str = refUrl[idx];
11+
if(str === '/') pathIndex+=1;
12+
if(str === '/' && refUrl[idx+1] && refUrl[idx+1] === ':') {
13+
//search for '}'
14+
for(let inner=idx+2; inner<1000;inner++){
15+
const innerStr = refUrl[inner];
16+
if(innerStr === '/'){
17+
const key = refUrl.slice(idx+2, inner)
18+
obj[key] = pathIndex
19+
idx = inner;
20+
break;
21+
}
22+
}
23+
}
24+
if(str === '?') break;
25+
}
26+
return obj
27+
}
28+
29+
class ValidatorOption {
30+
required: boolean;
31+
type: Function;
32+
as?: string
33+
}
34+
35+
36+
const objToValidate = {
37+
username: 'asfd',
38+
password: '1'
39+
}
40+
41+
const SCHEMA = {
42+
username: {
43+
presence: true,
44+
exclusion: {
45+
within: ["nicklas"],
46+
message: "'%{value}' is not allowed"
47+
}
48+
},
49+
password: {
50+
presence: true,
51+
length: {
52+
minimum: 6,
53+
message: "must be at least 6 characters"
54+
}
55+
}
56+
}
57+
58+
class Test {
59+
_pathVariables:Array<[string, ValidatorOption]> = [
60+
["one", {required:true, type: String, as: "ONE"}],
61+
["two", {required:true, type: Number, as: "TWO"}],
62+
["three", {required:true, type: Boolean, as: "THREE"}],
63+
];
64+
_requestParams:Array<[string, ValidatorOption]> = [
65+
["searchBy", {required:true, type: String}],
66+
["ascending", {required:true, type: Boolean, as: "TWO"}],
67+
];
68+
_HttpPathName = '/asdf/{one}/asdf/{two}/{three}';
69+
//@ts-ignore
70+
_executeRequestParam(req:Request):{errorMessages:String[], isValid:boolean, result: {}} {
71+
const _result = {};
72+
let queryString:string = req.url.split('?')[1];
73+
if(!queryString) return {errorMessages: ['No Query String'], isValid:false, result:_result}
74+
const queryStringArr = queryString.split('&');
75+
let errorMessages = this._requestParams.map(o => {
76+
//either return one or undefined
77+
let errorMessage = ''
78+
let isFound = false;
79+
queryStringArr.forEach((query:string) => {
80+
if(isFound) return;
81+
82+
const [requestParam, option] = o;
83+
const { required, type, as} = option;
84+
const [key, value] = query.split('=');
85+
if(requestParam === key){
86+
isFound = true;
87+
if(required && !value) errorMessage = `RequestParam ${requestParam} cannot be null`
88+
if(type && (type.name === 'Boolean') && (value !== 'true' && value !== 'false')){
89+
errorMessage = `RequestParam ${requestParam} must be Boolean`
90+
} else if(!validate[`is${type.name}`](type(value))) {
91+
errorMessage = `RequestParam ${requestParam} must be ${type.name}`
92+
}
93+
94+
let typeCastValue;
95+
if(type.name === 'Boolean') {
96+
typeCastValue = (value === 'false') ? false : true;
97+
} else {
98+
typeCastValue = type(value);
99+
}
100+
101+
if(as) { _result[as] = typeCastValue }
102+
else {_result[key] = typeCastValue }
103+
}
104+
})
105+
return errorMessage;
106+
}).filter(isValid => !!isValid);
107+
108+
const isValid = errorMessages.length === 0;
109+
//@ts-ignore
110+
return {errorMessages, isValid, result:_result}
111+
}
112+
//@ts-ignore
113+
_executePathVariable(req:Request):{errorMessages:string[], isValid:boolean, result:{}}{
114+
let _result = {};
115+
const objMap = constructObjectFromRefUrl(this._HttpPathName);
116+
const path = req.url.split('//')[1].split('/').slice(1);
117+
const errorMessages = this._pathVariables.map((o)=> {
118+
//either return one or undefined
119+
let [pathname, { required, type, as}] = o;
120+
const position = objMap[pathname];
121+
let value = path[position];
122+
value = value.indexOf('?') ? value.split('?')[0] : value;
123+
const obj = {[pathname]: value};
124+
125+
if(required && !value) return `PathVariable ${pathname} cannot be null`
126+
if(type && (type.name === 'Boolean') && (value !== 'true' && value !== 'false')){
127+
return `PathVariable ${pathname} must be Boolean`
128+
} else if(!validate[`is${type.name}`](type(value))) {
129+
return `PathVariable ${pathname} must be ${type.name}`
130+
}
131+
132+
let typeCastValue;
133+
if(type.name === 'Boolean') {
134+
typeCastValue = (value === 'false') ? false : true;
135+
} else {
136+
typeCastValue = type(value);
137+
}
138+
139+
if(as) { _result[as] = typeCastValue }
140+
else {_result[pathname] = typeCastValue }
141+
return undefined
142+
143+
}).filter(isValid => !!isValid)
144+
145+
const isValid = errorMessages.length === 0;
146+
//@ts-ignore
147+
return {errorMessages, isValid, result:_result}
148+
}
149+
150+
_requestBodyOption = {
151+
schema: SCHEMA
152+
}
153+
//@ts-ignore
154+
_executeRequestBody(req:Request):{errorMessages:string[], isValid:boolean, result:{}}{
155+
const objToValidate = req.body;
156+
const schema = this._requestBodyOption.schema;
157+
let objError = {};
158+
if(schema) objError = validate(objToValidate, schema);
159+
const errorMessages = Object.keys(objError).map(key => objError[key]);
160+
const isValid = errorMessages.length === 0;
161+
return { errorMessages, isValid, result: isValid ? objToValidate : {} };
162+
}
163+
}
164+
165+
let req = {
166+
body: objToValidate,
167+
url: 'http://www.vidy.com/asdf/value1/asfd/1/true?searchBy=asdf&ascending=true'
168+
};
169+
170+
171+
//@ts-ignore
172+
// const result = new Test()._executeRequestParam(req);
173+
// const result = new Test()._executePathVariable(req);
174+
const result = new Test()._executeRequestBody(req);
175+
console.log(result)

src/Model/Person/Person.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import {hashedPassword} from '../../utils/password'
44
import PersonDetail from '../PersonDetail/PersonDetail'
55
import Asset from '../Asset/Asset'
66

7+
78
@Table({timestamps: true, tableName: "person", schema: "core"})
89
class Person extends Model<Person> {
910
@BeforeCreate
@@ -16,6 +17,7 @@ class Person extends Model<Person> {
1617

1718
@AllowNull(false) @IsEmail @Unique @Column
1819
email: string
20+
1921
@Length({min: 6, msg: 'password must be at least 6 characters'})
2022
@Column({ type: DataType.STRING, allowNull: false })
2123
password: string

src/Token/TokenUtil.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ export function validate(req:Request): Promise<TokenError|boolean>{
3939
if(!req.headers.authorization || typeof req.headers.authorization === 'object') {
4040
return resolve(TokenError.TOKEN_INVALID)
4141
}
42+
console.log(req.headers)
4243
const token:string = req.headers.authorization as string
4344
verify(token)
4445
.then(decoded => {

src/app.ts

Lines changed: 26 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -33,25 +33,29 @@ import HttpError from './Error/HttpError/HttpError';
3333
// INTERCEPT
3434
app.use((req:Request, res:Response, next) => {
3535
// Intercept here
36-
TokenUtil.validate(req)
37-
.then((validate:TokenError|boolean) => {
38-
if(validate instanceof TokenError) {
39-
res.status(400).json({message: ''})
40-
return Promise.reject(JSON.stringify(req) + validate)
41-
}
42-
return Promise.resolve(req)
43-
})
44-
.then(request => {
45-
TokenUtil.authenticate(request).then((authenticated:TokenError|boolean) => {
46-
if(authenticated instanceof TokenError) {
47-
res.status(400).json({message: ''})
48-
return Promise.reject(JSON.stringify(request) + authenticated)
49-
}
50-
return Promise.resolve(authenticated)
51-
})
52-
})
53-
.then(_ => next())
54-
.catch(logger.error)
36+
// TokenUtil.validate(req)
37+
// if(!req.headers.authorization || typeof req.headers.authorization === 'object') {
38+
// return resolve(TokenError.TOKEN_INVALID)
39+
// }
40+
// .then((validate:TokenError|boolean) => {
41+
// if(validate instanceof TokenError) {
42+
// res.status(400).json({message: ''})
43+
// return Promise.reject(JSON.stringify(req) + validate)
44+
// }
45+
// return Promise.resolve(req)
46+
// })
47+
// .then(request => {
48+
// TokenUtil.authenticate(request).then((authenticated:TokenError|boolean) => {
49+
// if(authenticated instanceof TokenError) {
50+
// res.status(400).json({message: ''})
51+
// return Promise.reject(JSON.stringify(request) + authenticated)
52+
// }
53+
// return Promise.resolve(authenticated)
54+
// })
55+
// })
56+
// .then(_ => next())
57+
// .catch(logger.error)
58+
next();
5559
})
5660

5761
// ROUTES
@@ -72,8 +76,7 @@ import HttpError from './Error/HttpError/HttpError';
7276
app.use(HttpError.handle404);
7377
app.use(HttpError.handle4xxAnd5xx);
7478
process.on('unhandledRejection', (reason) => logger.error(new Date().getTime(), reason))
75-
76-
79+
console.log(assetRoute.stack[0].route.stack[0].handle);
7780
// START
7881
app.listen(config.server.port, function () {
7982
logger.info(`server listening on port: ${config.server.port}`);
@@ -84,4 +87,5 @@ import HttpError from './Error/HttpError/HttpError';
8487
logger.info('DB MODEL' + JSON.stringify(Db_blog.models))
8588
})
8689
.catch(err => logger.error('Db_blog Unable to connect to the database:', err));
87-
});
90+
});
91+

src/controller/assetController.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ PathDetailUtil.registerRoute(getAssetUrl, 'post', Roles.User)
1111
router.post(getAssetUrl, validateToken, authorizeUser(getAssetUrl),
1212
(req:Request, res: Response, next) => {
1313
//find and check if user is the owner of the asset
14-
const
1514
})
1615

1716
const addAssetUrl = `${url}/add`

0 commit comments

Comments
 (0)