Skip to content

Commit 152bc98

Browse files
authored
Merge pull request #67 from oslabs-beta/Carter/specTest
Carter/spec test
2 parents 8531d80 + 240c528 commit 152bc98

File tree

11 files changed

+257
-133
lines changed

11 files changed

+257
-133
lines changed

server/config/passport.js

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,15 @@
1+
/** using import statements in the electron / node files breaks npm start and nodepty
2+
* - types are left in place in these files for future iteration alternate import method is required for them to function
3+
*/
4+
// import { TablePaginationUnstyledSpacerSlotProps } from "@mui/base";
5+
// import { Error } from "mongoose";
6+
// import { Authenticator, Profile } from "passport";
7+
18
const GitHubStrategy = require('passport-github2').Strategy;
29
const GoogleStrategy = require('passport-google-oauth20').Strategy;
310
const { GithubUser, GoogleUser } = require('../models/userModel.js');
411

5-
module.exports = function (passport) {
12+
module.exports = function (passport/*: Authenticator */) {
613
passport.use(
714
new GitHubStrategy(
815
{
@@ -11,10 +18,10 @@ module.exports = function (passport) {
1118
callbackURL: 'http://localhost:3001/auth/github/callback',
1219
},
1320

14-
(accessToken, refreshToken, profile, done) => {
21+
(accessToken/* : String */, refreshToken/* : (String | undefined) */, profile/* : Profile */, done/* : Function */)/* : void */ => {
1522
//console.log('this is our accessToken:', accessToken);
1623
// we are checking if the github profile is in our monogDB
17-
GithubUser.findOne({ githubId: profile.id }, (err, result) => {
24+
GithubUser.findOne({ githubId: profile.id }, (err/* : Error */, result/* : { githubId: String, username: String } */)/* : void */ => {
1825
if (result) {
1926
// already have this user
2027
//console.log('user is: ', result);
@@ -27,7 +34,7 @@ module.exports = function (passport) {
2734
username: profile.displayName,
2835
})
2936
.save()
30-
.then((newUser) => {
37+
.then((newUser)/* : void */=> {
3138
//console.log('created new user: ', newUser);
3239
// res.locals.userId = newUser._id
3340
done(null, newUser);
@@ -48,10 +55,10 @@ module.exports = function (passport) {
4855
callbackURL: 'http://localhost:3001/auth/google/callback',
4956
},
5057

51-
(accessToken, refreshToken, profile, done) => {
58+
(accessToken/* : String */, refreshToken/* : (String | undefined) */, profile/* : Profile */, done/* : Function */)/* : void */=> {
5259
//console.log('this is our accessToken:', accessToken);
5360
// we are checking if the google profile is in our monogDB
54-
GoogleUser.findOne({ googleId: profile.id }, (err, result) => {
61+
GoogleUser.findOne({ googleId: profile.id }, (err/* : Error */, result/* : {googleId: String, username: String} */) => {
5562
if (result) {
5663
// already have this user
5764
//console.log('user is: ', result);
@@ -63,7 +70,7 @@ module.exports = function (passport) {
6370
googleId: profile.id,
6471
})
6572
.save()
66-
.then((newUser) => {
73+
.then((newUser)/* : void */=> {
6774
//console.log('created new user: ', newUser);
6875
// res.locals.userId = newUser._id
6976
done(null, newUser);
@@ -76,11 +83,11 @@ module.exports = function (passport) {
7683
)
7784
);
7885

79-
passport.serializeUser((user, done) => {
86+
passport.serializeUser((user, done)/* : void */=> {
8087
done(null, user);
8188
});
8289

83-
passport.deserializeUser((obj, done) => {
90+
passport.deserializeUser((obj/* : (false | Express.User | null | undefined) */, done)/* : void */ => {
8491
done(null, obj);
8592
});
8693
};

server/controllers/cookieController.js

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,21 @@
1-
const cookieController = {};
1+
/** using import statements in the electron / node files breaks npm start and nodepty
2+
* - types are left in place in these files for future iteration alternate import method is required for them to function
3+
*/
4+
// import { NextFunction, Request, Response } from "express";
5+
// import { cookieControllerType } from "../utils/backendTypes";
6+
7+
const cookieController /*: cookieControllerType*/ = {};
28

39
// Middleware to initialize a cookie when user logs in
4-
cookieController.setSSIDCookie = (req, res, next) => {
10+
cookieController.setSSIDCookie = (req/*: Request*/, res/*: Response*/, next/*: NextFunction*/)/*: void*/ => {
511
// eslint-disable-next-line no-useless-escape
612
//removing double quotes with Regex?
713
res.cookie('ssid', JSON.stringify(res.locals.userId).replace(/\"/g, ''));
814
return next();
915
};
1016

1117
// Middleware to delete a cookie upon user logging out
12-
cookieController.deleteCookie = (req, res, next) => {
18+
cookieController.deleteCookie = (req/*: Request*/, res/*: Response*/, next/*: NextFunction*/)/*: void*/ => {
1319
res.clearCookie('ssid');
1420
return next();
1521
};

server/controllers/sessionController.js

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,35 @@
1+
/** using import statements in the electron / node files breaks npm start and nodepty
2+
* - types are left in place in these files for future iteration alternate import method is required for them to function
3+
*/
4+
// import { ErrorRequestHandler, NextFunction, Request, Response } from "express";
5+
// import { MongoError, FindCursor } from "mongodb";
6+
// import { sessionControllerType } from "../utils/backendTypes";
7+
18
// Import the session model that defines schema of session
29
const Session = require('../models/sessionModel');
310

4-
const sessionController = {};
11+
const sessionController /*:sessionControllerType*/ = {};
512

613
// Middleware to initialize a session upon successful login
7-
sessionController.startSession = (req, res, next) => {
8-
Session.create({ cookieId: res.locals.userId }, (err, result) => {
14+
sessionController.startSession = (req /* : Request */, res /* : Response */, next /* : NextFunction */) /* : void */ => {
15+
Session.create({ cookieId: res.locals.userId }, (err /* : MongoError */, result /* : void */) /* : void */ => {
916
if (err && err.code !== 11000) return next(err);
1017
res.locals.ssid = res.locals.userId;
1118
return next();
1219
});
1320
};
1421

1522
// Middleware to end currently active sessions, if any
16-
sessionController.endSession = (req, res, next) => {
17-
Session.deleteMany({ cookieId: req.cookies.ssid }, (err) => {
23+
sessionController.endSession = (req /* : Request */, res /*: Response */, next /* : NextFunction */)/*: void*/ => {
24+
Session.deleteMany({ cookieId: req.cookies.ssid }, (err /* : ErrorRequestHandler */) /* void */ => {
1825
if (err) return next(err);
1926
return next();
2027
});
2128
};
2229

2330
// Middleware to check if entered user is currently already logged in
24-
sessionController.isLoggedIn = (req, res, next) => {
25-
Session.find({ cookieId: req.cookies.ssid }, (err, data) => {
31+
sessionController.isLoggedIn = (req /* :Request*/, res /* Response*/, next /* : NextFunction */) /* void */ => {
32+
Session.find({ cookieId: req.cookies.ssid }, (err /* : ErrorRequestHandler */, data /* : Array<{cookieId: String, createdAt: Date}> */) /* void */ => {
2633
if (err) return next(err);
2734
if (data.length === 0) return next('User Not Logged In');
2835
return next();

server/controllers/testStateController.js

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,37 @@
1+
/** using import statements in the electron / node files breaks npm start and nodepty
2+
* - types are left in place in these files for future iteration alternate import method is required for them to function
3+
*/
4+
// import { ErrorRequestHandler, NextFunction, Request, Response } from "express";
5+
// import { FindCursor } from "mongodb";
6+
// import { testStateControllerType } from "../utils/backendTypes";
7+
18
// Import test state model that defines the structure of test stored in DB
29
const TestState = require('../models/testStateModel');
3-
const testStateController = {};
10+
const testStateController /* :testStateControllerType */ = {};
411

512
// Middleware to upload a passed test into DB
6-
testStateController.upload = (req, res, next) => {
7-
const { testName, testType, testState } = req.body;
8-
const userId = req.cookies.ssid;
13+
testStateController.upload = (req /* : Request */, res /* : Response */, next /* : NextFunction */) /* : void */ => {
14+
const { testName, testType, testState }/*:
15+
{ testName : string, testType : string, testState : Object }*/ = req.body;
16+
const userId /* : number */ = req.cookies.ssid;
917

1018
TestState.create(
1119
{
12-
userId,
13-
testName,
14-
testType,
15-
testState
20+
userId: String,
21+
testName: String,
22+
testType: String,
23+
testState: Object
1624
},
17-
(err) => {
25+
(err /* : Error */) /* : void */ => {
1826
if (err) return next('Upload Failed');
1927
return next();
2028
}
2129
);
2230
};
2331

2432
// Middleware too get all saved tests of current user and of selected type
25-
testStateController.getTests = (req, res, next) => {
26-
TestState.find({ userId: req.cookies.ssid, testType: req.params.testType }, (err, result) => {
33+
testStateController.getTests = (req /* : Request */, res /* : Response */, next /* : NextFunction */) => {
34+
TestState.find({ userId: req.cookies.ssid, testType: req.params.testType }, (err /* : ErrorRequestHandler */, result /* : FindCursor */) /* : void */ => {
2735
// If an error occurs, invoke error handler with err object
2836
if (err) return next(err);
2937
// Save resulting tests array to locals object

server/controllers/userController.js

Lines changed: 90 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -1,89 +1,108 @@
1+
/** using import statements in the electron / node files breaks npm start and nodepty
2+
* - types are left in place in these files for future iteration alternate import method is required for them to function
3+
*/
4+
5+
// import { expression } from "@babel/template";
6+
// import { ErrorRequestHandler, NextFunction, Request, Response } from "express";
7+
// import { Cursor } from "mongoose";
8+
// import { BasicGroupByOptions } from "rxjs";
9+
// import { userControllerType } from "../utils/backendTypes";
10+
11+
/**
12+
* Errors on lines 89-90 and 97-98 are due to Typescript not recognizing inherent _id property on MongoDB collections.
13+
*/
14+
15+
116
const { User } = require('../models/userModel');
217
const bcrypt = require('bcryptjs');
318

4-
const userController = {};
19+
const userController/*: userControllerType*/ = {
520

6-
// Middleware to encrypt passwords using bcrypt
7-
userController.bcrypt = (req, res, next) => {
8-
// The cost factor determines how much time is needed to calculate a single bcrypt hash
9-
const saltRounds = 10;
10-
// Destructure password from request body
11-
const { password } = req.body;
12-
// Generate the salt by passing in saltRounds (cost factor)
13-
bcrypt.genSalt(saltRounds, (err, salt) => {
14-
// Hash a password by passing in the plaintext into the hash function
15-
bcrypt.hash(password, salt, (err, hash) => {
16-
// Save encrypted password into res.locals to be accessed later
17-
res.locals.encryptedPassword = hash;
18-
return next();
21+
// Middleware to encrypt passwords using bcrypt
22+
bcrypt: (req/*: Request*/, res/*: Response*/, next/*: NextFunction*/)/*: void*/ => {
23+
// The cost factor determines how much time is needed to calculate a single bcrypt hash
24+
const saltRounds = 10;
25+
// Destructure password from request body
26+
const { password }/*: { password: String }*/ = req.body;
27+
// Generate the salt by passing in saltRounds (cost factor)
28+
bcrypt.genSalt(saltRounds, (err/*: ErrorRequestHandler*/, salt/*: String*/)/*: void*/ => {
29+
// Hash a password by passing in the plaintext into the hash function
30+
bcrypt.hash(password, salt, (err/*: ErrorRequestHandler*/, hash/*: String*/)/*: void*/ => {
31+
// Save encrypted password into res.locals to be accessed later
32+
res.locals.encryptedPassword = hash;
33+
return next();
34+
});
1935
});
20-
});
21-
};
36+
},
37+
38+
// Middleware to save user information in database
39+
signup: (req/*: Request*/, res/*: Response*/, next/*: NextFunction*/)/*: (void | Response)*/ => {
40+
// collection.create method to insert new user
41+
User.create(
42+
// Pass in username from request body and encrypted password
43+
{ username/*: req.body.username*/, password/*: res.locals.encryptedPassword*/ },
44+
// Callback to handle results of query
45+
(err/*: ErrorRequestHandler*/, newUser/*: (null | undefined | { _id: number })*/) => {
46+
if (!newUser) return res.status(400).json("Username already exists, please choose another one.");
47+
// If there is an error, invoke global error handler
48+
if (err) return next(err);
49+
// Save user ID into response locals
50+
res.locals.userId = newUser._id;
51+
// Inovke next middleware
52+
return next();
53+
}
54+
);
55+
},
2256

23-
// Middleware to save user information in database
24-
userController.signup = (req, res, next) => {
25-
// collection.create method to insert new user
26-
User.create(
27-
// Pass in username from request body and encrypted password
28-
{ username: req.body.username, password: res.locals.encryptedPassword },
29-
// Callback to handle results of query
30-
(err, newUser) => {
31-
if (!newUser) return res.status(400).json("Username already exists, please choose another one.");
57+
// Middleware to check credentials and log user into application
58+
login: (req/*: Request*/, res/*: Response*/, next/*: NextFunction*/)/*: void*/ => {
59+
// Collection.find method to look for all user instances with passed username
60+
User.find({ username/*: req.body.username*/ }, (err/*: ErrorRequestHandler*/,
61+
result/*: Array<{ _id: number, username: String, password: String }>*/)/*: void*/ => {
3262
// If there is an error, invoke global error handler
3363
if (err) return next(err);
34-
// Save user ID into response locals
35-
res.locals.userId = newUser._id;
36-
// Inovke next middleware
37-
return next();
38-
}
39-
);
40-
};
64+
// If there are no matching usernames, invoke global error handler
65+
if (result.length === 0) return next('Incorrect username/password combo');
66+
// If there is a user with passed username, use the bcrypt.compare method to compare plaintext password with encrypted password
67+
bcrypt.compare(req.body.password, result[0].password, (err/*: ErrorRequestHandler*/, match/*: boolean*/) => {
68+
// If an error occurs in the compare method, invoke global error handler
69+
if (err) return next(err);
70+
// If there is a match, invoke next middleware
71+
if (match) {
72+
res.locals.userId = result[0]._id;
73+
return next();
74+
}
75+
// If there is no match, invoke global error handler
76+
return next('Incorrect username/password combination');
77+
});
78+
});
79+
},
4180

42-
// Middleware to check credentials and log user into application
43-
userController.login = (req, res, next) => {
44-
// Collection.find method to look for all user instances with passed username
45-
User.find({ username: req.body.username }, (err, result) => {
46-
// If there is an error, invoke global error handler
47-
if (err) return next(err);
48-
// If there are no matching usernames, invoke global error handler
49-
if (result.length === 0) return next('Incorrect username/password combo');
50-
// If there is a user with passed username, use the bcrypt.compare method to compare plaintext password with encrypted password
51-
bcrypt.compare(req.body.password, result[0].password, (err, match) => {
52-
// If an error occurs in the compare method, invoke global error handler
81+
getUsers: (req/*: Request*/, res/*: Response*/, next/*: NextFunction*/)/*: void*/ => {
82+
// Collection.find method to look for all user instances with passed username
83+
User.find({}, (err/*: ErrorRequestHandler*/, result/*: Array<{ _id: number, username: String, password: String }>*/) => {
84+
// If there is an error, invoke global error handler
5385
if (err) return next(err);
54-
// If there is a match, invoke next middleware
55-
if (match) {
56-
res.locals.userId = result[0]._id;
57-
return next();
58-
}
59-
// If there is no match, invoke global error handler
60-
return next('Incorrect username/password combination');
86+
res.locals.users = result;
87+
return next();
6188
});
62-
});
63-
};
89+
},
6490

65-
userController.getUsers = (req, res, next) => {
66-
// Collection.find method to look for all user instances with passed username
67-
User.find({}, (err, result) => {
68-
// If there is an error, invoke global error handler
69-
if (err) return next(err);
70-
res.locals.users = result;
71-
return next();
72-
});
73-
};
74-
75-
userController.githubLogin = (req, res, next) => {
76-
// store user._id in res.locals
77-
res.locals.userId = req.user._id;
91+
githubLogin: (req/*: Request*/, res/*: Response*/, next/*: NextFunction*/)/*: void*/ => {
92+
// store user._id in res.locals
93+
if(!req.user || !req.user._id) throw new Error("User or user ID not defined.")
94+
res.locals.userId = req.user._id;
7895

79-
return next();
80-
};
96+
return next();
97+
},
8198

82-
userController.googleLogin = (req, res, next) => {
83-
// store user._id in res.locals
84-
res.locals.userId = req.user._id;
99+
googleLogin: (req/*: Request*/, res/*: Response*/, next/*: NextFunction*/)/*: void*/ => {
100+
// store user._id in res.locals
101+
if(!req.user || !req.user._id) throw new Error("User or user ID not defined.")
102+
res.locals.userId = req.user._id;
85103

86-
return next();
104+
return next();
105+
}
87106
};
88107

89108
module.exports = userController;

server/models/sessionModel.js

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,16 @@
1+
/** using import statements in the electron / node files breaks npm start and nodepty
2+
* - types are left in place in these files for future iteration alternate import method is required for them to function
3+
*/
4+
5+
// import { Schema as SchemaType } from "mongoose";
6+
17
// Import mongoose for MongoDB object modeling
28
const mongoose = require('mongoose');
39
// Schema constructor
410
const Schema = mongoose.Schema;
511

612
// Initialize a new schema object for collection 'session'
7-
const sessionSchema = new Schema({
13+
const sessionSchema/* : SchemaType */ = new Schema({
814
// Save user ID
915
cookieId: { type: String, required: true, unique: true },
1016
createdAt: { type: Date, default: Date.now },

0 commit comments

Comments
 (0)