Skip to content

Commit

Permalink
Revise backend auth (#53)
Browse files Browse the repository at this point in the history
* dev: fix account endpoints

* fix: fix isAccountant casting

* dev: fix goal endpoints

* dev: fix transaction/plaid/stripe/report endpoints

* fix: fix updateTransaction parameters
  • Loading branch information
nekopudding authored Jul 4, 2022
1 parent ba174be commit 04f7904
Show file tree
Hide file tree
Showing 14 changed files with 222 additions and 351 deletions.
93 changes: 34 additions & 59 deletions server/src/main_modules/accounts/account-routes.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,103 +3,78 @@ const { getDefinedFields } = require.main.require("./utils/get-defined-fields");
const { fieldsAreNotNull } = require("../../utils/get-defined-fields");
const { generateToken, authenticate } = require("./account-auth");
const { createAccount, findAccountById, updateProfile, createReview, deleteAccount, createSubscription, updateSubscription } = require("./account-store");
const { Account } = require('./models');

const _ = require.main.require('./utils/tests/model-samples')

module.exports = function(app) {
app.route('/accounts')
.post((req,res,next) => {
.post(async (req,res,next) => {
const df = getDefinedFields(req.query);
const {firstname,lastname,email,age,profession,isAccountant} = df;
if (!fieldsAreNotNull({firstname,lastname,email,age,profession,isAccountant})) {
const {accountId,avatar,firstname,lastname,email,age,profession,isAccountant} = df;
if (!fieldsAreNotNull({accountId,firstname,lastname,email,age,profession,isAccountant})) {
return next(new Error('missing params'));
}
createAccount({
profile: { firstname,lastname,email,age,profession},
isAccountant: isAccountant
await createAccount({
accountId,
profile: { avatar,firstname,lastname,email,age,profession},
isAccountant
}, (err,newAccount) => {
if (err) { return next(err); }
res.json({
token: generateToken(newAccount.id), //will be changed so frontend generates token
data: newAccount
});
res.json(newAccount)

})
});

app.route('/accounts/:accountId')
.get((req,res,next) => {
const {accountId} = req.params;
const {token} = req.query;
authenticate(token,accountId, (err,foundAccount) => {
if (err) return next(err)
if (!foundAccount) return next(new Error('account not found'));
return res.json(foundAccount);
});
})
.put((req,res,next) => {
const {accountId} = req.params;
const {token} = req.query;

authenticate(token,accountId, (err,foundAccount) => {
Account.findOne({accountId: req.params.accountId},(err,account) => {
if (err) return next(err);
if (!foundAccount) return next(new Error('account not found'))
updateProfile(foundAccount.id,req.query, (err,foundAccount) => {
if (err) return next(err);
return res.json(foundAccount)
})
if (!account) return res.status(404).end('account not found');
return res.json(account);
})
})
.delete((req,res,next) => {
const {accountId} = req.params;
const {token} = req.query;
authenticate(token,accountId, (err,foundAccount) => {
.put((req,res,next) => {
updateProfile(req.params.accountId,req.query, (err,account) => {
if (err) return next(err);
if(!foundAccount) return next(new Error('account not found'));
deleteAccount(foundAccount.id, (err) => {
if (err) return next(err);
return res.end('account deleted');
})
if (!account) return res.status(404).end('account not found');
return res.json(account)
})
})
.delete(async (req,res,next) => {
const deletedAccount = await deleteAccount(req.params.accountId);
if (!deletedAccount) return res.status(404).end('account not found')
return res.end('account deleted');
})

app.route('/reviews/:accountantId')
.post((req,res,next) => {
const {accountantId} = req.params;
const df = getDefinedFields({accountantId,...req.query});
const {token,authorId,date,rating,title,content} = df;
if (!fieldsAreNotNull({authorId,date,rating,title,token})) { return next(new Error('missing params'))}
authenticate(token,authorId, (err,foundAccount) => {
const df = getDefinedFields(req.query);
const {authorId,date,rating,title,content} = df;
if (!fieldsAreNotNull({authorId,date,rating,title})) { return next(new Error('missing params'))}
createReview(accountantId,df, (err,account) => {
if (err) return next(err);
if (!foundAccount) return next(new Error('accountant not found'))
createReview(foundAccount.id,{accountId: accountantId,...df}, (err,foundAccount) => {
if (err) return next(err);
return res.json(foundAccount)
})
if (!account) return res.status(404).end('account not found');
return res.json(account)
})
})
app.route('/subscription/:accountId')
.post((req,res,next) => {
const {accountId} = req.params;
const {token, subscriptionDate,expiryDate} = req.query;
authenticate(token,accountId, (err,foundAccount) => {
createSubscription(accountId,req.query, (err,account) => {
if (err) return next(err);
if (!foundAccount) return next(new Error('account not found'))
createSubscription(foundAccount.id,req.query, (err,foundAccount) => {
if (err) return next(err);
return res.json(foundAccount)
})
if (!account) return res.status(404).end('account not found');
return res.json(account)
})
})
.put((req,res,next) => {
const {accountId} = req.params;
const {token, expiryDate} = req.query;
authenticate(token,accountId, (err,foundAccount) => {
updateSubscription(accountId,req.query, (err,account) => {
if (err) return next(err);
if (!foundAccount) return next(new Error('account not found'))
updateSubscription(foundAccount.id,req.query, (err,foundAccount) => {
if (err) return next(err);
return res.json(foundAccount)
})
if (!account) return res.status(404).end('account not found');
return res.json(account)
})
})
}
79 changes: 39 additions & 40 deletions server/src/main_modules/accounts/account-store.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,82 +19,81 @@ module.exports = {
* - @param {Error} err - potential error thrown by mongoose
* - @param {Account} createdAccount - the account that was successfully created
*/
createAccount: (data,callback) => {
const account = new Account({...data});
createAccount: async (data,callback) => {
const foundAccount = await Account.findOne({accountId: data.accountId});
if (foundAccount) return callback(new Error('account already exists'),foundAccount);

const isAccountant = (data.isAccountant === 'true');
const account = new Account({...data, isAccountant}); //cast to boolean as http can only send string

account.save((err,createdAccount) => {
const userTransaction = new UserTransaction({userId:createdAccount.id});
const userGoal = new UserGoal({userId: createdAccount.id});
const userReport = new UserReport({userId: createdAccount.id})
userTransaction.save();
userGoal.save();
userReport.save();
callback(err,createdAccount);
account.save((err,account) => {
if (!isAccountant && !err) {
console.log('creating goals/transaction/reports document')
const userTransaction = new UserTransaction({userId: data.accountId});
const userGoal = new UserGoal({userId: data.accountId});
const userReport = new UserReport({userId: data.accountId})
userTransaction.save(err => err && console.log(err));
userGoal.save(err => err && console.log(err));
userReport.save(err => err && console.log(err));
}

callback(err,account);
});
},
/**
* Wrapper for mongoose findById.
* @param {string} id
* @param {function} callback - run on query result
* - @param {Error} err - error thrown by mongoose
* - @param {Account} foundAccount - account found by query
*/
findAccountById:(id,callback) => {
Account.findById(id, (err,foundAccount) => callback(err,foundAccount));
},
/**
* Wrapper for mongoose findByIdAndUpdate
* Wrapper for mongoose findOneAndUpdate
* @param {string} id
* @param {object} data - must contain fields: firsname,lastname,email,age,profession,hasAccountant
* @param {*} callback
*/
updateProfile:(id,data,callback) => {
const {avatar,firstname,lastname,email,age,profession,hasAccountant} = data;
const {avatar,firstname,lastname,email,age,profession} = data;

const fieldsToUpdate = parseProfileData({avatar,firstname,lastname,email,age,profession,hasAccountant})
Account.findByIdAndUpdate(id,{$set: fieldsToUpdate},
const fieldsToUpdate = parseProfileData({avatar,firstname,lastname,email,age,profession})
Account.findOneAndUpdate({accountId: id},{$set: fieldsToUpdate},
{returnDocument: 'after'},
(err,foundAccount) => {
if(err) console.log(err);
callback(err,foundAccount)
(err,account) => {
callback(err,account)
}
);
},
deleteAccount: (id,callback) => {
Account.deleteOne({id: id}, (err) => {
if (err) console.log(err);
callback(err);
});
deleteAccount: async (id,callback) => {
const account = await Account.findOne({accountId: id});
await Account.deleteOne({accountId: id});
await UserGoal.deleteOne({userId: id})
await UserTransaction.deleteOne({userId: id});
await UserReport.deleteOne({userId:id});
return account;
},

createReview: (accountId,data,callback) => {
createReview: (accountantId,data,callback) => {
const {authorId,date,rating,title,content} = data;

const newReview = {authorId,date,rating,title,content};

Account.findByIdAndUpdate(accountId,{$push: {reviews: newReview}},
Account.findOneAndUpdate({accountId: accountantId},{$push: {reviews: newReview}},
{returnDocument: 'after'},
(err,foundAccount) => {
(err,account) => {
if(err) console.log(err);
callback(err,foundAccount)
callback(err,account)
}
);
},
createSubscription: (accountId,data,callback) => {
createSubscription: (id,data,callback) => {
const {subscriptionDate,expiryDate} = data;
const fieldsToUpdate = parseSubscriptionData({subscriptionDate,expiryDate})
Account.findByIdAndUpdate(accountId,{$set: fieldsToUpdate},
Account.findOneAndUpdate({accountId: id},{$set: fieldsToUpdate},
{returnDocument: 'after'},
(err,foundAccount) => {
if(err) console.log(err);
callback(err,foundAccount)
}
);
},
updateSubscription: (accountId,data,callback) => {
updateSubscription: (id,data,callback) => {
const {expiryDate} = data;
const fieldsToUpdate = parseSubscriptionData({expiryDate})
Account.findByIdAndUpdate(accountId,{$set: fieldsToUpdate},
Account.findOneAndUpdate({accountId: id},{$set: fieldsToUpdate},
{returnDocument: 'after'},
(err,foundAccount) => {
if(err) console.log(err);
Expand Down
5 changes: 2 additions & 3 deletions server/src/main_modules/accounts/models.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,11 @@ const accountDB = mongoose.createConnection('mongodb://localhost/accountDB')

const {r_string,r_bool,r_num, r_date} = require.main.require('./utils/types/mongo-required')
const accountSchema = new mongoose.Schema({
accountId: r_string,
profile: {type: profileSchema, required: true},
isAccountant: r_bool,
isAuthenticated: {...r_bool, default: false},
authenticateExpiryDate: {...r_date, default: '2022'},
reviews: {type: [reviewSchema], default: []},
subscription: subscriptionSchema,
subscription: {type: subscriptionSchema, default: {subscriptionDate: '2022', expiryDate: '2022'}},
stripeCustomerId: String,
stripeSubscriptionId: String
})
Expand Down
7 changes: 2 additions & 5 deletions server/src/main_modules/accounts/profile/profile.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,6 @@ const profileSchema = new mongoose.Schema({
email: r_string,
age: r_num,
profession: r_string,
numberOfClients: Number,
hasAccountant: {...r_bool, default: false},
})

/**
Expand All @@ -19,8 +17,8 @@ const profileSchema = new mongoose.Schema({
* @param {object} fields - some or all of the fields in the profile schema
*/
function parseProfileData(fields) {
const {avatar,firstname,lastname,email,age,profession,hasAccountant} = fields;
const df = getDefinedFields({avatar,firstname,lastname,email,age,profession,hasAccountant});
const {avatar,firstname,lastname,email,age,profession} = fields;
const df = getDefinedFields({avatar,firstname,lastname,email,age,profession});

const fieldsToUpdate = {
...(df.avatar && {"profile.avatar": df.avatar}),
Expand All @@ -29,7 +27,6 @@ function parseProfileData(fields) {
...(df.email && {"profile.email": df.email}),
...(df.age && {"profile.age": df.age}),
...(df.profession && {"profile.profession": df.profession}),
...(df.hasAccountant && {"profile.hasAccountant": df.hasAccountant}),
}
return fieldsToUpdate;
}
Expand Down
Loading

0 comments on commit 04f7904

Please sign in to comment.