Skip to content

Commit 55cd403

Browse files
committed
first commit
0 parents  commit 55cd403

27 files changed

+2983
-0
lines changed

.gitignore

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
# See https://help.github.com/ignore-files/ for more about ignoring files.
2+
3+
# dependencies
4+
/node_modules
5+
6+
# misc
7+
.DS_Store
8+
.env
9+
.env.local
10+
.env.development.local
11+
.env.test.local
12+
.env.production.local
13+
14+
*.csv
15+
*.dat
16+
*.iml
17+
*.log
18+
*.out
19+
*.pid
20+
*.seed
21+
*.sublime-*
22+
.vscode
23+
*.swo
24+
*.swp
25+
*.tgz
26+
*.xml
27+
.vscode
28+
.idea
29+
.project
30+
.strong-pm
31+
coverage
32+
npm-debug.log*
33+
yarn-debug.log*
34+
yarn-error.log*

Config/Constants.js

Lines changed: 149 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,149 @@
1+
'use strict';
2+
3+
const swaggerDefaultResponseMessages = [
4+
{ code: 200, message: 'OK' },
5+
{ code: 400, message: 'Bad Request' },
6+
{ code: 401, message: 'Unauthorized' },
7+
{ code: 404, message: 'Data Not Found' },
8+
{ code: 500, message: 'Internal Server Error' }
9+
];
10+
11+
const STATUS_MSG = {
12+
ERROR: {
13+
INVALID_USER_PASS: {
14+
statusCode: 401,
15+
type: 'INVALID_USER_PASS',
16+
customMessage: 'Invalid username or password'
17+
},
18+
SOCIAL_LOGIN_FAILED: {
19+
statusCode: 401,
20+
type: 'SOCIAL_LOGIN_FAILED',
21+
customMessage: 'Login Failed! Please try again.'
22+
},
23+
INCORRECT_PASSWORD: {
24+
statusCode: 401,
25+
customMessage: 'Incorrect Password',
26+
type: 'INCORRECT_PASSWORD'
27+
},
28+
ACCESS_DENIED: {
29+
statusCode: 401,
30+
customMessage: 'You do not have permission for this API',
31+
type: 'ACCESS_DENIED'
32+
},
33+
DUPLICATE: {
34+
statusCode: 400,
35+
customMessage: 'Duplicate Entry',
36+
type: 'DUPLICATE'
37+
},
38+
DB_ERROR: {
39+
statusCode: 400,
40+
customMessage: 'DB Error',
41+
type: 'DB_ERROR'
42+
},
43+
INVALID_ID: {
44+
statusCode: 400,
45+
customMessage: 'Invalid Id Provided : ',
46+
type: 'INVALID_ID'
47+
},
48+
APP_ERROR: {
49+
statusCode: 400,
50+
customMessage: 'Application Error',
51+
type: 'APP_ERROR'
52+
},
53+
IMP_ERROR: {
54+
statusCode: 500,
55+
customMessage: 'Implementation Error',
56+
type: 'IMP_ERROR'
57+
},
58+
INVALID_TOKEN: {
59+
statusCode: 401,
60+
customMessage: 'Invalid token provided',
61+
type: 'INVALID_TOKEN'
62+
},
63+
EMAIL_NOT_VERIFIED: {
64+
statusCode: 401,
65+
customMessage: 'Your Email address is not verified.',
66+
type: 'EMAIL_NOT_VERIFIED'
67+
},
68+
EMAIL_NOT_EXIST: {
69+
statusCode: 400,
70+
customMessage: 'Email address does not exist.',
71+
type: 'EMAIL_NOT_EXIST'
72+
},
73+
ROLE_NOT_EXIST: {
74+
statusCode: 400,
75+
customMessage: 'Role does not exist',
76+
type: 'ROLE_NOT_EXIST'
77+
},
78+
TOKEN_NOT_VERIFIED: {
79+
statusCode: 400,
80+
customMessage: 'Token is not verified.',
81+
type: 'TOKEN_NOT_VERIFIED'
82+
},
83+
PASSWORD_NOT_MATCHED: {
84+
statusCode: 400,
85+
customMessage: 'Password and Confirm Password are not same.',
86+
type: 'PASSWORD_NOT_MATCHED'
87+
},
88+
OLD_AND_NEW_PASSWORD_SHOULD_NOT_SAME: {
89+
statusCode: 400,
90+
customMessage: 'Old Password and New Password should not same.',
91+
type: 'OLD_AND_NEW_PASSWORD_SHOULD_NOT_SAME'
92+
}
93+
},
94+
SUCCESS: {
95+
CREATED: {
96+
statusCode: 201,
97+
customMessage: 'Created Successfully',
98+
type: 'CREATED'
99+
},
100+
DEFAULT: {
101+
statusCode: 200,
102+
customMessage: 'Success',
103+
type: 'DEFAULT'
104+
},
105+
UPDATED: {
106+
statusCode: 200,
107+
customMessage: 'Updated Successfully',
108+
type: 'UPDATED'
109+
},
110+
LOGOUT: {
111+
statusCode: 200,
112+
customMessage: 'Logged Out Successfully',
113+
type: 'LOGOUT'
114+
},
115+
DELETED: {
116+
statusCode: 200,
117+
customMessage: 'Deleted Successfully',
118+
type: 'DELETED'
119+
},
120+
FORGOT_PASSWORD_MAIL_SENT: {
121+
statusCode: 200,
122+
customMessage: 'Forgot password request initiated, check your mail.',
123+
type: 'MAIL_SENT'
124+
},
125+
PASSWORD_CHANGED: {
126+
statusCode: 200,
127+
customMessage: 'Password Updated Successfully.',
128+
type: 'PASSWORD_CHANGED'
129+
},
130+
AUTHENTICATED: {
131+
statusCode: 200,
132+
customMessage: 'User is authenticated',
133+
type: 'AUTHENTICATED'
134+
}
135+
}
136+
};
137+
138+
const Constants = {
139+
SERVER,
140+
STATUS_MSG,
141+
swaggerDefaultResponseMessages,
142+
notificationMessages,
143+
hashingSecret,
144+
defaultDistanceForRestaurantSearch,
145+
userRoles,
146+
serverUser
147+
};
148+
149+
module.exports = Constants;

