Compare commits
4 Commits
677f929f1c
...
751953ae70
| Author | SHA1 | Date |
|---|---|---|
|
|
751953ae70 | |
|
|
fa2dd0d0cc | |
|
|
394ca64c34 | |
|
|
5d9f9c89fc |
|
|
@ -18,7 +18,7 @@ app.use(express.urlencoded({ extended: true }));
|
||||||
const db = require("./models");
|
const db = require("./models");
|
||||||
const Role = db.Role;
|
const Role = db.Role;
|
||||||
const User = db.User;
|
const User = db.User;
|
||||||
const PitchType = db.pitchType;
|
const PitchType = db.PitchType;
|
||||||
|
|
||||||
db.sequelize.sync();
|
db.sequelize.sync();
|
||||||
// force: true will drop the table if it already exists
|
// force: true will drop the table if it already exists
|
||||||
|
|
@ -36,12 +36,12 @@ app.get("/", (req, res) => {
|
||||||
require('./routes/auth.routes')(app);
|
require('./routes/auth.routes')(app);
|
||||||
require('./routes/user.routes')(app);
|
require('./routes/user.routes')(app);
|
||||||
require('./routes/pitchType.routes')(app);
|
require('./routes/pitchType.routes')(app);
|
||||||
|
require('./routes/bullpenSession.routes')(app);
|
||||||
|
|
||||||
function initial() {
|
function initial() {
|
||||||
Role.bulkCreate([
|
Role.bulkCreate([
|
||||||
{ name: 'user' },
|
{ name: 'user' },
|
||||||
{ name: 'moderator' },
|
{ name: 'administrator' },
|
||||||
{ name: 'administrato' },
|
|
||||||
]);
|
]);
|
||||||
User.bulkCreate([
|
User.bulkCreate([
|
||||||
{ firstName: 'Nolan', lastName: 'Ryan', dateOfBirth: new Date(1947, 1, 31), email: 'ryan.nolan@bullpen.com', password: bcrypt.hashSync('nolan', 8) },
|
{ firstName: 'Nolan', lastName: 'Ryan', dateOfBirth: new Date(1947, 1, 31), email: 'ryan.nolan@bullpen.com', password: bcrypt.hashSync('nolan', 8) },
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@ const Op = db.Sequelize.Op;
|
||||||
|
|
||||||
const jwt = require("jsonwebtoken");
|
const jwt = require("jsonwebtoken");
|
||||||
|
|
||||||
exports.signup = (req, res) => {
|
exports.register = (req, res) => {
|
||||||
// Save User to Database
|
// Save User to Database
|
||||||
User.create({
|
User.create({
|
||||||
firstName: req.body.firstName,
|
firstName: req.body.firstName,
|
||||||
|
|
@ -42,7 +42,7 @@ exports.signup = (req, res) => {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
exports.signin = (req, res) => {
|
exports.login = (req, res) => {
|
||||||
User.findOne({
|
User.findOne({
|
||||||
where: {
|
where: {
|
||||||
email: req.body.email
|
email: req.body.email
|
||||||
|
|
@ -92,6 +92,10 @@ exports.signin = (req, res) => {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
exports.logout = (req, res) => {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
exports.refreshToken = async (req, res) => {
|
exports.refreshToken = async (req, res) => {
|
||||||
const { refreshToken: requestToken } = req.body;
|
const { refreshToken: requestToken } = req.body;
|
||||||
|
|
||||||
|
|
@ -113,7 +117,7 @@ exports.refreshToken = async (req, res) => {
|
||||||
RefreshToken.destroy({ where: { id: refreshToken.id } });
|
RefreshToken.destroy({ where: { id: refreshToken.id } });
|
||||||
|
|
||||||
res.status(403).json({
|
res.status(403).json({
|
||||||
message: "Refresh token was expired. Please make a new signin request",
|
message: "Refresh token was expired. Please make a new login request",
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,53 @@
|
||||||
|
const db = require("../models/index");
|
||||||
|
const BullpenSession = db.BullpenSession;
|
||||||
|
const Pitch = db.Pitch;
|
||||||
|
|
||||||
|
exports.insert = (req, res) => {
|
||||||
|
BullpenSession.create(req.body, { include: [{
|
||||||
|
model: Pitch,
|
||||||
|
as: 'pitches'
|
||||||
|
}]}
|
||||||
|
)
|
||||||
|
.then(bullpenSession => {
|
||||||
|
return res.status(201).send(bullpenSession);
|
||||||
|
})
|
||||||
|
.catch(err => {
|
||||||
|
res.status(500).send({ message: err.message });
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.findAll = (req, res) => {
|
||||||
|
BullpenSession.findAll({
|
||||||
|
include: {
|
||||||
|
model: Pitch,
|
||||||
|
as: 'pitches'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.then(bullpenSessions => {
|
||||||
|
res.status(200).send(bullpenSessions);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
exports.findOne = (req, res) => {
|
||||||
|
const id = req.params.id;
|
||||||
|
BullpenSession.findByPk(id, {
|
||||||
|
include: {
|
||||||
|
model: Pitch,
|
||||||
|
as: 'pitches'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.then(data => {
|
||||||
|
if (data) {
|
||||||
|
res.send(data);
|
||||||
|
} else {
|
||||||
|
res.status(404).send({
|
||||||
|
message: `Cannot find bullpen session with id=${id}.`
|
||||||
|
});
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(err => {
|
||||||
|
res.status(500).send({
|
||||||
|
message: `Error retrieving bullpen session with id=${id}: ${err.message}`
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
@ -1,6 +1,5 @@
|
||||||
const db = require("../models/index");
|
const db = require("../models/index");
|
||||||
const PitchType = db.pitchType;
|
const PitchType = db.PitchType;
|
||||||
const Op = db.Sequelize.Op;
|
|
||||||
|
|
||||||
exports.findAll = (req, res) => {
|
exports.findAll = (req, res) => {
|
||||||
PitchType.findAll()
|
PitchType.findAll()
|
||||||
|
|
@ -30,7 +29,7 @@ exports.findOne = (req, res) => {
|
||||||
})
|
})
|
||||||
.catch(err => {
|
.catch(err => {
|
||||||
res.status(500).send({
|
res.status(500).send({
|
||||||
message: "Error retrieving pitch type with id=" + id
|
message: `Error retrieving pitch type with id=${id}: ${err.message}`
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -27,6 +27,9 @@ module.exports = {
|
||||||
onUpdate: 'CASCADE',
|
onUpdate: 'CASCADE',
|
||||||
onDelete: 'CASCADE'
|
onDelete: 'CASCADE'
|
||||||
},
|
},
|
||||||
|
pitchTime: {
|
||||||
|
type: Sequelize.DATE,
|
||||||
|
},
|
||||||
aimedArea: {
|
aimedArea: {
|
||||||
type: Sequelize.INTEGER
|
type: Sequelize.INTEGER
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,5 @@
|
||||||
'use strict';
|
'use strict';
|
||||||
const {
|
const { Model } = require('sequelize');
|
||||||
Model
|
|
||||||
} = require('sequelize');
|
|
||||||
module.exports = (sequelize, DataTypes) => {
|
module.exports = (sequelize, DataTypes) => {
|
||||||
class BullpenSession extends Model {
|
class BullpenSession extends Model {
|
||||||
/**
|
/**
|
||||||
|
|
@ -15,19 +13,11 @@ module.exports = (sequelize, DataTypes) => {
|
||||||
as: 'pitches',
|
as: 'pitches',
|
||||||
});
|
});
|
||||||
BullpenSession.belongsTo(models.User, {
|
BullpenSession.belongsTo(models.User, {
|
||||||
as: "pitcher"
|
foreignKey: "pitcherId"
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
BullpenSession.init({
|
BullpenSession.init({
|
||||||
pitcherId: {
|
|
||||||
type: DataTypes.INTEGER,
|
|
||||||
allowNull: false,
|
|
||||||
references: {
|
|
||||||
model: 'User',
|
|
||||||
key: 'id'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
startedAt: {
|
startedAt: {
|
||||||
type: DataTypes.DATE,
|
type: DataTypes.DATE,
|
||||||
allowNull: false,
|
allowNull: false,
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,4 @@
|
||||||
'use strict';
|
const { Model } = require('sequelize');
|
||||||
const {
|
|
||||||
Model, DataTypes
|
|
||||||
} = require('sequelize');
|
|
||||||
module.exports = (sequelize, DataTypes) => {
|
module.exports = (sequelize, DataTypes) => {
|
||||||
class Pitch extends Model {
|
class Pitch extends Model {
|
||||||
/**
|
/**
|
||||||
|
|
@ -12,27 +9,16 @@ module.exports = (sequelize, DataTypes) => {
|
||||||
static associate(models) {
|
static associate(models) {
|
||||||
Pitch.belongsTo(models.BullpenSession, {
|
Pitch.belongsTo(models.BullpenSession, {
|
||||||
foreignKey: 'bullpenSessionId',
|
foreignKey: 'bullpenSessionId',
|
||||||
as: 'bullpenSession'
|
|
||||||
});
|
});
|
||||||
Pitch.belongsTo(models.PitchType);
|
Pitch.belongsTo(models.PitchType, {
|
||||||
|
foreignKey: 'pitchTypeId'
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Pitch.init({
|
Pitch.init({
|
||||||
pitchTypeId: {
|
pitchTime: {
|
||||||
type: DataTypes.INTEGER,
|
type: DataTypes.DATE,
|
||||||
allowNull: false,
|
allowNull: false
|
||||||
references: { // User belongsTo PitchType 1:1
|
|
||||||
model: 'PitchTypes',
|
|
||||||
key: 'id'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
bullpenSessionId: {
|
|
||||||
type: DataTypes.INTEGER,
|
|
||||||
allowNull: false,
|
|
||||||
references: {
|
|
||||||
model: 'BullpenSessions',
|
|
||||||
key: 'id'
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
aimedArea: {
|
aimedArea: {
|
||||||
type: DataTypes.INTEGER,
|
type: DataTypes.INTEGER,
|
||||||
|
|
|
||||||
|
|
@ -11,14 +11,15 @@ module.exports = function(app) {
|
||||||
});
|
});
|
||||||
|
|
||||||
app.post(
|
app.post(
|
||||||
"/api/auth/signup",
|
"/api/auth/register",
|
||||||
[
|
[
|
||||||
verifySignUp.checkDuplicateUsernameOrEmail,
|
verifySignUp.checkDuplicateUsernameOrEmail,
|
||||||
verifySignUp.checkRolesExisted
|
verifySignUp.checkRolesExisted
|
||||||
],
|
],
|
||||||
controller.signup
|
controller.register
|
||||||
);
|
);
|
||||||
|
|
||||||
app.post("/api/auth/signin", controller.signin);
|
app.post("/api/auth/login", controller.login);
|
||||||
|
app.post("/api/auth/logout", controller.logout);
|
||||||
app.post("/api/auth/refreshtoken", controller.refreshToken);
|
app.post("/api/auth/refreshtoken", controller.refreshToken);
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,25 @@
|
||||||
|
const { authJwt } = require("../middleware");
|
||||||
|
const controller = require("../controllers/bullpenSession.controller");
|
||||||
|
|
||||||
|
module.exports = function(app) {
|
||||||
|
app.use(function(req, res, next) {
|
||||||
|
res.header(
|
||||||
|
"Access-Control-Allow-Headers",
|
||||||
|
"x-access-token, Origin, Content-Type, Accept"
|
||||||
|
);
|
||||||
|
next();
|
||||||
|
});
|
||||||
|
|
||||||
|
app.post(
|
||||||
|
"/api/bullpen_session",
|
||||||
|
[authJwt.verifyToken],
|
||||||
|
controller.insert);
|
||||||
|
app.get(
|
||||||
|
"/api/bullpen_session",
|
||||||
|
[authJwt.verifyToken],
|
||||||
|
controller.findAll);
|
||||||
|
app.get(
|
||||||
|
"/api/bullpen_session/:id",
|
||||||
|
[authJwt.verifyToken],
|
||||||
|
controller.findOne);
|
||||||
|
};
|
||||||
|
|
@ -10,6 +10,12 @@ module.exports = function(app) {
|
||||||
next();
|
next();
|
||||||
});
|
});
|
||||||
|
|
||||||
app.get("/api/pitch_types", controller.findAll);
|
app.get(
|
||||||
app.get("/api/pitch_types/:id", controller.findOne);
|
"/api/pitch_types",
|
||||||
|
[authJwt.verifyToken],
|
||||||
|
controller.findAll);
|
||||||
|
app.get(
|
||||||
|
"/api/pitch_types/:id",
|
||||||
|
[authJwt.verifyToken],
|
||||||
|
controller.findOne);
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -17,11 +17,6 @@ module.exports = {
|
||||||
},
|
},
|
||||||
|
|
||||||
async down (queryInterface, Sequelize) {
|
async down (queryInterface, Sequelize) {
|
||||||
/**
|
return queryInterface.dropTable('Roles');
|
||||||
* Add commands to revert seed here.
|
|
||||||
*
|
|
||||||
* Example:
|
|
||||||
* await queryInterface.bulkDelete('People', null, {});
|
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -15,11 +15,6 @@ module.exports = {
|
||||||
},
|
},
|
||||||
|
|
||||||
async down (queryInterface, Sequelize) {
|
async down (queryInterface, Sequelize) {
|
||||||
/**
|
return queryInterface.dropTable('Users');
|
||||||
* Add commands to revert seed here.
|
|
||||||
*
|
|
||||||
* Example:
|
|
||||||
* await queryInterface.bulkDelete('People', null, {});
|
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -1,25 +1,18 @@
|
||||||
'use strict';
|
|
||||||
|
|
||||||
/** @type {import('sequelize-cli').Migration} */
|
/** @type {import('sequelize-cli').Migration} */
|
||||||
module.exports = {
|
module.exports = {
|
||||||
async up (queryInterface, Sequelize) {
|
async up (queryInterface, Sequelize) {
|
||||||
/**
|
return queryInterface.bulkInsert('PitchTypes',[
|
||||||
* Add seed commands here.
|
{ name: 'Fastball', abbreviation: 'FB', createdAt: new Date(), updatedAt: new Date() },
|
||||||
*
|
{ name: 'Curveball', abbreviation: 'CB', createdAt: new Date(), updatedAt: new Date() },
|
||||||
* Example:
|
{ name: 'Slider', abbreviation: 'SL', createdAt: new Date(), updatedAt: new Date() },
|
||||||
* await queryInterface.bulkInsert('People', [{
|
{ name: 'Changeup', abbreviation: 'CH', createdAt: new Date(), updatedAt: new Date() },
|
||||||
* name: 'John Doe',
|
{ name: 'Cutter', abbreviation: 'CUT', createdAt: new Date(), updatedAt: new Date() },
|
||||||
* isBetaMember: false
|
{ name: 'Sweeper', abbreviation: 'SW', createdAt: new Date(), updatedAt: new Date() },
|
||||||
* }], {});
|
{ name: 'Slurve', abbreviation: 'SLV', createdAt: new Date(), updatedAt: new Date() },
|
||||||
*/
|
]);
|
||||||
},
|
},
|
||||||
|
|
||||||
async down (queryInterface, Sequelize) {
|
async down (queryInterface, Sequelize) {
|
||||||
/**
|
return queryInterface.dropTable('PitchTypes');
|
||||||
* Add commands to revert seed here.
|
|
||||||
*
|
|
||||||
* Example:
|
|
||||||
* await queryInterface.bulkDelete('People', null, {});
|
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,43 @@
|
||||||
|
const request = require("supertest")
|
||||||
|
const {
|
||||||
|
expect,
|
||||||
|
describe,
|
||||||
|
test,
|
||||||
|
} = require('@jest/globals');
|
||||||
|
|
||||||
|
const app = require("../app")
|
||||||
|
|
||||||
|
const { bullpenSession } = require("./data/bullpenSession.test.data")
|
||||||
|
|
||||||
|
describe("Test bullpen session", () => {
|
||||||
|
test("should create bullpen session with pitches", async () => {
|
||||||
|
let response = await request(app)
|
||||||
|
.post("/api/auth/login")
|
||||||
|
.send({
|
||||||
|
email: 'ryan.nolan@bullpen.com',
|
||||||
|
password: 'nolan'
|
||||||
|
});
|
||||||
|
const user = response.body;
|
||||||
|
|
||||||
|
response = await request(app)
|
||||||
|
.post("/api/bullpen_session")
|
||||||
|
.set('x-access-token', user.accessToken)
|
||||||
|
.send(bullpenSession);
|
||||||
|
|
||||||
|
expect(response.statusCode).toBe(201);
|
||||||
|
const bullpenSessionData = await response.body;
|
||||||
|
expect(bullpenSessionData).toBeDefined();
|
||||||
|
expect(bullpenSessionData.id).toBeDefined();
|
||||||
|
expect(bullpenSessionData.id).toBeGreaterThan(0);
|
||||||
|
expect(bullpenSessionData.pitches).toBeDefined();
|
||||||
|
expect(Array.isArray(bullpenSessionData.pitches)).toBe(true);
|
||||||
|
expect(bullpenSessionData.pitches.length).toBe(2);
|
||||||
|
|
||||||
|
response = await request(app)
|
||||||
|
.get(`/api/bullpen_session/${bullpenSessionData.id}`)
|
||||||
|
.set('x-access-token', user.accessToken);
|
||||||
|
expect(response.statusCode).toBe(200);
|
||||||
|
|
||||||
|
console.log(JSON.stringify(response.body, null, 2));
|
||||||
|
});
|
||||||
|
})
|
||||||
|
|
@ -0,0 +1,20 @@
|
||||||
|
const bullpenSession = {
|
||||||
|
pitcherId: 1,
|
||||||
|
startedAt: new Date(2025, 3, 22, 16, 5, 13),
|
||||||
|
finishedAt: new Date(2025, 3, 22, 16, 23, 45),
|
||||||
|
pitches: [{
|
||||||
|
pitchTypeId: 1,
|
||||||
|
pitchTime: new Date(2025, 3, 22, 16, 7, 21),
|
||||||
|
aimedArea: 11,
|
||||||
|
hitArea: 12
|
||||||
|
}, {
|
||||||
|
pitchTypeId: 4,
|
||||||
|
pitchTime: new Date(2025, 3, 22, 16, 9, 57),
|
||||||
|
aimedArea: 6,
|
||||||
|
hitArea: 14
|
||||||
|
}]
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
bullpenSession
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,26 @@
|
||||||
|
const request = require("supertest")
|
||||||
|
const {
|
||||||
|
expect,
|
||||||
|
describe,
|
||||||
|
test,
|
||||||
|
} = require('@jest/globals');
|
||||||
|
|
||||||
|
const app = require("../app")
|
||||||
|
|
||||||
|
describe("Test retrieving pitch types", () => {
|
||||||
|
test("should retrieve all pitch types", async () => {
|
||||||
|
let response = await request(app)
|
||||||
|
.post("/api/auth/login")
|
||||||
|
.send({
|
||||||
|
email: 'ryan.nolan@bullpen.com',
|
||||||
|
password: 'nolan'
|
||||||
|
});
|
||||||
|
const user = response.body;
|
||||||
|
|
||||||
|
response = await request(app)
|
||||||
|
.get('/api/pitch_types')
|
||||||
|
.set('x-access-token', user.accessToken);
|
||||||
|
expect(response.statusCode).toBe(200);
|
||||||
|
expect(response.body.length).toEqual(7);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
@ -3,45 +3,34 @@ const {
|
||||||
expect,
|
expect,
|
||||||
describe,
|
describe,
|
||||||
test,
|
test,
|
||||||
beforeAll,
|
|
||||||
afterAll,
|
|
||||||
} = require('@jest/globals');
|
} = require('@jest/globals');
|
||||||
|
|
||||||
const app = require("../app")
|
const app = require("../app")
|
||||||
|
|
||||||
const { signupUser } = require("./data/user.test.data")
|
const { signupUser } = require("./data/user.test.data")
|
||||||
const res = require("express/lib/response");
|
|
||||||
|
|
||||||
describe("Test user authentication", () => {
|
describe("Test user authentication", () => {
|
||||||
test("should signup a user", async () => {
|
test("should register a user", async () => {
|
||||||
const response = await request(app)
|
const response = await request(app)
|
||||||
.post("/api/auth/signup")
|
.post("/api/auth/register")
|
||||||
.send(signupUser);
|
.send(signupUser);
|
||||||
|
|
||||||
expect(response.header['content-type']).toBe('application/json; charset=utf-8');
|
expect(response.header['content-type']).toBe('application/json; charset=utf-8');
|
||||||
expect(response.statusCode).toBe(200);
|
expect(response.statusCode).toBe(200);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("Test user login", async () => {
|
test("Test user login", async() => {
|
||||||
let user = {};
|
|
||||||
let response = await request(app)
|
let response = await request(app)
|
||||||
.post("/api/auth/signin")
|
.post("/api/auth/login")
|
||||||
.send({
|
.send({
|
||||||
email: 'ryan.nolan@bullpen.com',
|
email: 'ryan.nolan@bullpen.com',
|
||||||
password: 'nolan'
|
password: 'nolan'
|
||||||
});
|
});
|
||||||
expect(response.statusCode).toBe(200);
|
expect(response.statusCode).toBe(200);
|
||||||
expect(response.body.accessToken).not.toBeNull();
|
expect(response.body.accessToken).not.toBeNull();
|
||||||
user = response.body;
|
const user = response.body;
|
||||||
|
|
||||||
response = await request(app)
|
|
||||||
.get(`/api/users/${user.id}`);
|
|
||||||
expect(response.statusCode).toBe(403);
|
|
||||||
|
|
||||||
response = await request(app)
|
response = await request(app)
|
||||||
.get(`/api/users/${user.id}`)
|
.get(`/api/users/${user.id}`)
|
||||||
.set('x-access-token', user.accessToken);
|
.set('x-access-token', user.accessToken);
|
||||||
console.log(response.body);
|
|
||||||
expect(response.statusCode).toBe(200);
|
expect(response.statusCode).toBe(200);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue