First working prototype
This commit is contained in:
408
server.js
408
server.js
@@ -38,23 +38,25 @@ if (!JWT_SECRET) {
|
||||
}
|
||||
|
||||
app.post("/register", async (req, res) => {
|
||||
const { username, password, role } = req.body;
|
||||
const { username, password, role, salt } = req.body;
|
||||
try {
|
||||
const hash = await bcrypt.hash(password, 10);
|
||||
|
||||
const inputs = {
|
||||
username: username,
|
||||
hash: hash,
|
||||
role: role
|
||||
role: role,
|
||||
salt: salt
|
||||
}
|
||||
const query = db.prepare("INSERT INTO Users (Username, PasswordHash, Role, CreatedAt) VALUES (@username, @hash, @role, datetime('now'))");
|
||||
const query = db.prepare("INSERT INTO Users (Username, PasswordHash, Role, CreatedAt, Salt) VALUES (@username, @hash, @role, datetime('now'), @salt)");
|
||||
query.run(inputs);
|
||||
|
||||
res.send({ success: true, message: "User registered" })
|
||||
|
||||
} catch (err) {
|
||||
if (err.message.includes("Violation of UNIQUE KEY constraint")) {
|
||||
if (err.message.includes("UNIQUE")) {
|
||||
res.status(500).send({ success: false, message: `Username "${username}" is already taken.` });
|
||||
return;
|
||||
}
|
||||
res.status(500).send({ success: false, message: err.message });
|
||||
}
|
||||
@@ -62,7 +64,7 @@ app.post("/register", async (req, res) => {
|
||||
|
||||
app.post("/login", async (req, res) => {
|
||||
const { username, password } = req.body;
|
||||
try {
|
||||
//try {
|
||||
const query = db.prepare("SELECT * FROM Users WHERE Username = @username");
|
||||
const results = query.all({ username: username });
|
||||
|
||||
@@ -82,7 +84,8 @@ app.post("/login", async (req, res) => {
|
||||
res.send({
|
||||
success: true,
|
||||
message: "Login successful",
|
||||
token
|
||||
token,
|
||||
salt: results[0].Salt
|
||||
});
|
||||
const update = db.prepare("UPDATE Users SET LastLogin = datetime('now') WHERE Username = @username");
|
||||
update.run({ username: username });
|
||||
@@ -90,11 +93,97 @@ app.post("/login", async (req, res) => {
|
||||
console.log("Issued token: " + JSON.stringify(token))
|
||||
}
|
||||
else res.status(401).send({ success: false, message: "Invalid credentials" });
|
||||
//} catch (err) {
|
||||
// res.status(500).send({ success: false, message: err.message });
|
||||
//}
|
||||
});
|
||||
|
||||
app.post("/getSalt", async (req, res) => {
|
||||
const { username } = req.body;
|
||||
try {
|
||||
const query = db.prepare("SELECT * FROM Users WHERE Username = @username");
|
||||
const results = query.all({ username: username });
|
||||
|
||||
if (results.length == 0) return res.status(400).send({ message: "User not found" });
|
||||
|
||||
const isDeleted = results[0].IsDeleted;
|
||||
|
||||
if (isDeleted === true) {
|
||||
return res.status(400).json({ message: "User not found (deleted)" })
|
||||
}
|
||||
|
||||
res.send({
|
||||
salt: results[0].Salt
|
||||
});
|
||||
} catch (err) {
|
||||
res.status(500).send({ success: false, message: err.message });
|
||||
}
|
||||
});
|
||||
|
||||
app.post("/setPassword", authenticate, async (req, res) => {
|
||||
try {
|
||||
const { name, iv, password } = req.body;
|
||||
|
||||
const inputs = {
|
||||
name: name,
|
||||
userID: req.user.Id,
|
||||
iv: iv,
|
||||
password: password
|
||||
}
|
||||
|
||||
const query = db.prepare("INSERT INTO Passwords (Name, UserID, Password, IV) VALUES (@name, @userID, @password, @iv)");
|
||||
query.run(inputs);
|
||||
|
||||
res.status(200).json({ success: true, message: "Success" });
|
||||
} catch (err) {
|
||||
res.status(500).json({ success: false, message: err.message });
|
||||
}
|
||||
});
|
||||
|
||||
app.post("/updatePassword", authenticate, async (req, res) => {
|
||||
try {
|
||||
const { name, iv, password } = req.body;
|
||||
|
||||
const inputs = {
|
||||
name: name,
|
||||
userID: req.user.Id,
|
||||
iv: iv,
|
||||
password: password
|
||||
}
|
||||
|
||||
const query = db.prepare("UPDATE Passwords SET Password = @password, IV = @iv WHERE UserID = @userID AND Name = @name");
|
||||
query.run(inputs);
|
||||
|
||||
res.status(200).json({ success: true, message: "Success" });
|
||||
} catch (err) {
|
||||
res.status(500).json({ success: false, message: err.message });
|
||||
}
|
||||
});
|
||||
|
||||
app.post("/getPassword", authenticate, async (req, res) => {
|
||||
try {
|
||||
const { name } = req.body;
|
||||
|
||||
const query = db.prepare("SELECT * FROM Passwords WHERE UserID = @userID AND Name = @name");
|
||||
const results = query.all({ userID: req.user.Id, name: name});
|
||||
|
||||
if (results.length == 0) {
|
||||
res.status(500).json({ success: false, message: `No password with name ${name}` });
|
||||
return;
|
||||
}
|
||||
|
||||
if (results.length > 1) {
|
||||
res.status(500).json({ success: false, message: `More than one password with name ${name}` });
|
||||
return;
|
||||
}
|
||||
|
||||
res.status(200).json({ password: results[0].Password, iv: results[0].IV, success: true, message: "Success" });
|
||||
} catch (err) {
|
||||
res.status(500).json({ success: false, message: err.message });
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
app.post("/getWatchlist", authenticate, async (req, res) => {
|
||||
const { id } = req.body;
|
||||
|
||||
@@ -108,319 +197,12 @@ app.post("/getWatchlist", authenticate, async (req, res) => {
|
||||
res.status(200).json({ watchlist: watchlist });
|
||||
});
|
||||
|
||||
app.post("/isWatched", authenticate, async (req, res) => {
|
||||
const { id } = req.body;
|
||||
|
||||
const query = db.prepare(`SELECT PlayerID FROM Watch WHERE UserID = @userID`);
|
||||
const watchlist = query.all({ userID: req.user.Id, id: id});
|
||||
|
||||
const isWatched = watchlist.some(row => row.PlayerID === parseInt(id));
|
||||
|
||||
res.status(200).json({ isWatched: isWatched });
|
||||
});
|
||||
|
||||
app.post("/toggleWatched", authenticate, async (req, res) => {
|
||||
const { id } = req.body;
|
||||
|
||||
const query = db.prepare(`SELECT PlayerID FROM Watch WHERE UserID = @userID`);
|
||||
const watchlist = query.all({ userID: req.user.Id, id: id });
|
||||
|
||||
const isWatched = watchlist.some(row => row.PlayerID === parseInt(id));
|
||||
|
||||
if (isWatched) {
|
||||
const query = db.prepare(`DELETE FROM Watch WHERE UserID = @userID AND PlayerID = @id`);
|
||||
query.run({ userID: req.user.Id, id: id });
|
||||
|
||||
res.status(200).json({ message: "No longer watching player" });
|
||||
return;
|
||||
}
|
||||
|
||||
// Otherwise, watch the player
|
||||
const watchQuery = db.prepare(`INSERT INTO Watch (UserID, PlayerID) VALUES (@userID, @id)`);
|
||||
watchQuery.run({ userID: req.user.Id, id: id });
|
||||
|
||||
res.status(200).json({ message: "Watching Player" });
|
||||
});
|
||||
|
||||
app.post("/getPlayers", authenticate, async (req, res) => {
|
||||
const { player, positions } = req.body;
|
||||
|
||||
const query = db.prepare(`SELECT p.PlayerID, p.PlayerName, c.TotalValue, p.Team, p.Position FROM Player AS p JOIN Contract AS c ON p.PlayerID = c.PlayerID WHERE p.PlayerName LIKE '%' || @query || '%' AND p.Position IN (@one, @two, @three, @four) ORDER BY p.PlayerName;`);
|
||||
const matches = query.all({
|
||||
query: player,
|
||||
one: positions[0],
|
||||
two: positions[1],
|
||||
three: positions[2],
|
||||
four: positions[3]
|
||||
});
|
||||
|
||||
res.status(200).json({ query: player, matches: matches });
|
||||
});
|
||||
|
||||
app.post("/getHighest", authenticate, async (req, res) => {
|
||||
const { amount } = req.body;
|
||||
|
||||
const query = db.prepare(`
|
||||
SELECT p.PlayerID, p.PlayerName, p.[Position], p.Team, TotalValue, TrueAvgPerYear, Years
|
||||
FROM Player AS p JOIN Contract AS c ON p.PlayerID = c.PlayerID
|
||||
ORDER BY TotalValue DESC
|
||||
LIMIT @amount;
|
||||
`);
|
||||
const matches = query.all({ amount: amount });
|
||||
|
||||
res.status(200).json({ matches: matches });
|
||||
});
|
||||
|
||||
app.post("/getHighestOffense", authenticate, async (req, res) => {
|
||||
const { amount } = req.body;
|
||||
|
||||
const query = db.prepare(`
|
||||
SELECT Player.PlayerID, Player.[Position], Player.PlayerName, Player.Team,
|
||||
SUM(total_yards) AS TotalYards,
|
||||
SUM(passing_yards) AS PassingYards,
|
||||
SUM(rushing_yards) AS RushingYards,
|
||||
SUM(receiving_yards) AS RecievingYards,
|
||||
CASE WHEN Player.Position = 'QB' THEN (SUM(pass_touchdown)) ELSE 0 END + SUM(receiving_touchdown) + SUM(rush_touchdown) AS AmendedTotalTDs,
|
||||
CASE WHEN Player.Position = 'QB' THEN (SUM(pass_touchdown)) ELSE 0 END AS PassTDs,
|
||||
SUM(receiving_touchdown) AS ReceivingTDs,
|
||||
SUM(rush_touchdown) AS RushTDs,
|
||||
SUM(offense_snaps) * 1.0 / SUM(team_offense_snaps) AS SnapPercentage,
|
||||
SUM(interception) + sum(fumble_lost) AS Turnovers,
|
||||
SUM(tackled_for_loss) AS TackledForLoss,
|
||||
CASE
|
||||
WHEN Player.Position = 'QB'
|
||||
THEN SUM(qb_dropback) - SUM(pass_attempts) - SUM(qb_scramble)
|
||||
ELSE 0
|
||||
END AS Sacks,
|
||||
SUM(safety) AS Safties,
|
||||
|
||||
SUM(total_yards)
|
||||
+ ((CASE WHEN Player.Position = 'QB' THEN (SUM(pass_touchdown)) ELSE 0 END + SUM(receiving_touchdown) + SUM(rush_touchdown)) * 50)
|
||||
+ (SUM(offense_snaps) * 100.0 / SUM(team_offense_snaps))
|
||||
- ((SUM(interception) + sum(fumble_lost)) * 75)
|
||||
- (
|
||||
SUM(tackled_for_loss))
|
||||
|
||||
- (SUM(safety) * 100.0)
|
||||
AS OffenseScore,
|
||||
|
||||
AvgPerYear,
|
||||
(SUM(total_yards)
|
||||
+ ((CASE WHEN Player.Position = 'QB' THEN (SUM(pass_touchdown)) ELSE 0 END + SUM(receiving_touchdown) + SUM(rush_touchdown)) * 50)
|
||||
+ (SUM(offense_snaps) * 100.0 / SUM(team_offense_snaps))
|
||||
- ((SUM(interception) + sum(fumble_lost)) * 75)
|
||||
- (
|
||||
SUM(tackled_for_loss)
|
||||
)
|
||||
- (SUM(safety) * 100.0)) / AvgPerYear AS PaydirtScore
|
||||
|
||||
FROM Player JOIN DatasetPlayerStats ON Player.PlayerID = DatasetPlayerStats.PlayerID JOIN Contract ON Player.PlayerID = Contract.PlayerID
|
||||
WHERE season = 2024 AND SeasonType = 'REG'
|
||||
GROUP BY Player.PlayerID, Player.PlayerName, Player.Team, Player.[Position], Contract.AvgPerYear
|
||||
ORDER BY OffenseScore DESC
|
||||
LIMIT @amount;
|
||||
`);
|
||||
const matches = query.all({ amount: amount });
|
||||
|
||||
res.status(200).json({ matches: matches });
|
||||
});
|
||||
|
||||
|
||||
app.post("/getPlayerStats", authenticate, async (req, res) => {
|
||||
const { playerID } = req.body;
|
||||
|
||||
const query = db.prepare(`
|
||||
SELECT player.playerid, player.playername, season, seasontype, week, pass_attempts, complete_pass, total_yards, total_tds, interception, receptions, receiving_yards, receiving_touchdown, rush_attempts, rushing_yards, rush_touchdown, fumble
|
||||
fROM Player JOIN DatasetPlayerStats ON Player.PlayerID = DatasetPlayerStats.PlayerID
|
||||
WHERE Player.PlayerID = @playerID
|
||||
ORDER BY Season, week;
|
||||
`);
|
||||
const matches = query.all({ playerID: playerID })
|
||||
|
||||
res.status(200).json({ matches: matches });
|
||||
});
|
||||
|
||||
app.post("/getPlayerScores", authenticate, async (req, res) => {
|
||||
const { playerID } = req.body;
|
||||
|
||||
const query = db.prepare(`
|
||||
SELECT Player.PlayerID, Player.[Position], Player.PlayerName, Player.Team,
|
||||
c.TotalValue, c.TrueAvgPerYear, c.Years, c.StartYear, c.EndYear, Player.Height, Player.Weight,
|
||||
SUM(total_yards) AS TotalYards,
|
||||
SUM(passing_yards) AS PassingYards,
|
||||
SUM(rushing_yards) AS RushingYards,
|
||||
SUM(receiving_yards) AS RecievingYards,
|
||||
CASE WHEN Player.Position = 'QB' THEN (SUM(pass_touchdown)) ELSE 0 END + SUM(receiving_touchdown) + SUM(rush_touchdown) AS AmendedTotalTDs,
|
||||
CASE WHEN Player.Position = 'QB' THEN (SUM(pass_touchdown)) ELSE 0 END AS PassTDs,
|
||||
SUM(receiving_touchdown) AS ReceivingTDs,
|
||||
SUM(rush_touchdown) AS RushTDs,
|
||||
SUM(offense_snaps) * 1.0 / SUM(team_offense_snaps) AS SnapPercentage,
|
||||
SUM(interception) + sum(fumble_lost) AS Turnovers,
|
||||
SUM(tackled_for_loss) AS TackledForLoss,
|
||||
CASE
|
||||
WHEN Player.Position = 'QB'
|
||||
THEN SUM(qb_dropback) - SUM(pass_attempts) - SUM(qb_scramble)
|
||||
ELSE 0
|
||||
END AS Sacks,
|
||||
SUM(safety) AS Safties,
|
||||
|
||||
SUM(total_yards)
|
||||
+ ((CASE WHEN Player.Position = 'QB' THEN (SUM(pass_touchdown)) ELSE 0 END + SUM(receiving_touchdown) + SUM(rush_touchdown)) * 50)
|
||||
+ (SUM(offense_snaps) * 100.0 / SUM(team_offense_snaps))
|
||||
- ((SUM(interception) + sum(fumble_lost)) * 75)
|
||||
- (
|
||||
SUM(tackled_for_loss)
|
||||
)
|
||||
|
||||
- (SUM(safety) * 100.0)
|
||||
AS OffenseScore,
|
||||
|
||||
AvgPerYear,
|
||||
(SUM(total_yards)
|
||||
+ ((CASE WHEN Player.Position = 'QB' THEN (SUM(pass_touchdown)) ELSE 0 END + SUM(receiving_touchdown) + SUM(rush_touchdown)) * 50)
|
||||
+ (SUM(offense_snaps) * 100.0 / SUM(team_offense_snaps))
|
||||
- ((SUM(interception) + sum(fumble_lost)) * 75)
|
||||
- (
|
||||
SUM(tackled_for_loss)
|
||||
)
|
||||
- (SUM(safety) * 100.0)) / AvgPerYear * 1000000 AS PaydirtScore
|
||||
|
||||
|
||||
FROM Player JOIN DatasetPlayerStats ON Player.PlayerID = DatasetPlayerStats.PlayerID JOIN Contract AS c ON Player.PlayerID = c.PlayerID
|
||||
WHERE season = 2024 AND SeasonType = 'REG' AND Player.PlayerID = @playerID
|
||||
GROUP BY c.TotalValue, c.TrueAvgPerYear, c.Years, c.StartYear, Player.Height, Player.Weight, c.EndYear, Player.PlayerID, Player.PlayerName, Player.Team, Player.[Position], c.AvgPerYear
|
||||
ORDER BY PaydirtScore DESC;
|
||||
`);
|
||||
const matches = query.all({ playerID: playerID })
|
||||
|
||||
res.status(200).json({ match: matches[0] });
|
||||
});
|
||||
|
||||
|
||||
|
||||
app.post("/getHighestPaydirt", authenticate, async (req, res) => {
|
||||
const { amount } = req.body;
|
||||
|
||||
const query = db.prepare(`
|
||||
SELECT Player.PlayerID, Player.[Position], Player.PlayerName, Player.Team,
|
||||
SUM(total_yards) AS TotalYards,
|
||||
SUM(passing_yards) AS PassingYards,
|
||||
SUM(rushing_yards) AS RushingYards,
|
||||
SUM(receiving_yards) AS RecievingYards,
|
||||
CASE WHEN Player.Position = 'QB' THEN (SUM(pass_touchdown)) ELSE 0 END + SUM(receiving_touchdown) + SUM(rush_touchdown) AS AmendedTotalTDs,
|
||||
CASE WHEN Player.Position = 'QB' THEN (SUM(pass_touchdown)) ELSE 0 END AS PassTDs,
|
||||
SUM(receiving_touchdown) AS ReceivingTDs,
|
||||
SUM(rush_touchdown) AS RushTDs,
|
||||
SUM(offense_snaps) * 1.0 / SUM(team_offense_snaps) AS SnapPercentage,
|
||||
SUM(interception) + sum(fumble_lost) AS Turnovers,
|
||||
SUM(tackled_for_loss) AS TackledForLoss,
|
||||
CASE
|
||||
WHEN Player.Position = 'QB'
|
||||
THEN SUM(qb_dropback) - SUM(pass_attempts) - SUM(qb_scramble)
|
||||
ELSE 0
|
||||
END AS Sacks,
|
||||
SUM(safety) AS Safties,
|
||||
|
||||
SUM(total_yards)
|
||||
+ ((CASE WHEN Player.Position = 'QB' THEN (SUM(pass_touchdown)) ELSE 0 END + SUM(receiving_touchdown) + SUM(rush_touchdown)) * 50)
|
||||
+ (SUM(offense_snaps) * 100.0 / SUM(team_offense_snaps))
|
||||
- ((SUM(interception) + sum(fumble_lost)) * 75)
|
||||
- (
|
||||
SUM(tackled_for_loss))
|
||||
|
||||
- (SUM(safety) * 100.0)
|
||||
AS OffenseScore,
|
||||
|
||||
AvgPerYear,
|
||||
(SUM(total_yards)
|
||||
+ ((CASE WHEN Player.Position = 'QB' THEN (SUM(pass_touchdown)) ELSE 0 END + SUM(receiving_touchdown) + SUM(rush_touchdown)) * 50)
|
||||
+ (SUM(offense_snaps) * 100.0 / SUM(team_offense_snaps))
|
||||
- ((SUM(interception) + sum(fumble_lost)) * 75)
|
||||
- (
|
||||
SUM(tackled_for_loss)
|
||||
)
|
||||
|
||||
- (SUM(safety) * 100.0)) / AvgPerYear * 1000000 AS PaydirtScore
|
||||
|
||||
|
||||
FROM Player JOIN DatasetPlayerStats ON Player.PlayerID = DatasetPlayerStats.PlayerID JOIN Contract ON Player.PlayerID = Contract.PlayerID
|
||||
WHERE season = 2024 AND SeasonType = 'REG'
|
||||
GROUP BY Player.PlayerID, Player.PlayerName, Player.Team, Player.[Position], Contract.AvgPerYear
|
||||
ORDER BY PaydirtScore DESC
|
||||
LIMIT @amount;
|
||||
`);
|
||||
const matches = query.all({ amount: amount });
|
||||
|
||||
res.status(200).json({ matches: matches });
|
||||
});
|
||||
|
||||
app.post("/getPlayer", authenticate, async (req, res) => {
|
||||
const { id } = req.body;
|
||||
|
||||
const query = db.prepare(`SELECT p.PlayerName, p.PlayerID, c.TotalValue, c.TrueAvgPerYear, c.Years, c.StartYear, c.EndYear, p.Team, p.Position FROM Player AS p JOIN Contract AS c ON p.PlayerID = c.PlayerID WHERE p.PlayerID = @query`);
|
||||
const matches = query.run({ query: id });
|
||||
|
||||
if (matches.length !== 1) {
|
||||
res.status(400).json({ success: false })
|
||||
return;
|
||||
}
|
||||
res.status(200).json({ success: true, match: matches[0] });
|
||||
});
|
||||
|
||||
app.post("/getInfo", authenticate, async (req, res) => {
|
||||
const userData = req.user;
|
||||
|
||||
res.status(200).json(userData);
|
||||
});
|
||||
|
||||
app.post("/getCourses", authenticate, async (req, res) => {
|
||||
const query = db.prepare("SELECT * FROM Courses");
|
||||
const courses = query.all();
|
||||
|
||||
res.status(200).json(courses);
|
||||
});
|
||||
|
||||
app.post("/setInfo", authenticate, async (req, res) => {
|
||||
const { firstName, lastName, dob } = req.body;
|
||||
|
||||
try {
|
||||
const query = db.prepare(`
|
||||
UPDATE Users
|
||||
SET FirstName = @firstName,
|
||||
LastName = @lastName,
|
||||
DOB = @dob
|
||||
WHERE Username = @username
|
||||
`);
|
||||
query.run({
|
||||
username: req.user.Username,
|
||||
firstName: firstName,
|
||||
lastName: lastName,
|
||||
dob: dob || null
|
||||
});
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
if (error.message.includes("failed for parameter 'dob'.")) {
|
||||
res.status(500).json({ message: "Must input date of birth" })
|
||||
return;
|
||||
}
|
||||
res.status(500).json({ message: "Update request failed" })
|
||||
return;
|
||||
}
|
||||
|
||||
var updatedUser = req.user;
|
||||
updatedUser.FirstName = firstName;
|
||||
updatedUser.LastName = lastName;
|
||||
updatedUser.DOB = dob;
|
||||
|
||||
const token = jwt.sign(updatedUser, JWT_SECRET);
|
||||
console.log("Issued token: " + JSON.stringify(token))
|
||||
res.status(200).send({
|
||||
success: true,
|
||||
message: "Information updated successfully",
|
||||
token
|
||||
});
|
||||
});
|
||||
|
||||
app.post("/delete", authenticate, async (req, res) => {
|
||||
let { username, actor } = req.body;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user