Skip to content

Commit 7a0ef8c

Browse files
authored
Merge pull request #15 from andrewjcho84/projectManagement
Github Oauth and project management
2 parents dd16241 + 8ce69dd commit 7a0ef8c

File tree

19 files changed

+507
-171
lines changed

19 files changed

+507
-171
lines changed

.gitignore

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -486,4 +486,14 @@ ASALocalRun/
486486
reactype.dmg
487487
installers/
488488

489+
# for server key and ssl certificate generation
490+
server/domains.ext
491+
server/localhost.crt
492+
server/localhost.csr
493+
server/localhost.key
494+
server/RootCA.crt
495+
server/rootCA.key
496+
server/rootCA.pem
497+
server/RootCA.srl
498+
489499
# End of https://www.gitignore.io/api/node,linux,macos,windows,visualstudio,yarn

main.js

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,7 @@ const {
1111
shell,
1212
dialog,
1313
ipcMain,
14-
globalShortcut,
15-
session
14+
globalShortcut
1615
} = require('electron');
1716

1817
// Uncomment below for hot reloading during development
@@ -92,8 +91,11 @@ const createWindow = () => {
9291
width: 1920,
9392
height: 1080,
9493
webPreferences: {
95-
zoomFactor: 0.7,
96-
'node-Integration': false
94+
zoomFactor: 0.7
95+
// for proper security measures, nodeIntegration should be set to false, but this results in a blank page when serving app
96+
// nodeIntegration: false,
97+
// preload: 'preload.js',
98+
// enableRemoteModule: false
9799
},
98100
show: false,
99101
icon: path.join(__dirname, '/src/public/icons/png/256x256.png'),
@@ -118,9 +120,11 @@ const createWindow = () => {
118120
text: 'Initializing ...'
119121
});
120122

