From 233a8c2462ecd29ad5317d939fe9bdc9e19c80c6 Mon Sep 17 00:00:00 2001 From: rlmcneary2 Date: Fri, 28 Jun 2019 14:08:37 -0500 Subject: [PATCH] 345 - NHT: Users shall be able to create stats. --- .../20190627103100-add-stats-creator.js | 13 ++++++++++ models/stat.js | 10 ++++++++ public/components/game/details/details.js | 8 +++++-- public/components/game/details/details.stache | 2 +- public/models/stat.js | 18 ++++++++++++++ services/loggedIn.js | 15 ++++++++++++ services/stats.js | 24 +++++++++++++++---- 7 files changed, 82 insertions(+), 8 deletions(-) create mode 100644 migrations/20190627103100-add-stats-creator.js create mode 100644 services/loggedIn.js diff --git a/migrations/20190627103100-add-stats-creator.js b/migrations/20190627103100-add-stats-creator.js new file mode 100644 index 00000000..1c2f11d0 --- /dev/null +++ b/migrations/20190627103100-add-stats-creator.js @@ -0,0 +1,13 @@ +var async = require('async'); + +exports.up = function(db, callback) { + async.series([ + db.addColumn.bind(db, "stats","creatorId",{type: 'int'}) + ], callback); +}; + +exports.down = function(db, callback) { + async.series([ + db.removeColumn.bind(db, "stats","creatorId") + ], callback); +}; diff --git a/models/stat.js b/models/stat.js index bf151e2d..009296f9 100644 --- a/models/stat.js +++ b/models/stat.js @@ -41,6 +41,16 @@ var Stat = bookshelf.Model.extend( player: function(){ var Player = require("./player"); return this.belongsTo(Player,"playerId"); + }, + /** + * @function + * + * Informs Bookshelf.js that the `creator` property will be a [models/user] + * model with an `id` that matches the `creatorId` specified in the query. + **/ + creator: function() { + var User = require("./user"); + return this.belongsTo(User, "creatorId"); } }); diff --git a/public/components/game/details/details.js b/public/components/game/details/details.js index 22b9b2bb..653915d4 100644 --- a/public/components/game/details/details.js +++ b/public/components/game/details/details.js @@ -225,7 +225,7 @@ export const ViewModel = DefineMap.extend('GameDetailsVM', * ``` */ showStatMenuFor: function(player, element, event){ - if(!this.session || !this.session.isAdmin()) { + if(!this.session.user) { return; } var youtubePlayer = this.youtubePlayer; @@ -236,7 +236,8 @@ export const ViewModel = DefineMap.extend('GameDetailsVM', time: time, playerId: player.id, gameId: this.game.id, - player: player + player: player, + creatorId: this.session.user.id }); }, /** @@ -549,6 +550,9 @@ export const ViewModel = DefineMap.extend('GameDetailsVM', top: $(containers[index]).offset().top - first.top + (height/2) }; }, + createdBy: function(stat) { + return this.session && (this.session.isAdmin() || stat.creatorId === this.session.user.id); + }, connectedCallback(el) { this.element = el; diff --git a/public/components/game/details/details.stache b/public/components/game/details/details.stache index 2704f2d4..b7caf060 100644 --- a/public/components/game/details/details.stache +++ b/public/components/game/details/details.stache @@ -31,7 +31,7 @@ {{ type }} - {{# if(scope.vm.session.isAdmin()) }} + {{# if(scope.vm.createdBy(this)) }} {{/ if }} diff --git a/public/models/stat.js b/public/models/stat.js index 5ccafe5a..1e91e82a 100644 --- a/public/models/stat.js +++ b/public/models/stat.js @@ -25,6 +25,7 @@ import { DefineMap, DefineList, QueryLogic, superModel } from "can"; import bookshelfService from "./bookshelf-service"; import Player from "bitballs/models/player"; +import User from "bitballs/models/user"; var Stat = DefineMap.extend('Stat', { @@ -96,6 +97,23 @@ var Stat = DefineMap.extend('Stat', return Math.round(newVal); } }, + /** + * @property {bitballs/models/user} bitballs/models/stat.properties.creator creator + * @parent bitballs/models/user.properties + * + * User related to the stats + */ + creator: { + Type: User, + serialize: false + }, + /** + * @property {Number} bitballs/models/stat.properties.creatorId creatorId + * @parent bitballs/models/stat.properties + * + * The user that created the stat. + */ + creatorId: 'number', default: 'any' }); diff --git a/services/loggedIn.js b/services/loggedIn.js new file mode 100644 index 00000000..8bf0dc91 --- /dev/null +++ b/services/loggedIn.js @@ -0,0 +1,15 @@ +module.exports = function( respObj, status ) { + if ( typeof respObj === "string" ) { + respObj = { + message: respObj + }; + } + + return function ( req, res, next ) { + if ( req.user ) { + next(); + } else { + res.status( status || 404 ).end(); + } + } +} diff --git a/services/stats.js b/services/stats.js index 7377f895..d48eda71 100644 --- a/services/stats.js +++ b/services/stats.js @@ -98,6 +98,7 @@ var app = require("./app"); var Stat = require("../models/stat"); var adminOnly = require( "./adminOnly" ); +var loggedIn = require( "./loggedIn" ); var separateQuery = require("./separate-query"); app.get('/services/stats', function(req, res){ @@ -124,13 +125,26 @@ app.put('/services/stats/:id', adminOnly( "Must be an admin to update stats" ), }); }); -app.delete('/services/stats/:id', adminOnly( "Must be an admin to delete stats" ), function(req, res){ - new Stat({id: req.params.id}).destroy().then(function(stat){ - res.send({}); +app.delete('/services/stats/:id', function(req, res){ + new Stat({id: req.params.id}) + .fetch() + .then(stat => { + return Promise.all([stat, stat.get("creatorId")]); + }) + .then(([stat, creatorId]) => { + debugger; + if ( req.isAdmin || req.user.attributes.id === creatorId ) { + stat.destroy() + .then(() => { + res.send({}); + }); + } else { + res.status( status || 404 ).end(); + } + }); }); -}); -app.post('/services/stats', adminOnly( "Must be an admin to create stats" ), function(req, res) { +app.post('/services/stats', loggedIn( "Must be logged in to create stats" ), function(req, res) { new Stat(clean(req.body)).save().then(function(stat){ res.send({id: stat.get('id')}); }, function(e){