Config/DbConfig.js

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
'use strict';
2+
3+
const mongoURL = 'mongodb://localhost/stackoverflow';
4+
5+
const mongo = {
6+
URI: mongoURL,
7+
port: 27017
8+
};
9+
10+
module.exports = {
11+
mongo
12+
};

Config/ServerConfig.js

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
'use strict';
2+
3+
// Normalize a port into a number, string, or false.
4+
const normalizePort = (val) => {
5+
const port = parseInt(val, 10);
6+
7+
if (isNaN(port)) {
8+
// named pipe
9+
return val;
10+
}
11+
12+
if (port >= 0) {
13+
// port number
14+
return port;
15+
}
16+
17+
return false;
18+
};
19+
20+
const server = {
21+
host: process.env.HOST || '0.0.0.0',
22+
port: normalizePort(process.env.PORT || '3000')
23+
};
24+
25+
const swaggerOptions = {
26+
info: {
27+
title: 'Stackoverflow Wrapper API Documentation',
28+
version: '1.0.0',
29+
},
30+
grouping: 'tags',
31+
sortTags: 'name',
32+
expanded: 'none',
33+
securityDefinitions: {
34+
Bearer: {
35+
type: 'apiKey',
36+
name: 'Authorization',
37+
in: 'header',
38+
// 'x-keyPrefix': 'Bearer '
39+
}
40+
},
41+
security: [{ 'Bearer': [] }],
42+
jsonPath: '/swagger.json',
43+
basePath: '/api',
44+
documentationPath: '/explorer',
45+
swaggerUI: false,
46+
sortEndpoints: 'method'
47+
};
48+
49+
if (process.env.NODE_ENV && process.env.NODE_ENV === 'production') {
50+
swaggerOptions.host = `${server.host}:${server.port}`;
51+
}
52+
53+
module.exports = {
54+
server,
55+
swaggerOptions,
56+
};

Config/index.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
'use strict';
2+
3+
module.exports = {
4+
ServerConfig: require('./ServerConfig'),
5+
DbConfig: require('./DbConfig'),
6+
Constants: require('./Constants')
7+
};

