Compare commits

..

No commits in common. "2ba7778901a5c54c443b41da472375a2910dbf8b" and "adb27445ff20d8409a7ab6123f6c5f795300d43e" have entirely different histories.

25 changed files with 55 additions and 3927 deletions

View File

@ -0,0 +1,3 @@
module.exports = {
secret: "bullpen-secret-key"
};

View File

@ -1,6 +1,7 @@
const db = require("../models"); const db = require("../models");
const config = require("../config/auth.config"); const config = require("../config/auth.config");
const { user: User, role: Role, refreshToken: RefreshToken } = db; const User = db.user;
const Role = db.role;
const Op = db.Sequelize.Op; const Op = db.Sequelize.Op;
@ -46,12 +47,16 @@ exports.signin = (req, res) => {
email: req.body.email email: req.body.email
} }
}) })
.then(async (user) => { .then(user => {
if (!user) { if (!user) {
return res.status(404).send({ message: "User Not found." }); return res.status(404).send({ message: "User Not found." });
} }
const passwordIsValid = user.validPassword(req.body.password); const passwordIsValid = user.validPassword(req.body.password);
// const passwordIsValid = bcrypt.compareSync(
// req.body.password,
// user.password
// );
if (!passwordIsValid) { if (!passwordIsValid) {
return res.status(401).send({ return res.status(401).send({
@ -65,11 +70,9 @@ exports.signin = (req, res) => {
{ {
algorithm: 'HS256', algorithm: 'HS256',
allowInsecureKeySizes: true, allowInsecureKeySizes: true,
expiresIn: config.jwtExpiration expiresIn: 86400, // 24 hours
}); });
let refreshToken = await RefreshToken.createToken(user);
const authorities = []; const authorities = [];
user.getRoles().then(roles => { user.getRoles().then(roles => {
for (let i = 0; i < roles.length; i++) { for (let i = 0; i < roles.length; i++) {
@ -80,8 +83,7 @@ exports.signin = (req, res) => {
username: user.username, username: user.username,
email: user.email, email: user.email,
roles: authorities, roles: authorities,
accessToken: token, accessToken: token
refreshToken: refreshToken
}); });
}); });
}) })
@ -89,43 +91,3 @@ exports.signin = (req, res) => {
res.status(500).send({ message: err.message }); res.status(500).send({ message: err.message });
}); });
}; };
exports.refreshToken = async (req, res) => {
const { refreshToken: requestToken } = req.body;
if (requestToken == null) {
return res.status(403).json({ message: "Refresh Token is required!" });
}
try {
let refreshToken = await RefreshToken.findOne({ where: { token: requestToken } });
console.log(refreshToken)
if (!refreshToken) {
res.status(403).json({ message: "Refresh token is not in database!" });
return;
}
if (RefreshToken.verifyExpiration(refreshToken)) {
RefreshToken.destroy({ where: { id: refreshToken.id } });
res.status(403).json({
message: "Refresh token was expired. Please make a new signin request",
});
return;
}
const user = await refreshToken.getUser();
let newAccessToken = jwt.sign({ id: user.id }, config.secret, {
expiresIn: config.jwtExpiration,
});
return res.status(200).json({
accessToken: newAccessToken,
refreshToken: refreshToken.token,
});
} catch (err) {
return res.status(500).send({ message: err });
}
};

View File

@ -72,5 +72,3 @@ function initial() {
{ name: 'Slurve', abbreviation: 'SLV' }, { name: 'Slurve', abbreviation: 'SLV' },
]); ]);
} }
module.exports = app;

View File

