diff --git a/src/server/controllers/PlayerControllerMongoose.js b/src/server/controllers/PlayerControllerMongoose.js index 66fd1b7..fbea26f 100644 --- a/src/server/controllers/PlayerControllerMongoose.js +++ b/src/server/controllers/PlayerControllerMongoose.js @@ -1,4 +1,3 @@ -const GameModel = require("../models/GameModel"); const PlayerModel = require("../models/PlayerModel"); /** diff --git a/src/server/controllers/UserControllerMongoose.js b/src/server/controllers/UserControllerMongoose.js index 519250c..81de795 100644 --- a/src/server/controllers/UserControllerMongoose.js +++ b/src/server/controllers/UserControllerMongoose.js @@ -1,9 +1,10 @@ const bcrypt = require("bcryptjs"); +const fs = require("node:fs/promises"); const UserModel = require("../models/UserModel"); const BoardModel = require("../models/BoardModel"); -exports.listUsers = (req, res) => { +exports.listUsers = () => { return new Promise((resolve, reject) => { UserModel.find({}, "-password") .then((users) => { @@ -141,3 +142,30 @@ exports.addBoardToUser = ( board ) => { }) }); }; + +exports.updateProfilePicture = ( userId, pfpFilename ) => { + return new Promise( ( resolve, reject ) => { + UserModel.findByIdAndUpdate( userId, { pfpFilename: pfpFilename } ) + .then( ( userBefore ) => { + if( userBefore === null ){ + let userNotFoundError = new Error(`No user found in session"`); + userNotFoundError.name = "NotFoundError"; + throw userNotFoundError; + } + if( userBefore.pfpFilename !== null ){ + return fs.rm( "public/uploads/" + userBefore.pfpFilename ); + } else { + return undefined; + } + }) + .then( () => { + return UserModel.findById( userId , {}, { new: true }); + }) + .then( ( user ) => { + resolve( user ); + }) + .catch( ( err ) => { + reject( err ); + }) + }); +}; diff --git a/src/server/models/UserModel.js b/src/server/models/UserModel.js index da16bfb..248af69 100644 --- a/src/server/models/UserModel.js +++ b/src/server/models/UserModel.js @@ -11,6 +11,7 @@ const UserSchema = new Schema({ }, password: { type: String, required: true, }, boards: [{ type: Schema.Types.ObjectId, ref: "Board" }], + pfpFilename: [{ type: String, required: false, default: null }], }); // Virtual for player's URL diff --git a/src/server/routes/UserRouter.js b/src/server/routes/UserRouter.js index 707cb1f..be2c41e 100644 --- a/src/server/routes/UserRouter.js +++ b/src/server/routes/UserRouter.js @@ -60,21 +60,26 @@ const fileFilterFn = function( req, file, cb ){ return; } - let board = JSON.parse( req.body.board ); + if( req.body.board ){ - boardController.isBoardFromUser( board.boardId, req.session.user ) - .then( ( isFromUser ) => { - if( !isFromUser && board.boardId !== undefined ){ - cb( new Error( "The associated board is not the users" ) ); - } else { - if( req.session.user === undefined ){ - cb( new Error( "Only logged in Users can upload pictures" ) ); - return; + let board = JSON.parse( req.body.board ); + + boardController.isBoardFromUser( board.boardId, req.session.user ) + .then( ( isFromUser ) => { + if( !isFromUser && board.boardId !== undefined ){ + cb( new Error( "The associated board is not the users" ) ); + } else { + if( req.session.user === undefined ){ + cb( new Error( "Only logged in Users can upload pictures" ) ); + return; + } + + cb( null, true ); } - - cb( null, true ); - } - }); + }); + } else { + cb( null, true ); + } } @@ -84,7 +89,7 @@ router.get("/", (req, res)=>{ if( req.session.user !== undefined ){ userController.findUser( req.session.user ) .then( user => { - res.send({success: true, user: { username: user.username } } ); + res.send({success: true, user: { username: user.username, pfpFilename: user.pfpFilename } } ); }) .catch( err => { console.debug(err); @@ -124,6 +129,7 @@ router.post("/login", (req, res)=>{ res.send({success: true, user: { username: req.session.user } } ); }) .catch( ( err ) => { + console.error( err ); res.send({success:false, error: "Error with logging you in" }); }) }else{ @@ -240,19 +246,45 @@ router.get("/boards/:id", (req, res) => { }); +router.get("/pfp/:filename", (req, res) => { + console.log("Getting pfp: ", req.params.filename); + let options = { + root: 'public/uploads', + dotfiles: 'deny', + headers: { + 'Access-Control-Allow-Origin': '*', + } + } + res.sendFile( req.params.filename, options ); + }); + + router.post("/pfp", upload.single( "pfp" ), (req, res) => { if( req.session.user === undefined ){ res.send( { success: false, error: "Not logged in!" } ); } else { - let imageFile = null; if( !req.file ){ console.error( "No file attached" ); - return; + throw new Error("No file attached to be saved" ); } - imageFile = req.file; + let imageFile = req.file; return userController.updateProfilePicture( req.session.user, imageFile.filename ) .then( ( user ) => { - res.send( { success: true, newProfilePicture: user.profilePicture } ); + res.send( { success: true, newProfilePicture: user.pfpFilename } ); + }) + .catch( ( err ) => { + res.send( { success: false, error: err } ); + }); + } +}); + +router.delete("/pfp", (req, res) => { + if( req.session.user === undefined ){ + res.send( { success: false, error: "Not logged in!" } ); + } else { + return userController.updateProfilePicture( req.session.user, null ) + .then( ( _user ) => { + res.send( { success: true, } ); }) .catch( ( err ) => { res.send( { success: false, error: err } ); diff --git a/src/server/server.js b/src/server/server.js index d650542..caee48f 100644 --- a/src/server/server.js +++ b/src/server/server.js @@ -34,7 +34,7 @@ app.use(helmet( "media-src": ["'self'", "data:"], "style-src-elem": ["'self'", "'unsafe-inline'"], "connect-src": ["'self'", "ws:"], - "img-src": ["'self'", "blob:", "data:"], + "img-src": ["'self'", "blob:", "data:"], } } } diff --git a/src/webapp/assets/images/PFP_Bear.svg b/src/webapp/assets/images/PFP_Bear.svg new file mode 100644 index 0000000..5c92473 --- /dev/null +++ b/src/webapp/assets/images/PFP_Bear.svg @@ -0,0 +1,93 @@ + + + + diff --git a/src/webapp/assets/images/PFP_BearHead.svg b/src/webapp/assets/images/PFP_BearHead.svg new file mode 100644 index 0000000..0622bd9 --- /dev/null +++ b/src/webapp/assets/images/PFP_BearHead.svg @@ -0,0 +1,89 @@ + + + + diff --git a/src/webapp/assets/images/PFP_Person.svg b/src/webapp/assets/images/PFP_Person.svg new file mode 100644 index 0000000..843fb97 --- /dev/null +++ b/src/webapp/assets/images/PFP_Person.svg @@ -0,0 +1,54 @@ + + + + diff --git a/src/webapp/assets/scss/styles.scss b/src/webapp/assets/scss/styles.scss index cdbe75f..599640c 100644 --- a/src/webapp/assets/scss/styles.scss +++ b/src/webapp/assets/scss/styles.scss @@ -87,6 +87,8 @@ $modal-content-bg: $dark-blue; $font-family-base: "Urbanist"; +$enable-caret: false; + // 2. Include any default variable overrides here @@ -188,4 +190,8 @@ $utilities: map-merge( .image-contain{ object-fit: contain; +} + +.pfp{ + object-fit: cover; } \ No newline at end of file diff --git a/src/webapp/components/blocks/ChangeProfilePicture.vue b/src/webapp/components/blocks/ChangeProfilePicture.vue index 84a222f..5717fc7 100644 --- a/src/webapp/components/blocks/ChangeProfilePicture.vue +++ b/src/webapp/components/blocks/ChangeProfilePicture.vue @@ -1,11 +1,17 @@ @@ -36,23 +71,51 @@ revealAnswer();