Controllers/QuestionController.js

Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
'use strict';
2+
3+
const CONFIG = require('../Config');
4+
const Services = require('../Services');
5+
const { StackExchangeService } = require('../Lib');
6+
7+
const fetchAndStoreQuestions = async (request) => {
8+
if (request.query.fromDate) {
9+
const fromDate = typeof (request.query.fromDate) === 'object'
10+
&& Date.parse(request.query.fromDate) !== NaN ? Date.parse(request.query.fromDate) : false;
11+
if (!fromDate) return {
12+
statusCode: 400,
13+
customMessage: 'Make sure you are passing proper date in fromData parameter',
14+
type: 'DATA_ERROR'
15+
}
16+
}
17+
if (request.query.toDate) {
18+
const toDate = typeof (request.query.toDate) === 'object'
19+
&& Date.parse(request.query.toDate) !== NaN ? Date.parse(request.query.toDate) : false;
20+
if (!toDate) return {
21+
statusCode: 400,
22+
customMessage: 'Make sure you are passing proper date in toData parameter',
23+
type: 'DATA_ERROR'
24+
}
25+
}
26+
27+
let questionsList = [];
28+
try {
29+
questionsList = await StackExchangeService.fetchQuestions(request.query);
30+
} catch (error) {
31+
throw error;
32+
}
33+
34+
storeQuestionsInDB(questionsList, request.query.site);
35+
36+
return questionsList;
37+
};
38+
39+
const storeQuestionsInDB = async (questions, site) => {
40+
const questionList = [];
41+
for (let item of questions) {
42+
questionList.push({
43+
title: item.title,
44+
que_id: item.question_id,
45+
link: item.link,
46+
body: item.body,
47+
tags: item.tags,
48+
answer_count: item.answer_count,
49+
view_count: item.view_count,
50+
creation_date: item.creation_date,
51+
owner: {
52+
user_id: item.owner.user_id,
53+
reputation: item.owner.reputation,
54+
profile_image: item.owner.profile_image,
55+
display_name: item.owner.display_name,
56+
link: item.owner.link
57+
},
58+
site: site
59+
});
60+
}
61+
62+
try {
63+
await Services.Questions.insertMany(questionList);
64+
} catch (error) {
65+
throw error;
66+
}
67+
};
68+
69+
const getQuestions = async (request) => {
70+
let questions = [];
71+
const criteria = {
72+
site: request.query.site
73+
};
74+
const options = {
75+
limit: request.query.limit || 0,
76+
skip: request.query.skip || 0
77+
};
78+
try {
79+
questions = await Services.Questions.find(criteria, {}, options, {});
80+
} catch (err) {
81+
throw err;
82+
}
83+
return questions;
84+
};
85+
86+
const getAnswers = async (request) => {
87+
if (request.query.fromDate) {
88+
const fromDate = typeof (request.query.fromDate) === 'object'
89+
&& Date.parse(request.query.fromDate) !== NaN ? Date.parse(request.query.fromDate) : false;
90+
if (!fromDate) return {
91+
statusCode: 400,
92+
customMessage: 'Make sure you are passing proper date in fromData parameter',
93+
type: 'DATA_ERROR'
94+
}
95+
}
96+
if (request.query.toDate) {
97+
const toDate = typeof (request.query.toDate) === 'object'
98+
&& Date.parse(request.query.toDate) !== NaN ? Date.parse(request.query.toDate) : false;
99+
if (!toDate) return {
100+
statusCode: 400,
101+
customMessage: 'Make sure you are passing proper date in toData parameter',
102+
type: 'DATA_ERROR'
103+
}
104+
}
105+
106+
const data = request.query;
107+
data.queId = request.params.queId;
108+
109+
let answersList = [];
110+
try {
111+
answersList = await StackExchangeService.fetchAnswers(request.query);
112+
} catch (error) {
113+
throw error;
114+
}
115+
return answersList;
116+
};
117+
118+
module.exports = {
119+
fetchAndStoreQuestions,
120+
getQuestions,
121+
getAnswers
122+
};

0 commit comments

Comments
 (0)