@ -3,33 +3,29 @@ const config = require("../config/auth.config.js");
const db = require("../models"); const db = require("../models");
const User = db.user; const User = db.user;
const { TokenExpiredError } = jwt; verifyToken = (req, res, next) => {
const catchError = (err, res) => {
if (err instanceof TokenExpiredError) {
return res.status(401).send({ message: "Unauthorized! Access Token was expired!" });
}
return res.sendStatus(401).send({ message: "Unauthorized!" });
}
const verifyToken = (req, res, next) => {
let token = req.headers["x-access-token"]; let token = req.headers["x-access-token"];
if (!token) { if (!token) {
return res.status(403).send({ message: "No token provided!" }); return res.status(403).send({
message: "No token provided!"
});
} }
jwt.verify(token, config.secret, (err, decoded) => { jwt.verify(token,
if (err) { config.secret,
return catchError(err, res); (err, decoded) => {
} if (err) {
req.userId = decoded.id; return res.status(401).send({
next(); message: "Unauthorized!",
}); });
}
req.userId = decoded.id;
next();
});
}; };
const isAdmin = (req, res, next) => { isAdmin = (req, res, next) => {
User.findByPk(req.userId).then(user => { User.findByPk(req.userId).then(user => {
user.getRoles().then(roles => { user.getRoles().then(roles => {
for (let i = 0; i < roles.length; i++) { for (let i = 0; i < roles.length; i++) {
@ -46,7 +42,7 @@ const isAdmin = (req, res, next) => {
}); });
}; };
const isModerator = (req, res, next) => { isModerator = (req, res, next) => {
User.findByPk(req.userId).then(user => { User.findByPk(req.userId).then(user => {
user.getRoles().then(roles => { user.getRoles().then(roles => {
for (let i = 0; i < roles.length; i++) { for (let i = 0; i < roles.length; i++) {
@ -63,7 +59,7 @@ const isModerator = (req, res, next) => {
}); });
}; };
const isModeratorOrAdmin = (req, res, next) => { isModeratorOrAdmin = (req, res, next) => {
User.findByPk(req.userId).then(user => { User.findByPk(req.userId).then(user => {
user.getRoles().then(roles => { user.getRoles().then(roles => {
for (let i = 0; i < roles.length; i++) { for (let i = 0; i < roles.length; i++) {
@ -91,4 +87,4 @@ const authJwt = {
isModerator: isModerator, isModerator: isModerator,
isModeratorOrAdmin: isModeratorOrAdmin isModeratorOrAdmin: isModeratorOrAdmin
}; };
module.exports = authJwt; module.exports = authJwt;

View File

@ -29,12 +29,11 @@ const db = {};
db.Sequelize = Sequelize; db.Sequelize = Sequelize;
db.sequelize = sequelize; db.sequelize = sequelize;
db.user = require("./user.model.js")(sequelize); db.user = require("../models/user.model.js")(sequelize);
db.role = require("./role.model.js")(sequelize); db.role = require("../models/role.model.js")(sequelize);
db.pitchType = require("./pitchType.model.js")(sequelize); db.pitchType = require("../models/pitchType.model.js")(sequelize);
db.pitch = require("./pitch.model.js")(sequelize); db.pitch = require("../models/pitch.model.js")(sequelize);
db.bullpenSession = require("./bullpenSession.model.js")(sequelize); db.bullpenSession = require("../models/bullpenSession.model.js")(sequelize);
db.refreshToken = require("./refreshToken.model.js")(sequelize);
db.role.belongsToMany(db.user, { db.role.belongsToMany(db.user, {
through: "UserRoles" through: "UserRoles"
@ -42,12 +41,6 @@ db.role.belongsToMany(db.user, {
db.user.belongsToMany(db.role, { db.user.belongsToMany(db.role, {
through: "UserRoles" through: "UserRoles"
}); });
db.refreshToken.belongsTo(db.user, {
foreignKey: 'userId', targetKey: 'id'
});
db.user.hasOne(db.refreshToken, {
foreignKey: 'userId', targetKey: 'id'
});
db.ROLES = ["user", "admin", "moderator"]; db.ROLES = ["user", "admin", "moderator"];
@ -58,4 +51,4 @@ db.bullpenSession.belongsTo(db.user, {
db.pitch.belongsTo(db.bullpenSession); db.pitch.belongsTo(db.bullpenSession);
db.pitch.belongsTo(db.pitchType); db.pitch.belongsTo(db.pitchType);
module.exports = db; module.exports = db;

3772
backend/package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -1,10 +1,10 @@
{ {
"name": "bullpen-backend", "name": "bullpen-backend",
"version": "1.0.0", "version": "1.0.0",
"main": "src/index.js", "main": "index.js",
"scripts": { "scripts": {
"test": "echo \"Error: no test specified\" && exit 1", "test": "echo \"Error: no test specified\" && exit 1",
"start": "node src/index.js", "start": "node index.js",
"setup-example-db": "node database/setup.js" "setup-example-db": "node database/setup.js"
}, },
"engines": { "engines": {
@ -23,14 +23,9 @@
"pg": "^8.13.3", "pg": "^8.13.3",
"pg-hstore": "^2.3.4", "pg-hstore": "^2.3.4",
"sequelize": "^6.37.5", "sequelize": "^6.37.5",
"sqlite3": "^5.1.7", "sqlite3": "^5.1.7"
"uuid": "^11.1.0"
}, },
"devDependencies": { "devDependencies": {
"cross-env": "^7.0.3", "sequelize-cli": "^6.6.2"
"dotenv": "^16.4.7",
"jest": "^29.7.0",
"sequelize-cli": "^6.6.2",
"supertest": "^7.0.0"
} }
} }

View File

@ -20,5 +20,4 @@ module.exports = function(app) {
); );
app.post("/api/auth/signin", controller.signin); app.post("/api/auth/signin", controller.signin);
app.post("/api/auth/refreshtoken", controller.refreshToken); };
};

View File

@ -1,10 +0,0 @@
module.exports = {
secret: "bullpen-secret-key",
// jwtExpiration: 3600, // 1 hour
// jwtRefreshExpiration: 86400, // 24 hours
/* for test */
jwtExpiration: 60, // 1 minute
jwtRefreshExpiration: 120 // 2 minutes
};

View File

@ -1,36 +0,0 @@
const { DataTypes } = require('sequelize');
const config = require("../config/auth.config");
const { v4: uuidv4 } = require("uuid");
module.exports = (sequelize) => {
const RefreshToken = sequelize.define("refreshToken", {
token: {
type: DataTypes.STRING,
},
expiryDate: {
type: DataTypes.DATE,
},
});
RefreshToken.createToken = async function (user) {
let expiredAt = new Date();
expiredAt.setSeconds(expiredAt.getSeconds() + config.jwtRefreshExpiration);
let _token = uuidv4();
let refreshToken = await this.create({
token: _token,
userId: user.id,
expiryDate: expiredAt.getTime(),
});
return refreshToken.token;
};
RefreshToken.verifyExpiration = (token) => {
return token.expiryDate.getTime() < new Date().getTime();
};
return RefreshToken;
};

View File

@ -1,7 +0,0 @@
const signupUser = {
firstName: "Hans",
lastName: "Zimmer",
dateOfBirth: "1956-11-23",
email: "hans.zimmer@email.com",
password: "secret123"
}

View File

@ -1,19 +0,0 @@
const request = require("supertest")
const app = require("../src/index")
const { signupUser } = require("data/user.test.data")
require("dotenv").config();
describe("GET /api/auth/signup", () => {
it("should signup a user", async () => {
return request(app)
.post("/api/auth/signup")
.send(signupUser)
.expect('Content-Type', /json/)
.expect(200)
.then((res) => {
expect(res.statusCode).toBe(200);
})
});
});