Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,9 @@
| Method | URL | Description |
| -------- | ---------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------ |
| [GET] | /profile/ | Returns an array of all existing profiles. |
| [GET] | /profile/:okta_id/ | Returns the profile object with the specified `okta_id`. |
| [GET] | /profiles/users/:profile_id <b>(BUG: /profiles/users route does not exist; app.js only connects to /profiles/user)</b> | Returns an array filled with event objects that contains information based on profile_id and role_id. |
| [GET] | /profile/role/:role_id <b>(BUG: does not return any data)</b> | Returns an array filled with event objects that contain information based on role_id for all profiles of a role_id type. |
| [GET] | /profile/:profile_id/ <b>(BUG: does not complete request)</b> | Returns the profile object with the specified `profile_id`. |
| [GET] | /profiles/users/:profile_id | Returns an array filled with event objects that contains information based on profile_id and role_id. |
| [GET] | /profile/role/:role_id | Returns an array filled with event objects that contain information based on role_id for all profiles of a role_id type. |
| [POST] | /profile/ | Requires a name, password, and email. Registers a new user. |
| [PUT] | /profile/ | Returns an event object with the specified `okta`. Updates specific profile. |
| [DELETE] | /profile/:okta_id/ | Returns an event object with the specified `okta`. Deletes specific profile. |
Expand Down
2 changes: 1 addition & 1 deletion api/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ app.use('/', indexRouter);
app.use(['/profile', '/profiles'], profileRouter);
app.use(['/parent', '/parents'], parentRouter);
app.use(['/instructor', '/instructors'], instructorRouter);
app.use(['/user'], userRouter);
app.use(['/user', '/users'], userRouter);
app.use(['/conversation', '/conversations'], inboxRouter);
app.use(
['/program-type', '/program-types', '/program', '/programs'],
Expand Down
2 changes: 1 addition & 1 deletion api/courses/coursesRouter.js
Original file line number Diff line number Diff line change
Expand Up @@ -402,9 +402,9 @@ router.post(

router.put(
'/:course_id',
authRequired,
validateCourseObject,
checkInstructorExists,
authRequired,
checkCourseExists,
(req, res, next) => {
const course_id = parseInt(req.params.course_id);
Expand Down
59 changes: 29 additions & 30 deletions api/instructor/instructorRouter.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ const express = require('express');
const authRequired = require('../middleware/authRequired');
const Instructors = require('./instructorModel');
const router = express.Router();
const Profiles = require('../profile/profileModel');
// const Profiles = require('../profile/profileModel');
const {
getInstructorId,
checkInstructorExist,
Expand All @@ -11,37 +11,36 @@ const {
/* Create a new Instructor profile */
router.post('/register', (req, res) => {
if (!req.body) return res.sendStatus(400);
const newInstructor = {
profile: {
firstName: req.body.firstName,
lastName: req.body.lastName,
email: req.body.email,
login: req.body.email,
},
}; // now sending to Okta

// TO-DO: Implement Auth0 -> create new user
// oktaClient
// .createUser(newInstructor)
// .then((instructor) => {
// return Profiles.create({
// email: instructor.profile.email,
// name: instructor.profile.firstName + ' ' + instructor.profile.lastName,
// okta_id: instructor.id,
// role_id: 3,
// pending: true,
// }).then(() => instructor);
// })
// .then((instructor) => {
// res.status(201);
// res.send(instructor);
// })
// .catch((err) => {
// res.status(400);
// res.send(err);
// });
// const newInstructor = {
// profile: {
// firstName: req.body.firstName,
// lastName: req.body.lastName,
// email: req.body.email,
// login: req.body.email,
// },
});

// TO-DO: Implement Auth0 -> create new user
// oktaClient
// .createUser(newInstructor)
// .then((instructor) => {
// return Profiles.create({
// email: instructor.profile.email,
// name: instructor.profile.firstName + ' ' + instructor.profile.lastName,
// okta_id: instructor.id,
// role_id: 3,
// pending: true,
// }).then(() => instructor);
// })
// .then((instructor) => {
// res.status(201);
// res.send(instructor);
// })
// .catch((err) => {
// res.status(400);
// res.send(err);
// });

router.get('/courses', authRequired, getInstructorId, (req, res, next) => {
Instructors.findInstructorCourses(req.instructor_id)
.then((courses) => {
Expand Down
43 changes: 43 additions & 0 deletions api/middleware/auth0Middleware.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
const { expressjwt: jwt } = require('express-jwt');
const jwksRsa = require('jwks-rsa');
const createError = require('http-errors');
const config = require('../../config/auth0');

// writing the config for expressJwt method to be invoked with product environment variables
const verifyJwt = jwt({
secret: jwksRsa.expressJwtSecret({
cache: true,
rateLimit: true,
jwksRequestsPerMinute: 5,
jwksUri: config.jwksUri,
}),
audience: config.audience,
issuer: config.issuer,
algorithms: ['RS256'],
requestProperty: 'auth0User',
}).unless({ path: ['/'] });
//************ */
//in the above line add all public endpoints (routes with no need for auth) as a string inside the path array [] <=
// **** IMPORTANT note: if your public endpoint has descendent end points (ex.: ./yourRouterEndPoint/:user_id) you need ot use regex as in the following example:
// ({ path: ['/', /^\/<your router end point>\/.*/] }); => example: ({ path: ['/', /^\/application\/.*/, /^\/roles\/.*/] });
//************ */

//exporting the verifyjwt method as a middleware to be used in app.js server file against all routes except what is in the exception array in above method
const authRequired = (req, res, next) => {
verifyJwt(req, res, next);
};

//method to grab the current authenticated user from the req.auth0User and save it to req.body.user to be used globally in the server
const authProfile = async (req, res, next) => {
try {
const profile = await req.auth0User;
if (profile) {
req.body.profile = profile;
}
next();
} catch (err) {
next(createError(401, err.message));
}
};

module.exports = { authRequired, authProfile };
37 changes: 23 additions & 14 deletions api/middleware/authRequired.js
Original file line number Diff line number Diff line change
@@ -1,23 +1,32 @@
// const createError = require('http-errors');
// const Profiles = require('../profile/profileModel');
const Profiles = require('../profile/profileModel');
/**
* TO-DO: Implement Auth0
* If token verification fails
* catch(err) => next(createError(401, err.message));
*/

/**
* A simple middleware that asserts valid Okta idToken and sends 401 responses
* A simple middleware that asserts valid Auth0 idToken and sends 401 responses
* if the token is not present or fails validation. If the token is valid its
* contents are attached to req.profile
*/
const authRequired = async (req, res, next) => {
// TO-DO: Implement Auth0 -> assure authorized through Header Token
try {
// Verify that the token is valid
const profile = Profiles.findOrCreateProfile;
console.log("I'm in authRequired");

if (profile) {
req.profile = profile;
} else {
next({
status: 401,
message: 'Unable to process idToken',
});
}

// const match = authHeader.match(/Bearer (.+)/);
// if (!match) throw new Error('Missing idToken');
// req.profile = authorizedProfile;
next();
// Proceed with request if token is valid
next();
} catch (err) {
next({
status: err.status || 500,
message: err.message || 'Internal Server Error',
});
}
};

module.exports = authRequired;
41 changes: 41 additions & 0 deletions api/middleware/getUserfromAuth0.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
const axios = require('axios');
const config = require('../../config/auth0');

const getUserAuth0 = async (req, res, next) => {
try {
// Check if there's a token in the auth header
const authHeader = req.headers.authorization || '';
const token = authHeader.match(/Bearer (.+)/);
if (!token) {
next({
status: 401,
message: 'Missing Token',
});
}
// Check against Auth0 if token is valid and grab user data
await axios
.get(`${config.issuer}/userinfo`, {
headers: {
authorization: authHeader,
},
})
.then((res) => {
const profile = res.data;
req.profile = profile;
next();
})
.catch((err) => {
next({
status: 404,
message: err,
});
});
} catch (err) {
next({
status: err.status || 500,
message: err.message || 'Internal Server Error',
});
}
};

module.exports = { getUserAuth0 };
20 changes: 10 additions & 10 deletions api/middleware/ownerAuthorization.js
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
// pass in the key to the profile that is the owner of what's being affected
// pass in the key parameter to the profile that is the owner of what's being affected
const ownerAuthorization = (key) => (req, res, next) => {
// TO-DO: Implement Auth0 - check that the role_id matches the key passed

// if (
// req.profile.profile_id === req[key].profile_id ||
// (req.profile.role_id < 3 && req.profile.role_id < (req[key].role_id || 3))
// )
// next();
// else
// res
// .status(401)
// .json({ message: 'You are not authorized to take this action' });
if (
req.profile.profile_id === req[key].profile_id ||
(req.profile.role_id < 3 && req.profile.role_id < (req[key].role_id || 3))
)
next();
else
res
.status(401)
.json({ message: 'You are not authorized to take this action' });
next();
};

Expand Down
9 changes: 6 additions & 3 deletions api/profile/profileMiddleware.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,11 @@ const Profiles = require('./profileModel');

const checkProfileObject = (req, res, next) => {
const { email, name, role_id, avatarUrl } = req.body;
if (!role_id) return next({ status: 400, message: 'role_id is required' });
if (!email) return next({ status: 400, message: 'email is required' });
if (!name) return next({ status: 400, message: 'name is required' });
console.log(req.body);
console.log("I'm in the obj middleware");
// if (!role_id) return next({ status: 400, message: 'role_id is required' });
// if (!email) return next({ status: 400, message: 'email is required' });
// if (!name) return next({ status: 400, message: 'name is required' });
if (
typeof role_id !== 'number' ||
typeof email !== 'string' ||
Expand All @@ -15,6 +17,7 @@ const checkProfileObject = (req, res, next) => {
message:
'variables in the request body must all be of type string except role_id must be of type number',
});
console.log('I made it to the other side!');
if (email.length > 255 || name.length > 255)
return next({
status: 400,
Expand Down
4 changes: 1 addition & 3 deletions api/profile/profileModel.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,7 @@ const remove = async (id) => {
};

const findOrCreateProfile = async (profileObj) => {
const foundProfile = await findById(profileObj.okta_id).then(
(profile) => profile
);
const foundProfile = await findById(profileObj.id).then((profile) => profile);
if (foundProfile) {
return foundProfile;
} else {
Expand Down
31 changes: 18 additions & 13 deletions api/profile/profileRouter.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,22 @@ const {
checkProfileExist,
} = require('./profileMiddleware');

router.get('/role/:role_id', authRequired, checkRoleExist, function (req, res) {
const role_id = req.params.role_id;
Profiles.findByRoleId(role_id)
.then((roleList) => {
res.status(200).json(roleList);
})
.catch((err) => {
console.log(err);
res.status(500).json({ message: err.message });
});
});
router.get(
'/:role/:role_id',
authRequired,
checkRoleExist,
function (req, res) {
const role_id = req.params.role_id;
Profiles.findByRoleId(role_id)
.then((roleList) => {
res.status(200).json(roleList);
})
.catch((err) => {
console.log(err);
res.status(500).json({ message: err.message });
});
}
);

router.get(
'/users/:profile_id',
Expand Down Expand Up @@ -194,9 +199,9 @@ router.get(
* profile:
* $ref: '#/components/schemas/Profile'
*/
router.post('/', checkProfileObject, async (req, res) => {
router.post('/', authRequired, checkProfileObject, async (req, res) => {
const profile = req.body;

console.log("I'm back to the router!");
// TO-DO: Implement Auth0 - check DB if specific Auth0 ID already exists
// changed verification from findById(okta_id) to findBy(email)
try {
Expand Down
2 changes: 1 addition & 1 deletion api/programs/programTypesRouter.js
Original file line number Diff line number Diff line change
Expand Up @@ -151,8 +151,8 @@ router.get('/:id', authRequired, checkProgramExists, async function (req, res) {

router.post(
'/',
validateProgramObject,
authRequired,
validateProgramObject,
checkIfProgramIsUnique,
async (req, res, next) => {
try {
Expand Down
2 changes: 1 addition & 1 deletion api/user/userRouter.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ router.post('/register', (req, res) => {

router.get('/', authRequired, function (req, res) {
// TO-DO: Implement Auth0 to check logged in (middleware) then use req.profile from what is received back
// const { role_id, profile_id } = req.profile;
const { role_id, profile_id } = req.profile;

User.findUserData(role_id, profile_id)
.then((user) => {
Expand Down
7 changes: 7 additions & 0 deletions config/auth0.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
module.exports = {
jwksUri: process.env.AUTH0_JWKS_URI,
audience: process.env.AUTH0_AUDIENCE,
issuer: process.env.AUTH0_ISSUER,
connection: process.env.AUTH0_CONNECTION,
token: process.env.AUTH0_TOKEN,
};
7 changes: 3 additions & 4 deletions data/seeds/001_profiles.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
const faker = require('faker');

let profiles = [...new Array(20)].map((i, idx) => ({
// TO-DO: Implement Auth0 ID
// okta_id: idx === 0 ? '00ulthapbErVUwVJy4x6' : faker.random.alphaNumeric(20),
auth0_id: idx === 0 ? '00ulthapbErVUwVJy4x6' : faker.random.alphaNumeric(20),
avatarUrl: faker.image.avatar(),
email: idx === 0 ? 'llama001@maildrop.cc"' : faker.internet.email(),
name:
Expand All @@ -13,9 +12,9 @@ let profiles = [...new Array(20)].map((i, idx) => ({
}));

/*
Manually setting the `id` for each profile to the Okta provided ID. Adding
Manually setting the `id` for each profile to the Auth0 provided ID. Adding
profiles was not in scope for this iteration, but adding profiles in the
future will require the okta-id to be set as the `id` for each profile.
future will require the auth0-id to be set as the `id` for each profile.
*/

// TO-DO: Implement dummy Auth0 IDs
Expand Down
Loading