Skip to content

Commit

Permalink
Jma/cu 28kunhb fix posting early close (#14)
Browse files Browse the repository at this point in the history
* Fix first-time login issue

* Fix deadline timezone bug

* Add UTC conversions for other posting paths
  • Loading branch information
Jeff Ma committed Sep 1, 2022
1 parent 992f849 commit fad5cf9
Show file tree
Hide file tree
Showing 10 changed files with 285 additions and 193 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.

# vscode
.vscode/**

# dependencies
/node_modules
/.pnp
Expand Down
55 changes: 34 additions & 21 deletions src/backend/db/users.js
Original file line number Diff line number Diff line change
@@ -1,35 +1,48 @@
import { toUser, fromUser } from '../models/users';

const getById = (db) => (id) => db('users')
.where({
id
})
.then((data) => {
if (data.length == 0) {
return -1;
}
if (data.length > 1) {
return new Error(`Multiple Users with id: ${id}`);
}
return toUser(data[0]);
});
const getById = (db) => (id) =>
db('users')
.where({
id,
})
.then((data) => {
if (data.length === 0) {
return -1;
}
if (data.length > 1) {
// should never happen.
throw new Error(`Multiple Users with id: ${id}`);
}
return toUser(data[0]);
});

const updateProfilePicture = (db) => async (picture, id) => {
return db('users').where({
id
}).update({ picture });
return db('users')
.where({
id,
})
.update({ picture });
};

const getProfilePicture = (db) => async (userId) => {
const users = await db('users').where({
id: userId
id: userId,
});
console.log(users)
console.log(users);
return users.length > 0 ? users[0].picture : '';
}
};

const createUser = (db) => (email, givenName, familyName, userId) => db('users')
.insert(fromUser({ id: userId, email, givenName, familyName, picture: '', admin: false }));
const createUser = (db) => (email, givenName, familyName, userId) =>
db('users').insert(
fromUser({
id: userId,
email,
givenName,
familyName,
picture: '',
admin: false,
}),
);

export default (db) => ({
getById: getById(db),
Expand Down
117 changes: 74 additions & 43 deletions src/backend/google-auth.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ export const validateRequest = (req, res, next) => {
}
const [type, token] = authorization.split(' ');
if (type !== 'Bearer') {
console.log("Auth Error, (not a bearer token)", authorization, type, token);
console.log('Auth Error, (not a bearer token)', authorization, type, token);
res.sendStatus(403);
return;
}
Expand All @@ -34,6 +34,7 @@ export const validateRequest = (req, res, next) => {
const {
hd, // host domain
} = payload;

if (hd !== 'waterloop.ca') {
res.sendStatus(403);
}
Expand Down Expand Up @@ -64,76 +65,106 @@ router.post('/', (req, res) => {
family_name,
given_name,
} = payload;

if (hd !== 'waterloop.ca') {
throw {
status: 403,
msg: 'Attempted Sign in from not waterloop.ca account',
};
}
return db.users.getById(userId).then((userQueryResp) => {
if (userQueryResp === -1) {
// No user found so make one
return db.users
.createUser(email, given_name, family_name, userId)
.then(() => db.users.getById(userId));
}

// Check that the access token was sent along in the request
const authHeader = req.get("Authorization");
if (!authHeader) {
res.status(401).set('WWW-Authenticate', 'Bearer').send('No auth header found.').end();
return;
}
const [type, accessToken] = authHeader.split(' ');
if (type !== "Bearer" || !accessToken) {
res.status(401).set('WWW-Authenticate', 'Bearer').send('No bearer token found.').end();
return;
}
return db.users
.getById(userId)
.then((userQueryResp) => {
if (userQueryResp === -1) {
// No user found so make one
//// TODO: Set the user as admin if they are one here.
db.users
.createUser(email, given_name, family_name, userId)
.then(() => db.users.getById(userId))
.catch((err) => {
console.error(err);
return {};
});
}
// Check that the access token was sent along in the request
const authHeader = req.get('Authorization');
if (!authHeader) {
res
.status(401)
.set('WWW-Authenticate', 'Bearer')
.send('No auth header found.')
.end();
return;
}
const [type, accessToken] = authHeader.split(' ');
if (type !== 'Bearer' || !accessToken) {
res
.status(401)
.set('WWW-Authenticate', 'Bearer')
.send('No bearer token found.')
.end();
return;
}

// Check whether the user has admin priveleges (admins can edit content using the CMS)
db.featurePermissions
.getAllowedActions(userId, accessToken)
.then((resp) => {
// Check whether the user has admin priveleges (admins can edit content using the CMS)
db.featurePermissions
.getAllowedActions(userId, accessToken)
.then((resp) => {
console.log(resp);
const {allowedActions, groupIds} = resp;
if (allowedActions.includes('Edit Content')) { // The user has permission to log in to the CMS
res.send({ userId, groupIds, accessToken }).status(200);
const { allowedActions, groupIds } = resp;
if (allowedActions.includes('Edit Content')) {
// The user has permission to log in to the CMS
res.send({ userId, groupIds, accessToken }).status(200).end();
} else {
res.statusMessage = "ERROR: User does not have permission to edit website content.";
res.statusMessage =
'ERROR: User does not have permission to edit website content.';
res.status(403).end();
}
});
})
.catch((err) => {
console.log(`${err.status}: ${err.msg}`);
res.sendStatus(err.status || 400);
}
});
})
.catch((err) => {
console.log(err);
console.log(`${err.status}: ${err.msg}`);
res.sendStatus(err.status || 400);
});
});
})
});

router.post('/groups', (req, res) => {
const {userId, groupIds} = req.query;
const { userId, groupIds } = req.query;
const groupIdsArray = groupIds.split(',');

// Check that the access token was sent along in the request
const authHeader = req.get("Authorization");
const authHeader = req.get('Authorization');
if (!authHeader) {
res.status(401).set('WWW-Authenticate', 'Bearer').send('No auth header found.').end();
res
.status(401)
.set('WWW-Authenticate', 'Bearer')
.send('No auth header found.')
.end();
return;
}

const [type, accessToken] = authHeader.split(' ');
if (type !== "Bearer" || !accessToken) {
res.status(401).set('WWW-Authenticate', 'Bearer').send('No bearer token found.').end();
if (type !== 'Bearer' || !accessToken) {
res
.status(401)
.set('WWW-Authenticate', 'Bearer')
.send('No bearer token found.')
.end();
return;
}

db.featurePermissions.
updateUserGroups(userId, groupIdsArray, accessToken)
db.featurePermissions
.updateUserGroups(userId, groupIdsArray, accessToken)
.then((resp) => {
res.send(resp).status(200);
}).catch(err => {
console.log("Error: Failed to sync group membership info. with data from Google Groups.");
})
.catch((err) => {
console.log(
'Error: Failed to sync group membership info. with data from Google Groups.',
);
res.sendStatus(err.status || 400);
});
});
Expand Down
9 changes: 6 additions & 3 deletions src/backend/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ app.use(cookieParser());
app.use(
cors({
origin: [
'http://localhost:3000', // CLIENT_URI should hold the cms client uri
/^http:\/\/localhost:[0-9]{4}$/, // CLIENT_URI should hold the cms client uri
'https://teamwaterloop.ca', // Always allow the main site
],
credentials: true,
Expand Down Expand Up @@ -139,10 +139,13 @@ if (process.env.NODE_ENV !== 'production') {
});
}

// Dev environment doesn't use build folder:
let folder = process.env.NODE_ENV === 'production' ? 'build' : 'public';

/* These need to be the last routes */
app.use(express.static('./build'));
app.use(express.static(`./${folder}`));
app.get('*', (req, res) => {
res.sendFile('index.html', { root: path.join(__dirname, '../../build') });
res.sendFile('index.html', { root: path.join(__dirname, `../../${folder}`) });
});

if (process.env.NODE_ENV === 'production') {
Expand Down
80 changes: 38 additions & 42 deletions src/frontend/hooks/google-auth.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,51 +5,47 @@ import { useDispatch } from 'react-redux';
import api from '../api';

const useGoogleAuth = (onAuthComplete) => {
const dispatch = useDispatch();
const onSuccess = useCallback(
(response) => {
// https://github.com/anthonyjgrove/react-google-login/blob/7db5b9686a70ded6b090a9c01906ca978b00a54d/index.d.ts#L29
const { tokenId, profileObj, accessToken } = response;
console.log('Begin auth');
api.google
.checkToken(tokenId, accessToken)
.then((checkTokenResponse) => {
if (checkTokenResponse.status === 200) {
const {
userId,
groupIds,
accessToken,
} = checkTokenResponse.data;
onAuthComplete(null, {
userId,
tokenId,
groupIds,
accessToken,
});
}
})
.catch((err) => onAuthComplete(err));
const dispatch = useDispatch();
const onSuccess = useCallback(
(response) => {
// https://github.com/anthonyjgrove/react-google-login/blob/7db5b9686a70ded6b090a9c01906ca978b00a54d/index.d.ts#L29
const { tokenId, profileObj, accessToken } = response;
console.log('Begin auth');
api.google
.checkToken(tokenId, accessToken)
.then((checkTokenResponse) => {
if (checkTokenResponse.status === 200) {
const { userId, groupIds, accessToken } = checkTokenResponse.data;
onAuthComplete(null, {
userId,
tokenId,
groupIds,
accessToken,
});
}
})
.catch((err) => onAuthComplete(err));

dispatch(userActions.setUserPicture(profileObj.imageUrl));
},
[onAuthComplete],
);
dispatch(userActions.setUserPicture(profileObj.imageUrl));
},
[onAuthComplete],
);

const { signIn } = useGoogleLogin({
onSuccess,
onFailure: (err) => {
console.log('failed auth', err);
},
clientId:
'538509890740-e3dai2feq6knjfdspqde5ogt2kme0chm.apps.googleusercontent.com',
scope:
'profile email https://www.googleapis.com/auth/admin.directory.group.readonly',
prompt: 'consent',
});
const { signIn } = useGoogleLogin({
onSuccess,
onFailure: (err) => {
console.log('failed auth', err);
},
clientId:
'538509890740-e3dai2feq6knjfdspqde5ogt2kme0chm.apps.googleusercontent.com',
scope:
'profile email https://www.googleapis.com/auth/admin.directory.group.readonly',
prompt: 'consent',
});

return {
signIn,
};
return {
signIn,
};
};

export default useGoogleAuth;
Loading

0 comments on commit fad5cf9

Please sign in to comment.