121-
// and load the index.html of the app.
122-
// now loading what the server serves, this url will need to change when/if we decide to put reactype on the web
123-
mainWindow.loadURL(`http://localhost:8080`);
123+
// code below loads app locally
124+
// mainWindow.loadURL(`file://${__dirname}/build/index.html`);
125+
126+
// code below loads app from a server, this url will need to change when/if we decide to put reactype on the web
127+
mainWindow.loadURL(`https://localhost:8080`);
124128
// load page once window is loaded
125129
mainWindow.once('ready-to-show', () => {
126130
mainWindow.show();
@@ -311,3 +315,6 @@ app.on('activate', () => {
311315
createWindow();
312316
}
313317
});
318+
319+
// bypass ssl certification validation error
320+
// app.commandLine.appendSwitch('ignore-certificate-errors', 'true');

package.json

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@
7676
"test:clear": "cross-env NODE_ENV=test jest --clearCache",
7777
"linter": "eslint src",
7878
"develop": "concurrently \"npm run dev\" \"npm run electron\"",
79-
"server": "cross-env NODE_ENV=development nodemon server/server.js"
79+
"server": "nodemon server/server.js"
8080
},
8181
"bin": {
8282
"reactype": "./index.js"
@@ -143,6 +143,8 @@
143143
"localforage": "^1.7.2",
144144
"lodash.throttle": "^4.1.1",
145145
"material-table": "^1.57.2",
146+
"passport": "^0.4.1",
147+
"passport-github2": "^0.1.12",
146148
"prettier": "^1.19.1",
147149
"prismjs": "^1.19.0",
148150
"prop-types": "^15.6.2",
@@ -163,7 +165,8 @@
163165
"redux-devtools-extension": "^2.13.5",
164166
"redux-logger": "^3.0.6",
165167
"redux-thunk": "^2.3.0",
166-
"redux-undo": "^1.0.1"
168+
"redux-undo": "^1.0.1",
169+
"source-map-support": "^0.5.19"
167170
},
168171
"devDependencies": {
169172
"@babel/core": "^7.9.0",

server/controllers/cookieController.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,11 @@ const cookieController = {};
33
// setSSIDCookie - store the user id from database in cookie
44
cookieController.setSSIDCookie = (req, res, next) => {
55
// set cookie with key 'ssid' and value to user's id, also set http only
6+
console.log('Inside setSSIDCookie');
7+
68
res.cookie('ssid', res.locals.id, { maxAge: 3600000 });
7-
console.log('Successful setSSIDCookie');
9+
10+
console.log('Successful setSSIDCookie, ssid:', res.locals.id);
811
return next();
912
};
1013

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
const { Projects } = require('../models/reactypeModels');
2+
const projectController = {};
3+
4+
// saveProject saves current workspace to database
5+
6+
projectController.saveProject = (req, res, next) => {
7+
console.log('Inside projectController.saveProject...');
8+
// pull project name and project itself from body
9+
const { name, project } = req.body;
10+
// pull ssid from cookies for user id
11+
const userId = req.cookies.ssid;
12+
Projects.findOneAndUpdate(
13+
// looks in projects collection for project by user and name
14+
{ name, userId },
15+
// update or insert the project
16+
{ project },
17+
// Options: upsert: true - if none found, inserts new project, if found, updates project
18+
// new: true - returns updated document not the original one
19+
{ upsert: true, new: true },
20+
(err, result) => {
21+
if (err) {
22+
return next({
23+
log: `Error in projectController.saveProject: ${err}`,
24+
message: {
25+
err: `Error in projectController.saveProject, check server logs for details`
26+
}
27+
});
28+
} else {
29+
res.locals.savedProject = result;
30+
console.log('Successful saveProject');
31+
return next();
32+
}
33+
}
34+
);
35+
};
36+
37+
// gets all of current project's projects
38+
39+
projectController.getProjects = (req, res, next) => {
40+
console.log('Inside projectController.getProjects...');
41+
const userId = req.cookies.ssid;
42+
Projects.find({ userId }, (err, projects) => {
43+
if (err) {
44+
return next({
45+
log: `Error in projectController.getProjects: ${err}`,
46+
message: {
47+
err: `Error in projectController.getProjects, check server logs for details`
48+
}
49+
});
50+
} else {
51+
console.log('Successful getProjects');
52+
res.locals.projects = projects;
53+
return next();
54+
}
55+
});
56+
};
57+
58+
module.exports = projectController;

server/controllers/sessionController.js

Lines changed: 45 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
1-
const Session = require('../models/sessionModel');
1+
const { Sessions } = require('../models/reactypeModels');
22
const sessionController = {};
33

44
// isLoggedIn finds appropriate session for this request in database, then verifies whether or not the session is still valid
55
sessionController.isLoggedIn = (req, res, next) => {
6+
console.log('Inside isLoggedIn');
7+
console.log('req.cookies is', req.cookies);
68
// find session from request session ID in mongodb
7-
Session.findOne({ cookieId: req.cookies.ssid }, (err, session) => {
9+
Sessions.findOne({ cookieId: req.cookies.ssid }, (err, session) => {
810
if (err) {
911
return next({
1012
log: `Error in sessionController.isLoggedIn: ${err}`,
@@ -14,9 +16,11 @@ sessionController.isLoggedIn = (req, res, next) => {
1416
});
1517
// no session found, redirect to signup page
1618
} else if (!session) {
19+
console.log('No session found, redirecting to signup page');
1720
return res.redirect('/signup');
1821
} else {
1922
// session found, move onto next middleware
23+
console.log('Session found, moving onto next middleware');
2024
return next();
2125
}
2226
});
@@ -26,7 +30,7 @@ sessionController.isLoggedIn = (req, res, next) => {
2630
sessionController.startSession = (req, res, next) => {
2731
console.log('Inside startSession');
2832
// first check if user is logged in already
29-
Session.findOne({ cookieId: res.locals.id }, (err, session) => {
33+
Sessions.findOne({ cookieId: res.locals.id }, (err, session) => {
3034
if (err) {
3135
return next({
3236
log: `Error in sessionController.startSession find session: ${err}`,
@@ -37,7 +41,7 @@ sessionController.startSession = (req, res, next) => {
3741
// if session doesn't exist, create a session
3842
// if valid user logged in/signed up, res.locals.id should be user's id generated from mongodb, which we will set as this session's cookieId
3943
} else if (!session) {
40-
Session.create({ cookieId: res.locals.id }, (err, session) => {
44+
Sessions.create({ cookieId: res.locals.id }, (err, session) => {
4145
if (err) {
4246
return next({
4347
log: `Error in sessionController.startSession create session: ${err}`,
@@ -59,4 +63,41 @@ sessionController.startSession = (req, res, next) => {
5963
}
6064
});
6165
};
66+
67+
// creates a session when logging in with github
68+
sessionController.githubSession = (req, res, next) => {
69+
// req.user is passed in from passport js -> serializeuser/deserializeuser
70+
console.log('github session req.user is', req.user);
71+
const cookieId = req.user._id;
72+
Sessions.findOne({ cookieId }, (err, session) => {
73+
if (err) {
74+
return next({
75+
log: `Error in sessionController.githubSession find session: ${err}`,
76+
message: {
77+
err: `Error in sessionController.githubSession find session, check server logs for details`
78+
}
79+
});
80+
} else if (!session) {
81+
Sessions.create({ cookieId }, (err, session) => {
82+
if (err) {
83+
return next({
84+
log: `Error in sessionController.githubSession create session: ${err}`,
85+
message: {
86+
err: `Error in sessionController.githubSession create session, check server logs for details`
87+
}
88+
});
89+
} else {
90+
console.log('Successful start githubSession');
91+
res.locals.id = session.cookieId;
92+
return next();
93+
}
94+
});
95+
} else {
96+
console.log('Github session exists, moving on');
97+
res.locals.id = session.cookieId;
98+
return next();
99+
}
100+
});
101+
};
102+
62103
module.exports = sessionController;

server/controllers/userController.js

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
// middleware functions create a new user and verify users
22

3-
const Users = require('../models/userModel');
3+
const { Users } = require('../models/reactypeModels');
44

55
const userController = {};
66
const bcrypt = require('bcryptjs');
@@ -9,6 +9,7 @@ userController.createUser = (req, res, next) => {
99
console.log('Creating user...');
1010
const { email, username, password } = req.body;
1111
// error handling if username or password is missing
12+
// TODO make this more vague for security purposes
1213
if (!username) {
1314
return res.status(400).json('No username input');
1415
}
@@ -20,7 +21,7 @@ userController.createUser = (req, res, next) => {
2021
}
2122

2223
// create user using username and password
23-
Users.create({ email, username, password, projects: [] }, (err, newUser) => {
24+
Users.create({ username, password, email }, (err, newUser) => {
2425
if (err) {
2526
return next({
2627
log: `Error in userController.createUser: ${err}`,
@@ -41,7 +42,7 @@ userController.createUser = (req, res, next) => {
4142
// the appropriate user in the database, and then authenticate the submitted password against the password stored in the database.
4243

4344
userController.verifyUser = (req, res, next) => {
44-
console.log('Verifying user...');
45+
console.log('Inside userController.verifyUser...');
4546
const { username, password } = req.body;
4647
if (!username) {
4748
return res.status(400).json('No username input');

server/models/reactypeModels.js

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
const mongoose = require('mongoose');
2+
require('dotenv').config();
3+
4+
// connect to mongo db
5+
mongoose
6+
.connect(process.env.MONGO_URI, {
7+
// options for the connect method to parse the URI
8+
useNewUrlParser: true,
9+
useUnifiedTopology: true,
10+
useCreateIndex: true,
11+
// stop deprecation warning for findOneAndUpdate and findOneAndDelete queries
12+
useFindAndModify: false,
13+
// sets the name of the DB that our collections are part of
14+
dbName: 'ReacType'
15+
})
16+
.then(() => console.log('Connected to Mongo DB.'))
17+
.catch(err => console.log(err));
18+
19+
const Schema = mongoose.Schema;
20+
21+
const userSchema = new Schema({
22+
username: { type: String, required: true, unique: true },
23+
email: { type: String, required: false, unique: true },
24+
password: { type: String, required: true }
25+
});
26+
27+
// salt will go through 10 rounds of hashing
28+
const SALT_WORK_FACTOR = 10;
29+
const bcrypt = require('bcryptjs');
30+
31+
// mongoose middleware that will run before the save to collection happens (user gets put into database)
32+
// cannot use arrow function here as context of 'this' is important
33+
userSchema.pre('save', function(next) {
34+
// within this context, 'this' refers to the document (new user) about to be saved, in our case, it should have properties username, password, and projects array
35+
bcrypt.hash(this.password, SALT_WORK_FACTOR, (err, hash) => {
36+
if (err) {
37+
return next({
38+
log: `bcrypt password hashing error: ${err}`,
39+
message: {
40+
err: `bcrypt hash error: check server logs for details`
41+
}
42+
});
43+
}
44+
this.password = hash;
45+
return next();
46+
});
47+
});
48+
49+
const sessionSchema = new Schema({
50+
cookieId: { type: String, required: true, unique: true },
51+
createdAt: { type: Date, expires: 3600, default: Date.now }
52+
});
53+
54+
const projectSchema = new Schema({
55+
name: { type: String, required: true },
56+
project: Object,
57+
userId: {
58+
type: Schema.Types.ObjectId,
59+
ref: 'Users'
60+
},
61+
createdAt: { type: Date, default: Date.now }
62+
});
63+
64+
const Users = mongoose.model('Users', userSchema);
65+
const Sessions = mongoose.model('Sessions', sessionSchema);
66+
const Projects = mongoose.model('Projects', projectSchema);
67+
68+
module.exports = { Users, Sessions, Projects };

server/models/sessionModel.js

Lines changed: 0 additions & 10 deletions
This file was deleted.

server/models/userModel.js

Lines changed: 0 additions & 35 deletions
This file was deleted.

0 commit comments

Comments
 (0)