Compare commits

..

No commits in common. "003d4d9d1321634d102c971b685397bf1fd963b1" and "35d86335671c7b1ef29933361420c0a771d20ce8" have entirely different histories.

32 changed files with 73 additions and 511 deletions

View File

@ -15,8 +15,6 @@ require('./routes/info.routes')(app);
require('./routes/auth.routes')(app); require('./routes/auth.routes')(app);
require('./routes/user.routes')(app); require('./routes/user.routes')(app);
require('./routes/player.routes')(app); require('./routes/player.routes')(app);
require('./routes/team.routes')(app);
require('./routes/position.routes')(app);
require('./routes/pitchType.routes')(app); require('./routes/pitchType.routes')(app);
require('./routes/bullpenSession.routes')(app); require('./routes/bullpenSession.routes')(app);

View File

@ -3,23 +3,8 @@ const {registerUser} = require("../helper/user.helper");
const Player = db.Player; const Player = db.Player;
const User = db.User; const User = db.User;
const Auth = db.Auth; const Auth = db.Auth;
const Team = db.Team;
const Op = db.Sequelize.Op; const Op = db.Sequelize.Op;
const includeParams = [{
model: User,
as: 'user',
include: {
model: Auth,
as: 'auth',
attributes: ['email']
}
}, {
model: Team,
as: 'teams',
attributes: ['name']
}];
exports.insert = (req, res) => { exports.insert = (req, res) => {
registerUser(req.body.user).then(user => { registerUser(req.body.user).then(user => {
return Player.create({ return Player.create({
@ -35,9 +20,7 @@ exports.insert = (req, res) => {
jerseyNumber: req.body.jerseyNumber, jerseyNumber: req.body.jerseyNumber,
userId: user.id userId: user.id
}).then(player => { }).then(player => {
return player.reload({ return player.reload({ include: { model: User }});
include: includeParams
});
}); });
}).then(player => { }).then(player => {
res.status(201).send(player); res.status(201).send(player);
@ -52,7 +35,7 @@ exports.findAll = (req, res) => {
Player.findAll({ Player.findAll({
where: condition, where: condition,
include: includeParams include: ['user']
}).then(data => { }).then(data => {
res.send(data); res.send(data);
}).catch(err => { }).catch(err => {
@ -64,7 +47,15 @@ exports.findOne = (req, res) => {
const id = req.params.id; const id = req.params.id;
Player.findByPk(id, { Player.findByPk(id, {
include: includeParams include: {
model: User,
as: 'user',
include: {
model: Auth,
as: 'auth',
attributes: ['email']
}
}
}).then(data => { }).then(data => {
if (data) { if (data) {
res.send(data); res.send(data);
@ -81,7 +72,15 @@ exports.findOneByUserId = (req, res) => {
Player.findOne({ Player.findOne({
where: { userId: userId }, where: { userId: userId },
include: includeParams include: {
model: User,
as: 'user',
include: {
model: Auth,
as: 'auth',
attributes: ['email']
}
}
}).then(data => { }).then(data => {
if (data) { if (data) {
res.send(data); res.send(data);

View File

@ -1,35 +0,0 @@
const db = require("../models/index");
const Position = db.Position;
exports.findAll = (req, res) => {
Position.findAll()
.then(data => {
res.send(data);
})
.catch(err => {
res.status(500).send({
message:
err.message || "Some error occurred while retrieving pitch types."
});
});
};
exports.findOne = (req, res) => {
const id = req.params.id;
Position.findByPk(id)
.then(data => {
if (data) {
res.send(data);
} else {
res.status(404).send({
message: `Cannot find pitch type with id=${id}.`
});
}
})
.catch(err => {
res.status(500).send({
message: `Error retrieving pitch type with id=${id}: ${err.message}`
});
});
};

View File

@ -1,17 +1,8 @@
const db = require("../models/index"); const db = require("../models/index");
const Team = db.Team; const Team = db.Team;
const Player = db.Player;
const Op = db.Sequelize.Op; const Op = db.Sequelize.Op;
exports.insert = (req, res) => {
Team.create(req.body)
.then(team => {
return res.status(201).send(team);
})
.catch(err => {
res.status(500).send({ message: err.message });
});
}
exports.findAll = (req, res) => { exports.findAll = (req, res) => {
const title = req.query.title; const title = req.query.title;
const condition = title ? {title: {[Op.iLike]: `%${title}%`}} : null; const condition = title ? {title: {[Op.iLike]: `%${title}%`}} : null;
@ -43,48 +34,8 @@ exports.findOne = (req, res) => {
}); });
}; };
exports.addPlayer = async (req, res) => { exports.addPlayer = (req, res) => {
const teamId = req.params.id; const id = req.params.id;
const { playerIds } = req.body; const playerId = req.params.playerId;
try {
// Fetch the team by ID
const team = await Team.findByPk(teamId);
if (!team) {
return res.status(404).send({ message: `Team with id=${teamId} not found.` });
}
// Add multiple players to the team
await team.addPlayers(playerIds);
res.status(200).send({ message: `Players added to team with id=${teamId} successfully.` });
} catch (err) {
res.status(500).send({
message: `Error adding players to team with id=${teamId}: ${err.message}`
});
}
}
exports.removePlayer = async (req, res) => {
const teamId = req.params.id;
const { playerIds } = req.body;
try {
// Fetch the team by ID
const team = await Team.findByPk(teamId);
if (!team) {
return res.status(404).send({ message: `Team with id=${teamId} not found.` });
}
// Add multiple players to the team
await team.removePlayers(playerIds);
res.status(200).send({ message: `Players added to team with id=${teamId} successfully.` });
} catch (err) {
res.status(500).send({
message: `Error adding players to team with id=${teamId}: ${err.message}`
});
}
} }

View File

@ -6,8 +6,8 @@ const { Auth: Auth, User: User, Role: Role } = db;
const registerUser = (user) => { const registerUser = (user) => {
return Auth.create({ return Auth.create({
email: user.auth.email, email: user.email,
password: user.auth.password password: user.password
}).then((auth) => { }).then((auth) => {
return User.create({ return User.create({
firstName: user.firstName, firstName: user.firstName,

View File

@ -2,15 +2,7 @@ const db = require("./models/index");
const { beforeAll, afterAll } = require('@jest/globals'); const { beforeAll, afterAll } = require('@jest/globals');
const { const { Auth: Auth, User: User, Player: Player, Role: Role, PitchType: PitchType } = db;
Auth: Auth,
User: User,
Player: Player,
Role: Role,
PitchType: PitchType,
Team: Team,
Position: Position
} = db;
const Op = db.Sequelize.Op; const Op = db.Sequelize.Op;
beforeAll(async () => { beforeAll(async () => {
@ -39,7 +31,6 @@ beforeAll(async () => {
await Auth.destroy({ where: {} }); await Auth.destroy({ where: {} });
await User.destroy({ where: {} }); await User.destroy({ where: {} });
await Player.destroy({ where: {} }); await Player.destroy({ where: {} });
await Team.destroy({ where: {} });
await Auth.create({ await Auth.create({
email: 'player@example.com', password: 'hash1234' email: 'player@example.com', password: 'hash1234'
}).then(auth => { }).then(auth => {
@ -85,19 +76,6 @@ beforeAll(async () => {
{ name: 'Sweeper', abbreviation: 'SW' }, { name: 'Sweeper', abbreviation: 'SW' },
{ name: 'Slurve', abbreviation: 'SLV' } { name: 'Slurve', abbreviation: 'SLV' }
]); ]);
await Position.destroy({ where: {} });
await Position.bulkCreate([
{ name: 'Pitcher', abbreviation: 'P', description: '' },
{ name: 'Catcher', abbreviation: 'C', description: '' },
{ name: 'First Baseman', abbreviation: '1B', description: '' },
{ name: 'Second Baseman', abbreviation: '2B', description: '' },
{ name: 'Third Baseman', abbreviation: '3B', description: '' },
{ name: 'Short Stop', abbreviation: 'SS', description: '' },
{ name: 'Left Fielder', abbreviation: 'LF', description: '' },
{ name: 'Center Fielder', abbreviation: 'CF', description: '' },
{ name: 'Right Fielder', abbreviation: 'RF', description: '' },
]);
}); });
afterAll(async () => { afterAll(async () => {

View File

@ -5,7 +5,7 @@ checkDuplicateUsernameOrEmail = (req, res, next) => {
// Username // Username
Auth.findOne({ Auth.findOne({
where: { where: {
email: req.body.auth.email email: req.body.email
} }
}).then(auth => { }).then(auth => {
if (auth) { if (auth) {
@ -16,8 +16,6 @@ checkDuplicateUsernameOrEmail = (req, res, next) => {
} }
next(); next();
}).catch(err => {
return res.status(500).send({ message: err });
}); });
}; };

View File

@ -1,3 +1,4 @@
'use strict';
/** @type {import('sequelize-cli').Migration} */ /** @type {import('sequelize-cli').Migration} */
module.exports = { module.exports = {
async up(queryInterface, Sequelize) { async up(queryInterface, Sequelize) {
@ -21,7 +22,7 @@ module.exports = {
} }
}); });
}, },
async down(queryInterface, _Sequelize) { async down(queryInterface, Sequelize) {
await queryInterface.dropTable('Roles'); await queryInterface.dropTable('Roles');
} }
}; };

View File

@ -1,3 +1,5 @@
'use strict';
/** @type {import('sequelize-cli').Migration} */ /** @type {import('sequelize-cli').Migration} */
module.exports = { module.exports = {
async up (queryInterface, Sequelize) { async up (queryInterface, Sequelize) {
@ -37,7 +39,7 @@ module.exports = {
}); });
}, },
async down (queryInterface, _Sequelize) { async down (queryInterface, Sequelize) {
await queryInterface.dropTable('UserRoles'); await queryInterface.dropTable('UserRoles');
} }
}; };

View File

@ -1,3 +1,4 @@
'use strict';
/** @type {import('sequelize-cli').Migration} */ /** @type {import('sequelize-cli').Migration} */
module.exports = { module.exports = {
async up(queryInterface, Sequelize) { async up(queryInterface, Sequelize) {

View File

@ -1,3 +1,4 @@
'use strict';
/** @type {import('sequelize-cli').Migration} */ /** @type {import('sequelize-cli').Migration} */
module.exports = { module.exports = {
async up(queryInterface, Sequelize) { async up(queryInterface, Sequelize) {
@ -24,7 +25,7 @@ module.exports = {
} }
}); });
}, },
async down(queryInterface, _Sequelize) { async down(queryInterface, Sequelize) {
await queryInterface.dropTable('PitchTypes'); await queryInterface.dropTable('PitchTypes');
} }
}; };

View File

@ -1,3 +1,4 @@
'use strict';
/** @type {import('sequelize-cli').Migration} */ /** @type {import('sequelize-cli').Migration} */
module.exports = { module.exports = {
async up(queryInterface, Sequelize) { async up(queryInterface, Sequelize) {
@ -27,7 +28,7 @@ module.exports = {
} }
}); });
}, },
async down(queryInterface, _Sequelize) { async down(queryInterface, Sequelize) {
await queryInterface.dropTable('BullpenSessions'); await queryInterface.dropTable('BullpenSessions');
} }
}; };

View File

@ -1,3 +1,4 @@
'use strict';
/** @type {import('sequelize-cli').Migration} */ /** @type {import('sequelize-cli').Migration} */
module.exports = { module.exports = {
async up(queryInterface, Sequelize) { async up(queryInterface, Sequelize) {
@ -45,7 +46,7 @@ module.exports = {
} }
}); });
}, },
async down(queryInterface, _Sequelize) { async down(queryInterface, Sequelize) {
await queryInterface.dropTable('Pitches'); await queryInterface.dropTable('Pitches');
} }
}; };

View File

@ -1,37 +0,0 @@
/** @type {import('sequelize-cli').Migration} */
module.exports = {
async up(queryInterface, Sequelize) {
await queryInterface.createTable('Positions', {
id: {
allowNull: false,
autoIncrement: true,
primaryKey: true,
type: Sequelize.INTEGER
},
name: {
type: Sequelize.STRING,
allowNull: false,
unique: true
},
abbreviation: {
type: Sequelize.STRING,
allowNull: false
},
description: {
type: Sequelize.STRING,
allowNull: false
},
createdAt: {
allowNull: false,
type: Sequelize.DATE
},
updatedAt: {
allowNull: false,
type: Sequelize.DATE
}
});
},
async down(queryInterface, _Sequelize) {
await queryInterface.dropTable('Positions');
}
};

View File

@ -1,39 +0,0 @@
/** @type {import('sequelize-cli').Migration} */
module.exports = {
async up (queryInterface, Sequelize) {
await queryInterface.createTable('PlayerPositions', {
id: {
allowNull: false,
autoIncrement: true,
primaryKey: true,
type: Sequelize.INTEGER
},
playerId: {
type: Sequelize.INTEGER,
references: {
model: 'Players',
key: 'id'
}
},
positionId: {
type: Sequelize.INTEGER,
references: {
model: 'Positions',
key: 'id'
}
},
createdAt: {
allowNull: false,
type: Sequelize.DATE
},
updatedAt: {
allowNull: false,
type: Sequelize.DATE
}
});
},
async down (queryInterface, _Sequelize) {
await queryInterface.dropTable('PlayerPositions');
}
};

View File

View File

@ -1,33 +0,0 @@
/** @type {import('sequelize-cli').Migration} */
module.exports = {
async up(queryInterface, Sequelize) {
await queryInterface.createTable('Teams', {
id: {
allowNull: false,
autoIncrement: true,
primaryKey: true,
type: Sequelize.INTEGER
},
name: {
type: Sequelize.STRING,
allowNull: false,
unique: true
},
description: {
type: Sequelize.STRING,
allowNull: false
},
createdAt: {
allowNull: false,
type: Sequelize.DATE
},
updatedAt: {
allowNull: false,
type: Sequelize.DATE
}
});
},
async down(queryInterface, _Sequelize) {
await queryInterface.dropTable('Teams');
}
};

View File

@ -48,6 +48,22 @@ module.exports = {
type: Sequelize.DATE type: Sequelize.DATE
} }
}); });
// 2. Kopiere Daten von Users nach Players
await queryInterface.sequelize.query(`
INSERT INTO "Players" ("userId", "height", "weight", "gender", "bats", "throws", "createdAt", "updatedAt")
SELECT
"id" as "userId",
"height",
"weight",
"gender"::text::"enum_Players_gender",
"handedness"::text::"enum_Players_bats",
"handedness"::text::"enum_Players_throws",
"createdAt",
"updatedAt"
FROM "Users"
`);
}, },
async down(queryInterface, /*Sequelize*/) { async down(queryInterface, /*Sequelize*/) {
await queryInterface.dropTable('Players'); await queryInterface.dropTable('Players');

View File

@ -1,39 +0,0 @@
/** @type {import('sequelize-cli').Migration} */
module.exports = {
async up (queryInterface, Sequelize) {
await queryInterface.createTable('PlayerTeams', {
id: {
allowNull: false,
autoIncrement: true,
primaryKey: true,
type: Sequelize.INTEGER
},
playerId: {
type: Sequelize.INTEGER,
references: {
model: 'Players',
key: 'id'
}
},
teamId: {
type: Sequelize.INTEGER,
references: {
model: 'Teams',
key: 'id'
}
},
createdAt: {
allowNull: false,
type: Sequelize.DATE
},
updatedAt: {
allowNull: false,
type: Sequelize.DATE
}
});
},
async down (queryInterface, _Sequelize) {
await queryInterface.dropTable('PlayerTeams');
}
};

View File

@ -1,22 +0,0 @@
/** @type {import('sequelize-cli').Migration} */
module.exports = {
async up(queryInterface, _Sequelize) {
await queryInterface.sequelize.query(`
INSERT INTO "Players" ("userId", "height", "weight", "gender", "bats", "throws", "createdAt", "updatedAt")
SELECT
"id" as "userId",
"height",
"weight",
"gender"::text::"enum_Players_gender",
"handedness"::text::"enum_Players_bats",
"handedness"::text::"enum_Players_throws",
"createdAt",
"updatedAt"
FROM "Users"
`);
},
async down(queryInterface, /*Sequelize*/) {
await queryInterface.dropTable('Players');
}
};

View File

@ -18,10 +18,8 @@ module.exports = (sequelize, DataTypes) => {
otherKey: 'teamId', otherKey: 'teamId',
as: 'teams', as: 'teams',
}); });
Player.belongsToMany(models.Position, { Player.hasMany(models.Position, {
through: "PlayerPositions", through: "PlayerPositions",
foreignKey: 'playerId',
otherKey: 'positionId',
as: 'positions', as: 'positions',
}) })
} }

View File

@ -7,12 +7,7 @@ module.exports = (sequelize, DataTypes) => {
* The `models/index` file will call this method automatically. * The `models/index` file will call this method automatically.
*/ */
static associate(models) { static associate(models) {
Position.belongsToMany(models.Player, { // define association here
through: "PlayerPositions",
foreignKey: 'positionId',
otherKey: 'playerId',
as: 'players',
});
} }
} }
Position.init({ Position.init({

View File

@ -1,21 +0,0 @@
const { authJwt } = require("../middleware");
const controller = require("../controllers/position.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.get(
"/api/positions",
[authJwt.verifyToken],
controller.findAll);
app.get(
"/api/positions/:id",
[authJwt.verifyToken],
controller.findOne);
};

View File

@ -1,33 +0,0 @@
const { authJwt } = require("../middleware");
const controller = require("../controllers/team.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/teams",
[authJwt.verifyToken, authJwt.isCoachOrAdmin],
controller.insert);
app.get(
"/api/teams",
[authJwt.verifyToken, authJwt.isCoachOrAdmin],
controller.findAll);
app.get(
"/api/teams/:id",
[authJwt.verifyToken, authJwt.isCoachOrAdmin],
controller.findOne);
app.put(
'/api/teams/:id/add_players',
[authJwt.verifyToken, authJwt.isCoachOrAdmin],
controller.addPlayer);
app.put(
'/api/teams/:id/remove_players',
[authJwt.verifyToken, authJwt.isCoachOrAdmin],
controller.removePlayer);
};

View File

@ -2,11 +2,9 @@ const signupUser = {
firstName: "Hans", firstName: "Hans",
lastName: "Zimmer", lastName: "Zimmer",
dateOfBirth: "1956-11-23", dateOfBirth: "1956-11-23",
roles: ['admin'],
auth: {
email: "hans.zimmer@email.com", email: "hans.zimmer@email.com",
password: "secret123" password: "secret123",
} roles: ['admin']
} }
module.exports = { module.exports = {

View File

@ -46,6 +46,6 @@ describe("Test player creation, authentication and retrieval", () => {
.set('x-access-token', user.accessToken); .set('x-access-token', user.accessToken);
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);
expect(response.body.filter(p => p.user.id === player.user.id).shift()).toEqual(player); expect(response.body.filter(p => p.User.id === player.User.id).shift()).toEqual(player);
}); });
}); });

View File

@ -1,26 +0,0 @@
const request = require("supertest")
const {
expect,
describe,
test,
} = require('@jest/globals');
const app = require("../app")
describe("Test retrieving playing positions", () => {
test("should retrieve all playing positions", async () => {
let response = await request(app)
.post("/api/auth/login")
.send({
email: 'player@example.com',
password: 'hash1234'
});
const user = response.body;
response = await request(app)
.get('/api/positions')
.set('x-access-token', user.accessToken);
expect(response.statusCode).toBe(200);
expect(response.body.length).toEqual(9);
});
});

View File

@ -1,91 +0,0 @@
const request = require("supertest")
const {
expect,
describe,
test,
} = require('@jest/globals');
const app = require("../app")
describe("Test team creation, adding and removing player", () => {
test("should create a team", async () => {
let response = await request(app)
.post("/api/auth/login")
.send({
email: 'coach@example.com',
password: 'hash1234'
});
const user = response.body;
response = await request(app)
.post("/api/teams")
.set('x-access-token', user.accessToken)
.send({
name: "Team 1",
description: "Team 1 description"
});
expect(response.statusCode).toBe(201);
const teamId = response.body.id;
const teamName = response.body.name;
response = await request(app)
.get('/api/teams')
.set('x-access-token', user.accessToken);
expect(response.statusCode).toBe(200);
expect(response.body.length).toBeGreaterThan(0);
expect(response.body.filter(t => t.id === teamId).shift()).toBeDefined();
response = await request(app)
.get('/api/players')
.set('x-access-token', user.accessToken);
expect(response.statusCode).toBe(200);
expect(response.body.length).toBe(1);
const playerId = response.body[0].id;
// Add player to team
response = await request(app)
.put(`/api/teams/${teamId}/add_players`)
.set('x-access-token', user.accessToken)
.send({
playerIds: [playerId]
});
expect(response.statusCode).toBe(200);
response = await request(app)
.get('/api/teams')
.set('x-access-token', user.accessToken);
expect(response.statusCode).toBe(200);
expect(response.body.length).toBeGreaterThan(0);
expect(response.body.filter(t => t.id === teamId).shift()).toBeDefined();
response = await request(app)
.get(`/api/players/${playerId}`)
.set('x-access-token', user.accessToken);
expect(response.statusCode).toBe(200);
expect(response.body.teams.length).toBe(1);
expect(response.body.teams[0].name).toBe(teamName);
// Remove player from team
response = await request(app)
.put(`/api/teams/${teamId}/remove_players`)
.set('x-access-token', user.accessToken)
.send({
playerIds: [playerId]
});
expect(response.statusCode).toBe(200);
response = await request(app)
.get(`/api/teams/${teamId}`)
.set('x-access-token', user.accessToken);
expect(response.statusCode).toBe(200);
expect(response.body.players.length).toBe(0);
response = await request(app)
.get(`/api/players/${playerId}`)
.set('x-access-token', user.accessToken);
expect(response.statusCode).toBe(200);
expect(response.body.teams.length).toBe(0);
});
});

View File

@ -22,8 +22,8 @@ describe("Test user authentication", () => {
let response = await request(app) let response = await request(app)
.post("/api/auth/login") .post("/api/auth/login")
.send({ .send({
email: signupUser.auth.email, email: signupUser.email,
password: signupUser.auth.password, password: signupUser.password,
}); });
expect(response.statusCode).toBe(200); expect(response.statusCode).toBe(200);
expect(response.body.accessToken).not.toBeNull(); expect(response.body.accessToken).not.toBeNull();