Rewrite phase 1.
Started improved client code structure. Implemented session based authentication serverside. Implemented user, match, and sport database models serverside. Implemented Controllers for variety of C and R operations of CRUD.
This commit is contained in:
29
sports-matcher/server/.eslintrc.json
Normal file
29
sports-matcher/server/.eslintrc.json
Normal file
@@ -0,0 +1,29 @@
|
||||
{
|
||||
"env": {
|
||||
"es2021": true,
|
||||
"node": true
|
||||
},
|
||||
"extends": "eslint:recommended",
|
||||
"parserOptions": {
|
||||
"ecmaVersion": "latest",
|
||||
"sourceType": "module"
|
||||
},
|
||||
"rules": {
|
||||
"indent": [
|
||||
"error",
|
||||
4
|
||||
],
|
||||
"linebreak-style": [
|
||||
"error",
|
||||
"unix"
|
||||
],
|
||||
"quotes": [
|
||||
"error",
|
||||
"double"
|
||||
],
|
||||
"semi": [
|
||||
"error",
|
||||
"always"
|
||||
]
|
||||
}
|
||||
}
|
16
sports-matcher/server/.vscode/launch.json
vendored
Normal file
16
sports-matcher/server/.vscode/launch.json
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
{
|
||||
// Use IntelliSense to learn about possible attributes.
|
||||
// Hover to view descriptions of existing attributes.
|
||||
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"name": "Python: Current File",
|
||||
"type": "python",
|
||||
"request": "launch",
|
||||
"program": "${file}",
|
||||
"console": "integratedTerminal",
|
||||
"justMyCode": true
|
||||
}
|
||||
]
|
||||
}
|
94
sports-matcher/server/controllers/matchController.js
Normal file
94
sports-matcher/server/controllers/matchController.js
Normal file
@@ -0,0 +1,94 @@
|
||||
import express from "express";
|
||||
import { authenticationGuard } from "../middleware/authority.js";
|
||||
import { needDatabase } from "../middleware/database.js";
|
||||
import matchModel from "../schemas/matchModel.js";
|
||||
import sportModel from "../schemas/sportModel.js";
|
||||
import userModel from "../schemas/userModel.js";
|
||||
const MatchController = express.Router();
|
||||
|
||||
MatchController.get("/search/:sport", needDatabase, async (req, res) => {
|
||||
try {
|
||||
let sport = sportModel.findByName(req.params.sport);
|
||||
let query = matchModel.find({ sport: sport._id });
|
||||
query.where("when").gte(Date.now); // We don't want to return any results of matches that have already occurred.
|
||||
if (req.session.userId) query.where("publicity").gte(1).where("friends").in(req.session.userId);
|
||||
if (req.query.within) query.where("location").within({ center: req.query.location.split(","), radius: req.query.within });
|
||||
if (req.query.minDifficulty) query.where("difficulty").gte(req.query.minDifficulty);
|
||||
if (req.query.maxDifficulty) query.where("difficulty").lte(req.query.maxDifficulty);
|
||||
if (req.query.beforeDate) query.where("when").lte(req.query.beforeDate);
|
||||
|
||||
let queryResults = await query;
|
||||
res.send({ queryResults });
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
res.status(500).send("Internal server error.");
|
||||
}
|
||||
});
|
||||
|
||||
MatchController.get("/recent/:limit?", needDatabase, async (req, res) => {
|
||||
let limit = req.params.limit;
|
||||
if (!req.params.limit) limit = 10;
|
||||
if (isNaN(limit)) {
|
||||
res.status(400).send("Limit parameter not a number.");
|
||||
return;
|
||||
}
|
||||
if (limit > 50) {
|
||||
res.status(400).send("Limit greater than maximum limit of 50.");
|
||||
return;
|
||||
}
|
||||
try {
|
||||
const recent = await matchModel.find().where("publicity").gte(2).limit(limit).sort({ createDate: -1 });
|
||||
res.status(200).send({ recent: recent });
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
res.status(500).send("Internal server error.");
|
||||
// TODO: Check and improve error handling.
|
||||
}
|
||||
});
|
||||
|
||||
// TODO: delete, update match.
|
||||
MatchController.post("/", needDatabase, authenticationGuard, async (req, res) => {
|
||||
try {
|
||||
const userId = req.session.userId;
|
||||
const user = await userModel.findById(userId);
|
||||
const match = new matchModel({
|
||||
title: req.body.title,
|
||||
when: req.body.when,
|
||||
public: req.body.public,
|
||||
location: req.body.location,
|
||||
creator: userId,
|
||||
difficulty: req.body.difficulty,
|
||||
sport: await sportModel.findByName(req.body.sport),
|
||||
participants: [user._id]
|
||||
});
|
||||
await match.save();
|
||||
user.createdMatches.push(match._id);
|
||||
user.participatingMatches.push(match._id);
|
||||
await user.save();
|
||||
res.status(201).send(match);
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
res.status(500).send("Internal server error.");
|
||||
// TODO: Develop the error handling.
|
||||
}
|
||||
});
|
||||
|
||||
MatchController.get("/:matchId", needDatabase, async (req, res) => {
|
||||
if (!req.params.matchId) {
|
||||
res.status(404).send("Id must be provided to retrieve match");
|
||||
return;
|
||||
}
|
||||
try {
|
||||
const match = await matchModel.findById(req.params.matchId);
|
||||
if (match) {
|
||||
res.status(200).send(match);
|
||||
} else {
|
||||
res.status(404).send("Could not find match with ID: " + req.params.matchId);
|
||||
}
|
||||
} catch (error) {
|
||||
res.status(500).send("Internal server error.");
|
||||
// TODO: Develop the error handling.
|
||||
}
|
||||
});
|
||||
|
||||
export default MatchController;
|
48
sports-matcher/server/controllers/sportController.js
Normal file
48
sports-matcher/server/controllers/sportController.js
Normal file
@@ -0,0 +1,48 @@
|
||||
import express from "express";
|
||||
import { authenticationGuard } from "../middleware/authority.js";
|
||||
import { needDatabase } from "../middleware/database.js";
|
||||
import sportModel from "../schemas/sportModel.js";
|
||||
import userModel from "../schemas/userModel.js";
|
||||
|
||||
const SportController = express.Router();
|
||||
|
||||
SportController.post("/", needDatabase, authenticationGuard, async (req, res) => {
|
||||
const user = await userModel.findById(req.session.userId);
|
||||
try {
|
||||
if (user.accessLevel <= 2) {
|
||||
res.status(403).send("Insufficient privileges.");
|
||||
return;
|
||||
}
|
||||
const sport = new sportModel({
|
||||
name: req.body.name,
|
||||
maxPlayers: req.body.maxPlayers,
|
||||
minPlayers: req.body.minPlayers,
|
||||
description: req.body.description
|
||||
});
|
||||
await sport.save();
|
||||
res.status(201).send("Successfully created new sport.");
|
||||
} catch (error) {
|
||||
res.status(500).send("Internal server error.");
|
||||
// TODO: Add proper error checking here.
|
||||
}
|
||||
});
|
||||
|
||||
SportController.get("/:sportId", needDatabase, async (req, res) => {
|
||||
try {
|
||||
res.status(200).send(await sportModel.findById(req.params.sportId));
|
||||
} catch (error) {
|
||||
res.status(500).send("Internal server error.");
|
||||
// TODO: Add proper error checking here.
|
||||
}
|
||||
});
|
||||
|
||||
SportController.get("/", needDatabase, async (req, res) => {
|
||||
try {
|
||||
res.status(200).send(await sportModel.find());
|
||||
} catch (error) {
|
||||
res.status(500).send("Internal server error.");
|
||||
// TODO: Add proper error checking here.
|
||||
}
|
||||
});
|
||||
|
||||
export default SportController;
|
169
sports-matcher/server/controllers/userController.js
Normal file
169
sports-matcher/server/controllers/userController.js
Normal file
@@ -0,0 +1,169 @@
|
||||
import express from "express";
|
||||
import { authenticationGuard } from "../middleware/authority.js";
|
||||
import { needDatabase } from "../middleware/database.js";
|
||||
import User from "../schemas/userModel.js";
|
||||
const UserController = express.Router();
|
||||
|
||||
UserController.post("/login", needDatabase, async (req, res) => {
|
||||
try {
|
||||
const email = req.body.email;
|
||||
const pwd = req.body.password;
|
||||
const user = await User.credentialsExist(email, pwd);
|
||||
if (!user) {
|
||||
res.sendStatus(401);
|
||||
return;
|
||||
} else {
|
||||
req.session.userId = user._id;
|
||||
req.session.email = user.email;
|
||||
res.status(200).send("Authenticated.");
|
||||
}
|
||||
} catch (error) {
|
||||
if (error.name === "TypeError") {
|
||||
res.status(400).send("Missing required user info.");
|
||||
} else if (error.message === "Credentials do not exist.") {
|
||||
res.status(401).send("Credentials do not exist.");
|
||||
} else {
|
||||
console.error(error);
|
||||
if (process.env.NODE_ENV === "development") {
|
||||
res.status(500).send(error.toString());
|
||||
} else {
|
||||
res.status(500).send("Internal server error. This issue has been noted.");
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
UserController.get("/logout", authenticationGuard, (req, res) => {
|
||||
req.session.destroy((err) => {
|
||||
if (err) {
|
||||
console.error(err);
|
||||
if (process.env.NODE_ENV === "development") {
|
||||
res.status(500).send(err.toString());
|
||||
} else {
|
||||
res.status(500).send("Internal server error. This issue has been noted.");
|
||||
}
|
||||
res.status(500).send("");
|
||||
} else {
|
||||
res.sendStatus(200);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
UserController.get("/email/:userId?", needDatabase, authenticationGuard, async (req, res) => {
|
||||
if (!req.params.userId) req.params.userId = req.session.userId;
|
||||
const curUser = await User.findById(req.session.userId);
|
||||
const selUser = req.session.userId === req.params.userId ? curUser : await User.findById(req.params.userId);
|
||||
if (selUser.email.public || curUser._id === selUser._id || curUser.accessLevel > 2) {
|
||||
res.status(200).send({ email: selUser.email });
|
||||
} else {
|
||||
res.status(401).send("Could not authenticate request.");
|
||||
}
|
||||
});
|
||||
|
||||
UserController.get("/firstName/:userId?", needDatabase, authenticationGuard, async (req, res) => {
|
||||
if (!req.params.userId) req.params.userId = req.session.userId;
|
||||
const curUser = await User.findById(req.session.userId);
|
||||
const selUser = req.session.userId === req.params.userId ? curUser : await User.findById(req.params.userId);
|
||||
if (selUser.firstName.public || curUser._id === selUser._id || curUser.accessLevel > 2) {
|
||||
res.status(200).send({ firstName: selUser.firstName });
|
||||
} else {
|
||||
res.status(401).send("Could not authenticate request.");
|
||||
}
|
||||
});
|
||||
|
||||
UserController.get("/lastName/:userId?", needDatabase, authenticationGuard, async (req, res) => {
|
||||
if (!req.params.userId) req.params.userId = req.session.userId;
|
||||
const curUser = await User.findById(req.session.userId);
|
||||
const selUser = req.session.userId === req.params.userId ? curUser : await User.findById(req.params.userId);
|
||||
if (selUser.lastName.public || curUser._id === selUser._id || curUser.accessLevel > 2) {
|
||||
res.status(200).send({ email: selUser.lastName });
|
||||
} else {
|
||||
res.status(401).send("Could not authenticate request.");
|
||||
}
|
||||
});
|
||||
|
||||
UserController.get("/phone/:userId?", needDatabase, authenticationGuard, async (req, res) => {
|
||||
if (!req.params.userId) req.params.userId = req.session.userId;
|
||||
const curUser = await User.findById(req.session.userId);
|
||||
const selUser = req.session.userId === req.params.userId ? curUser : await User.findById(req.params.userId);
|
||||
if (selUser.phone.public || curUser._id === selUser._id || curUser.accessLevel > 2) {
|
||||
res.status(200).send({ phone: selUser.phone });
|
||||
} else {
|
||||
res.status(401).send("Could not authenticate request.");
|
||||
}
|
||||
});
|
||||
|
||||
UserController.get("/participatingMatches/:userId?", needDatabase, authenticationGuard, async (req, res) => {
|
||||
if (!req.params.userId) req.params.userId = req.session.userId;
|
||||
const curUser = await User.findById(req.session.userId);
|
||||
const selUser = req.session.userId === req.params.userId ? curUser : await User.findById(req.params.userId);
|
||||
if (selUser.participatingMatches.public || curUser._id === selUser._id || curUser.accessLevel > 2) {
|
||||
res.status(200).send({ participatingMatches: selUser.participatingMatches });
|
||||
} else {
|
||||
res.status(401).send("Could not authenticate request.");
|
||||
}
|
||||
});
|
||||
|
||||
UserController.get("/joinDate/:userId?", needDatabase, authenticationGuard, async (req, res) => {
|
||||
if (!req.params.userId) req.params.userId = req.session.userId;
|
||||
const curUser = await User.findById(req.session.userId);
|
||||
const selUser = req.session.userId === req.params.userId ? curUser : await User.findById(req.params.userId);
|
||||
if (curUser._id === selUser._id || curUser.accessLevel > 2) {
|
||||
res.status(200).send({ joinDate: selUser.joinDate });
|
||||
} else {
|
||||
res.status(401).send("Could not authenticate request.");
|
||||
}
|
||||
});
|
||||
|
||||
UserController.get("/createdMatches/:userId?", needDatabase, authenticationGuard, async (req, res) => {
|
||||
if (!req.params.userId) req.params.userId = req.session.userId;
|
||||
const curUser = await User.findById(req.session.userId);
|
||||
const selUser = req.session.userId === req.params.userId ? curUser : await User.findById(req.params.userId);
|
||||
if (curUser._id === selUser._id || curUser.accessLevel > 2) {
|
||||
res.status(200).send({ createdMatches: selUser.createdMatches });
|
||||
} else {
|
||||
res.status(401).send("Could not authenticate request.");
|
||||
}
|
||||
});
|
||||
|
||||
// TODO: Finish update requests using put.
|
||||
|
||||
UserController.post("/", needDatabase, async (req, res) => {
|
||||
try {
|
||||
let createdUser = new User({
|
||||
email: req.body.email,
|
||||
firstName: req.body.firstName,
|
||||
lastName: req.body.lastName,
|
||||
phone: req.body.phone,
|
||||
password: req.body.password,
|
||||
});
|
||||
await createdUser.save();
|
||||
res.sendStatus(201);
|
||||
return;
|
||||
} catch (err) {
|
||||
if (err.name === "TypeError" || err.name === "ValidationError") {
|
||||
if (process.env.NODE_ENV === "development") {
|
||||
console.error(err);
|
||||
res.status(400).send(err.toString());
|
||||
} else {
|
||||
res.status(400).send("Missing required user info.");
|
||||
}
|
||||
} else if (err.name === "MongoServerError" && err.message.startsWith("E11000")) {
|
||||
if (process.env.NODE_ENV === "development") {
|
||||
console.error(err);
|
||||
res.status(409).send(err.toString());
|
||||
} else {
|
||||
res.status(409).send("User already exists.");
|
||||
}
|
||||
} else {
|
||||
console.error(err);
|
||||
if (process.env.NODE_ENV === "development") {
|
||||
res.status(500).send(err.toString());
|
||||
} else {
|
||||
res.status(500).send("Internal server error. This issue has been noted.");
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
export default UserController;
|
2
sports-matcher/server/database/mongoose.js
Normal file
2
sports-matcher/server/database/mongoose.js
Normal file
@@ -0,0 +1,2 @@
|
||||
export const mongooseDbName = process.env.DB_NAME || "sm_db";
|
||||
export const mongoURI = process.env.MONGODB_URI || "mongodb://127.0.0.1:27017";
|
30
sports-matcher/server/middleware/authority.js
Normal file
30
sports-matcher/server/middleware/authority.js
Normal file
@@ -0,0 +1,30 @@
|
||||
import MongoStore from "connect-mongo";
|
||||
import session from "express-session";
|
||||
import { mongooseDbName, mongoURI } from "../database/mongoose.js";
|
||||
const sessionConf = {
|
||||
secret: process.env.SESSION_SECRET || "super duper secret string.",
|
||||
cookie: {
|
||||
expires: process.env.SESSION_TIMEOUT || 300000,
|
||||
httpOnly: true,
|
||||
},
|
||||
saveUninitialized: false,
|
||||
resave: false,
|
||||
};
|
||||
if (process.env.NODE_ENV === "production") {
|
||||
sessionConf.cookie.secure = true;
|
||||
sessionConf.store = MongoStore.create({ mongoUrl: mongoURI, dbName: mongooseDbName });
|
||||
}
|
||||
export const userSession = session(sessionConf);
|
||||
|
||||
export function authenticationGuard(req, res, next) {
|
||||
if (req.session.userId) {
|
||||
next();
|
||||
} else {
|
||||
res.sendStatus(401);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Authentication
|
||||
// TODO: Identity
|
||||
// TODO: Authority
|
9
sports-matcher/server/middleware/database.js
Normal file
9
sports-matcher/server/middleware/database.js
Normal file
@@ -0,0 +1,9 @@
|
||||
import mongoose from "mongoose";
|
||||
|
||||
export function needDatabase(res, req, next) {
|
||||
if (mongoose.connection.readyState != 1) {
|
||||
res.status(500).send("Internal server error: Database connection faulty.");
|
||||
} else {
|
||||
next();
|
||||
}
|
||||
}
|
5627
sports-matcher/server/package-lock.json
generated
Normal file
5627
sports-matcher/server/package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
29
sports-matcher/server/package.json
Normal file
29
sports-matcher/server/package.json
Normal file
@@ -0,0 +1,29 @@
|
||||
{
|
||||
"name": "server",
|
||||
"version": "1.0.0",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"description": "",
|
||||
"main": "server.js",
|
||||
"scripts": {
|
||||
"develop": "NODE_ENV=development nodemon server.js",
|
||||
"start": "NODE_ENV=production node server.js",
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
},
|
||||
"author": "",
|
||||
"license": "ISC",
|
||||
"devDependencies": {
|
||||
"eslint": "^8.12.0",
|
||||
"nodemon": "^2.0.15"
|
||||
},
|
||||
"dependencies": {
|
||||
"bcrypt": "^5.0.1",
|
||||
"body-parser": "^1.19.2",
|
||||
"connect-mongo": "^4.6.0",
|
||||
"cors": "^2.8.5",
|
||||
"express": "^4.17.3",
|
||||
"express-session": "^1.17.2",
|
||||
"mongoose": "^6.2.8",
|
||||
"validator": "^13.7.0"
|
||||
}
|
||||
}
|
27
sports-matcher/server/schemas/matchModel.js
Normal file
27
sports-matcher/server/schemas/matchModel.js
Normal file
@@ -0,0 +1,27 @@
|
||||
import mongoose from "mongoose";
|
||||
import ModelNameRegister from "./modelNameRegister.js";
|
||||
|
||||
const Types = mongoose.Schema.Types; // Some types require defining from this object.
|
||||
|
||||
const matchSchema = new mongoose.Schema({
|
||||
title: { type: String, required: true, trim: true },
|
||||
when: { type: Date, required: true },
|
||||
publicity: { type: Number, required: true, default: 2 },
|
||||
location: {
|
||||
type: [Number],
|
||||
required: true,
|
||||
validate: {
|
||||
validator: function (v) {
|
||||
return v.length === 2;
|
||||
},
|
||||
message: "Invalid coordinate format (array not length of 2)."
|
||||
}
|
||||
},
|
||||
creator: { type: Types.ObjectId, ref: ModelNameRegister.User },
|
||||
participants: { type: [{ type: Types.ObjectId, ref: ModelNameRegister.User }], required: true, default: [] },
|
||||
difficulty: { type: Number, required: true },
|
||||
sport: { type: Types.ObjectId, ref: ModelNameRegister.Sport },
|
||||
createDate: { type: Date, required: true, default: Date.now }
|
||||
});
|
||||
|
||||
export default mongoose.model(ModelNameRegister.Match, matchSchema);
|
5
sports-matcher/server/schemas/modelNameRegister.js
Normal file
5
sports-matcher/server/schemas/modelNameRegister.js
Normal file
@@ -0,0 +1,5 @@
|
||||
export default {
|
||||
Match: "match",
|
||||
User: "user",
|
||||
Sport: "sport"
|
||||
};
|
19
sports-matcher/server/schemas/sportModel.js
Normal file
19
sports-matcher/server/schemas/sportModel.js
Normal file
@@ -0,0 +1,19 @@
|
||||
import mongoose from "mongoose";
|
||||
import ModelNameRegister from "./modelNameRegister.js";
|
||||
|
||||
const sportSchema = new mongoose.Schema({
|
||||
name: { type: String, required: true, unique: true, trim: true },
|
||||
minPlayers: { type: Number, required: true, default: 1 },
|
||||
description: { type: String, required: true, trim: true }
|
||||
});
|
||||
|
||||
sportSchema.pre("save", function (next) {
|
||||
this.name = this.name.toLowerCase();
|
||||
next();
|
||||
});
|
||||
|
||||
sportSchema.statics.findByName = function (name) {
|
||||
return this.findOne({ name: name.trim().toLowerCase() });
|
||||
};
|
||||
|
||||
export default mongoose.model(ModelNameRegister.Sport, sportSchema);
|
68
sports-matcher/server/schemas/userModel.js
Normal file
68
sports-matcher/server/schemas/userModel.js
Normal file
@@ -0,0 +1,68 @@
|
||||
import mongoose from "mongoose";
|
||||
import validator from "validator";
|
||||
import bcrypt from "bcrypt";
|
||||
import modelNameRegister from "./modelNameRegister.js";
|
||||
|
||||
const Types = mongoose.Schema.Types;
|
||||
|
||||
const userSchema = new mongoose.Schema({
|
||||
email: {
|
||||
type: String,
|
||||
required: true,
|
||||
minlength: 1,
|
||||
trim: true,
|
||||
unique: true,
|
||||
validate: {
|
||||
validator: validator.isEmail,
|
||||
message: "String not email.",
|
||||
}
|
||||
},
|
||||
firstName: { type: String, required: true, trim: true },
|
||||
lastName: { type: String, required: true, trim: true },
|
||||
joinDate: { type: Date, default: Date.now, required: true },
|
||||
phone: { type: Number, required: false, min: 0 },
|
||||
password: {
|
||||
type: String,
|
||||
required: true,
|
||||
minlength: 8
|
||||
// TODO: Custom validator for password requirements?
|
||||
},
|
||||
createdMatches: { type: [{ type: Types.ObjectId, ref: modelNameRegister.Match }], required: true, default: [] },
|
||||
participatingMatches: { type: [{ type: Types.ObjectId, ref: modelNameRegister.Match }], required: true, default: [] },
|
||||
emailPublicity: { type: Number, required: true, default: 0 },
|
||||
bioPublicity: { type: Boolean, required: true, default: false },
|
||||
phonePublicity: { type: Boolean, required: true, default: false },
|
||||
participatingMatchesPublicity: { type: Boolean, required: true, default: false },
|
||||
friends: { type: Types.ObjectId, ref: modelNameRegister.User },
|
||||
accessLevel: { type: Number, required: true, default: 0 },
|
||||
});
|
||||
|
||||
userSchema.statics.credentialsExist = async function (email, password) {
|
||||
let userModel = this;
|
||||
let user = await userModel.findOne({ email: email });
|
||||
if (!user) {
|
||||
return Promise.reject(new Error("Credentials do not exist."));
|
||||
}
|
||||
if (await bcrypt.compare(password, user.password)) {
|
||||
return user;
|
||||
}
|
||||
};
|
||||
|
||||
userSchema.pre("save", function (next) {
|
||||
let user = this;
|
||||
if (user.isModified("password")) { // Only perform hashing if the password has changed.
|
||||
bcrypt.genSalt(10, (err, salt) => {
|
||||
bcrypt.hash(user.password, salt, (err, hash) => {
|
||||
if (err) {
|
||||
throw err; // Probably not, but I'm gonna leave this here for now.
|
||||
}
|
||||
user.password = hash;
|
||||
next();
|
||||
});
|
||||
});
|
||||
} else {
|
||||
next();
|
||||
}
|
||||
});
|
||||
|
||||
export default mongoose.model(modelNameRegister.User, userSchema);
|
47
sports-matcher/server/server.js
Normal file
47
sports-matcher/server/server.js
Normal file
@@ -0,0 +1,47 @@
|
||||
import express from "express";
|
||||
import bodyParser from "body-parser";
|
||||
import mongoose from "mongoose";
|
||||
import UserController from "./controllers/userController.js";
|
||||
import MatchController from "./controllers/matchController.js";
|
||||
import SportController from "./controllers/sportController.js";
|
||||
import { userSession } from "./middleware/authority.js";
|
||||
import { mongooseDbName, mongoURI } from "./database/mongoose.js";
|
||||
import cors from "cors";
|
||||
|
||||
const server = express();
|
||||
const port = process.env.PORT || 5000;
|
||||
|
||||
server.use(express.static("public")); // For all client files.
|
||||
|
||||
// Connection documentation: https://mongoosejs.com/docs/connections.html
|
||||
try {
|
||||
mongoose.connect(mongoURI, {
|
||||
useNewUrlParser: true,
|
||||
useUnifiedTopology: true,
|
||||
dbName: mongooseDbName,
|
||||
});
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
|
||||
|
||||
if (process.env.NODE_ENV === "development") {
|
||||
mongoose.set("bufferCommands", false); // We want to know if there are connection issues immediately for development. Disables globally.
|
||||
|
||||
server.use(cors());
|
||||
}
|
||||
|
||||
// Docs: https://www.npmjs.com/package/body-parser
|
||||
server.use(bodyParser.json());
|
||||
server.use(bodyParser.urlencoded({ extended: true }));
|
||||
|
||||
server.use(userSession);
|
||||
|
||||
server.use("/user", UserController);
|
||||
server.use("/match", MatchController);
|
||||
server.use("/sport", SportController);
|
||||
|
||||
|
||||
server.listen(port, () => {
|
||||
console.log(`Server listening on port ${port}.`);
|
||||
});
|
Reference in New Issue
Block a user