mirror of
https://bitbucket.org/tagfer_team/tagfer-server.git
synced 2025-12-25 03:37:38 +00:00
Merge branch 'T-954157790482088-User-Can-Create-A-Profile'
This commit is contained in:
commit
b3e4dfb3ab
1408
package-lock.json
generated
1408
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -31,11 +31,13 @@
|
||||
}
|
||||
},
|
||||
"dbPath": {
|
||||
"users": "users"
|
||||
"users": "users",
|
||||
"profiles": "profiles"
|
||||
},
|
||||
"loki" : {
|
||||
"verificationTTL": 300000,
|
||||
"verificationTTLClear": 1800000
|
||||
}
|
||||
},
|
||||
"defaultProfileName": "Business Profile"
|
||||
|
||||
}
|
||||
@ -1,4 +1,5 @@
|
||||
module.exports = {
|
||||
//Auth erors
|
||||
AUTH_INVALID_EMAIL: 'auth/invalid-email',
|
||||
AUTH_INVALID_PHONE_NUMBER: 'auth/invalid-phone-number',
|
||||
AUTH_USER_NOT_FOUND: 'auth/user-not-found',
|
||||
@ -8,8 +9,17 @@ module.exports = {
|
||||
AUTH_PHONE_ALREADY_EXISTS: 'auth/phone-number-already-exists',
|
||||
AUTH_PHONE_NOT_CACHED: 'auth/phone-number-not-cached',
|
||||
AUTH_VERIFICATION_CODE_MISMATCH: 'auth/phone-verification-code-mismatch',
|
||||
AUTH_INVALID_SESSION_ID: 'auth/invalid-session-id',
|
||||
AUTH_UNAUTHORIZED_ACCESS: 'auth/unauthorized-access-into-api',
|
||||
AUTH_UNABLE_TO_EXTRACT_SESSION_ID_FROM_AUTH_HEADER: 'auth/unable-to-extract-session-id-from-auth-header',
|
||||
//App Errors
|
||||
APP_NETWORK_ERROR: 'app/network-error',
|
||||
APP_NETWORK_TIMEOUT: 'app/network-timeout',
|
||||
APP_UNABLE_TO_PARSE_RESPONSE: 'app/unable-to-parse-response',
|
||||
MISSING_BODY_ATTRIBUTES: 'request/missing-body-attributes'
|
||||
APP_FIREBASE_DATABASE_ERROR: 'app/firebase-database-error',
|
||||
//Request Errors
|
||||
MISSING_BODY_ATTRIBUTES: 'request/missing-body-attributes',
|
||||
//Profile Errors
|
||||
MAX_NUMBER_OF_PROFILES_REACHED: 'profile/max-number-of-profiles-are-being-used',
|
||||
NO_PROFILE_FOUND_FOR_NUMBER: 'profile/no-profile-found-for-number'
|
||||
};
|
||||
@ -1,5 +1,6 @@
|
||||
const AuthHandlers = require('../ups/auth/handlers');
|
||||
const UserHandlers = require('../ups/users/handlers');
|
||||
const ProfileHandlers = require('../ups/profiles/handlers');
|
||||
|
||||
/**
|
||||
* Main router for our application, include all routes here. No logic should be added in this file.
|
||||
@ -17,6 +18,9 @@ function router(app) {
|
||||
|
||||
// Users Endpoints
|
||||
app.get('/users/by/phone', UserHandlers.findNetworkByPhone);
|
||||
|
||||
// Profile Endpoints
|
||||
app.post('/profiles/:profileNumber', ProfileHandlers.updateUserProfile);
|
||||
}
|
||||
|
||||
module.exports = router;
|
||||
@ -106,6 +106,22 @@ function createNewSessionId(tagferId) {
|
||||
return sessionId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the loki session containg the user's tagferId on the server
|
||||
* @param {string} id
|
||||
* @returns {object} Loki Session object containg user's tagferId or error if id param passed is invalid
|
||||
* @throws AUTH_INVALID_SESSION_ID
|
||||
*/
|
||||
function getSession(id) {
|
||||
const sessions = loki.getCollection("sessions");
|
||||
var session = sessions.by('id', id)
|
||||
if (session) {
|
||||
return session;
|
||||
} else {
|
||||
throw errors.AUTH_INVALID_SESSION_ID;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create new verification code for the phone number
|
||||
*/
|
||||
@ -166,6 +182,7 @@ module.exports = {
|
||||
signinWithEmail,
|
||||
createNewUser,
|
||||
createNewSessionId,
|
||||
getSession,
|
||||
resetPassword
|
||||
};
|
||||
|
||||
|
||||
@ -1,6 +1,9 @@
|
||||
const dao = require('./dao');
|
||||
const authDao = require('./dao');
|
||||
const profileDao = require('./../profiles/dao');
|
||||
const utils = require('../utils/utils');
|
||||
const errors = require('../../config/errors');
|
||||
const appConfig = require('../../config/app.json');
|
||||
const http = require('../../config/http');
|
||||
|
||||
// Handlers
|
||||
/**
|
||||
@ -14,7 +17,7 @@ function doesAttributeExist(req, res) {
|
||||
if (!utils.isAppSecretValid(req,res)) {
|
||||
return;
|
||||
}
|
||||
var promise = email? dao.doesEmailExist(email) : dao.doesTagferIdExist(tagferId.toLowerCase());
|
||||
var promise = email? authDao.doesEmailExist(email) : authDao.doesTagferIdExist(tagferId.toLowerCase());
|
||||
|
||||
promise.then((result) => res.json({ result }) ).catch(error => res.json(error));
|
||||
}
|
||||
@ -32,9 +35,9 @@ function sendPhoneCode(req, res) {
|
||||
}
|
||||
|
||||
const phoneNumber = req.body.phoneNumber;
|
||||
dao.doesPhoneExist(phoneNumber).then( result => {
|
||||
authDao.doesPhoneExist(phoneNumber).then( result => {
|
||||
if (result === false) {
|
||||
dao.sendVerificationCode(phoneNumber, status => res.json(status));
|
||||
authDao.sendVerificationCode(phoneNumber, status => res.json(status));
|
||||
} else{
|
||||
throw { error: errors.AUTH_PHONE_ALREADY_EXISTS };
|
||||
}
|
||||
@ -54,7 +57,7 @@ function verifyPhoneCode(req, res) {
|
||||
|
||||
const phoneNumber = req.body.phoneNumber;
|
||||
const code = req.body.code;
|
||||
res.json(dao.isVerificationCodeCorrect(phoneNumber, code));
|
||||
res.json(authDao.isVerificationCodeCorrect(phoneNumber, code));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -73,13 +76,13 @@ function signin(req, res) {
|
||||
var promise;
|
||||
|
||||
if (email) {
|
||||
promise = dao.signinWithEmail(email, password);
|
||||
promise = authDao.signinWithEmail(email, password);
|
||||
} else {
|
||||
promise = dao.signinWithTagferId(tagferId, password);
|
||||
promise = authDao.signinWithTagferId(tagferId, password);
|
||||
}
|
||||
|
||||
promise.then( ({ user })=> {
|
||||
const sessionId = dao.createNewSessionId(user.uid);
|
||||
const sessionId = authDao.createNewSessionId(user.uid);
|
||||
res.json({sessionId});
|
||||
}).catch(error => {
|
||||
res.json( {error: error.code} );
|
||||
@ -92,19 +95,26 @@ function signin(req, res) {
|
||||
* @param {Object} req { tagferId: String, email: String, password: String, phoneNumber: String, fullName: String }
|
||||
* @param {Object} res { sessionId: String } | { error: String }
|
||||
*/
|
||||
function signup(req, res) {
|
||||
const user = req.body;
|
||||
const verifier = () => user.tagferId && user.email && user.password && user.phoneNumber && user.fullName;
|
||||
if (!utils.isAppSecretValid(req,res) || !utils.isBodyValid(verifier, res)) {
|
||||
async function signup(req, res) {
|
||||
const {user, profile} = req.body;
|
||||
const userVerifier = () => user.tagferId && user.email && user.password && user.phoneNumber && user.fullName;
|
||||
const profileVerifier = () => profile.company && profile.company.profession && profile.company.name && profile.company.address && profile.company.number;
|
||||
|
||||
if (!utils.isAppSecretValid(req,res) || !utils.isBodyValid(userVerifier, res) || !utils.isBodyValid(profileVerifier, res)) {
|
||||
return;
|
||||
}
|
||||
|
||||
dao.createNewUser(user).then( user => {
|
||||
const sessionId = dao.createNewSessionId(user.uid);
|
||||
res.json({sessionId});
|
||||
}).catch(error => {
|
||||
res.json( {error: error.code} );
|
||||
});
|
||||
profile.name = appConfig.defaultProfileName;
|
||||
profile.email = user.email
|
||||
|
||||
try {
|
||||
await authDao.createNewUser(user);
|
||||
await profileDao.createInitialProfiles(profile, user.tagferId);
|
||||
const sessionId = authDao.createNewSessionId(user.tagferId);
|
||||
res.status(http.CREATED).json({sessionId});
|
||||
} catch (error) {
|
||||
res.status(http.BAD_REQUEST).json({error:error.code});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
28
src/ups/profiles/dao.js
Normal file
28
src/ups/profiles/dao.js
Normal file
@ -0,0 +1,28 @@
|
||||
const database = require('firebase-admin').database();
|
||||
|
||||
/**
|
||||
* Blind initializing function for a new user's default profile
|
||||
* @param {object} profileObj
|
||||
* @param {string} tagferId
|
||||
*/
|
||||
function createInitialProfiles(profileObj, tagferId) {
|
||||
//persist profile data to firebase
|
||||
return database.ref(`/profiles/${tagferId}/profile1`).set(profileObj);
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates a user profile
|
||||
* @param {object} profileObj JSON object containing all data for a profile captured from the frontend
|
||||
* @param {number} profileNumber Number used to identify which profile a user wants to update/add to if the profile slot is empty
|
||||
* @param {string} tagferId tagferId obtained by extracting from authorization header
|
||||
* @returns {Boolean} Boolean result of whether the
|
||||
*/
|
||||
function updateProfile(profileObj, profileNumber, tagferId) {
|
||||
//persist profile data to firebase
|
||||
return database.ref(`/profiles/${tagferId}/profile${profileNumber}`).set(profileObj);
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
updateProfile,
|
||||
createInitialProfiles
|
||||
};
|
||||
38
src/ups/profiles/handlers.js
Normal file
38
src/ups/profiles/handlers.js
Normal file
@ -0,0 +1,38 @@
|
||||
const profileDao = require('./dao');
|
||||
const authDao = require('../auth/dao');
|
||||
const utils = require('../utils/utils');
|
||||
const errors = require('../../config/errors');
|
||||
const http = require('../../config/http');
|
||||
const _ = require('lodash');
|
||||
|
||||
// Handlers
|
||||
/**
|
||||
* Endpoints: POST profiles/
|
||||
* Updates a profile for a user based on session stored tagferId
|
||||
* @param {Object} req
|
||||
* @param {Object} res {result: Boolean} | {error: String}
|
||||
*/
|
||||
async function updateUserProfile(req, res) {
|
||||
const profileObj = req.body;
|
||||
const profileNumber = req.params.profileNumber;
|
||||
|
||||
if (!utils.isProfileNumberValid(profileNumber, res)) {
|
||||
return;
|
||||
} else {
|
||||
const sessionId = utils.getSessionIdFromAuthHeader(req, res);
|
||||
try {
|
||||
const tagferId = authDao.getSession(sessionId).tagferId;
|
||||
profileDao.updateProfile(profileObj, profileNumber, tagferId).then( () => {
|
||||
res.status(http.CREATED).json({})
|
||||
}).catch( (error) => {
|
||||
res.status(http.INTERNAL_SERVER_ERROR).json({error: errors.APP_FIREBASE_DATABASE_ERROR})
|
||||
});
|
||||
} catch (error) {
|
||||
res.status(http.UNAUTHORIZED).json({error})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
updateUserProfile
|
||||
}
|
||||
@ -1,6 +1,7 @@
|
||||
const appConfig = require('../../config/app.json');
|
||||
const http = require('../../config/http');
|
||||
const errors = require('../../config/errors');
|
||||
const auth = require('../auth/dao');
|
||||
|
||||
/**
|
||||
* Verifies if the request is valid by checking if the request has the right app secret.
|
||||
@ -13,12 +14,22 @@ function isAppSecretValid(req, res) {
|
||||
const sysToken = appConfig.keys.appSecret;
|
||||
|
||||
if( usrToken !== sysToken) {
|
||||
res.status(http.UNAUTHORIZED).json({ error: 'Unauthorized access into api' });
|
||||
res.status(http.UNAUTHORIZED).json({ error: errors.AUTH_UNAUTHORIZED_ACCESS });
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
function getSessionIdFromAuthHeader(req, res) {
|
||||
const usrToken = req.headers.authorization;
|
||||
|
||||
if (usrToken) {
|
||||
return usrToken;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Checks if the body is valid
|
||||
* @param {Function} isValid verifier
|
||||
@ -32,7 +43,18 @@ function isBodyValid(isValid, response) {
|
||||
return true;
|
||||
}
|
||||
|
||||
function isProfileNumberValid(profileNumber, response) {
|
||||
if (profileNumber > 4 || profileNumber < 1) {
|
||||
response.status(http.BAD_REQUEST).json({error: errors.NO_PROFILE_FOUND_FOR_NUMBER});
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
isAppSecretValid,
|
||||
isBodyValid
|
||||
isBodyValid,
|
||||
getSessionIdFromAuthHeader,
|
||||
isProfileNumberValid
|
||||
};
|
||||
Loading…
x
Reference in New Issue
Block a user