From 3befe69f308075e591441e31cb2427850b4c75ee Mon Sep 17 00:00:00 2001 From: garrettmills Date: Wed, 4 Nov 2020 21:18:47 -0600 Subject: [PATCH] Add API endpoint to fetch team --- app/controllers/Teams.controller.js | 12 ++++ app/models/Player.model.js | 36 ++++++++++ app/models/Team.model.js | 42 +++++++++++- .../middleware/HomeLogger.middleware.js | 32 --------- .../middleware/InjectUserTeam.middleware.js | 27 ++++++++ app/routing/routers/api.routes.js | 68 +++++++++++++++++++ app/routing/routers/index.routes.js | 3 - 7 files changed, 184 insertions(+), 36 deletions(-) create mode 100644 app/models/Player.model.js delete mode 100644 app/routing/middleware/HomeLogger.middleware.js create mode 100644 app/routing/middleware/InjectUserTeam.middleware.js create mode 100644 app/routing/routers/api.routes.js diff --git a/app/controllers/Teams.controller.js b/app/controllers/Teams.controller.js index 3239c63..b134aeb 100644 --- a/app/controllers/Teams.controller.js +++ b/app/controllers/Teams.controller.js @@ -9,6 +9,18 @@ class Teams extends Controller { return [...super.services, 'models'] } + /** + * Return the API data for the current user's team. + * Requires an authenticated user. + * @param req + * @param res + * @param next + * @return {Promise} + */ + async get_my_team(req, res, next) { + return res.api(await req.user_team.to_api()) + } + async list_all_teams(req, res) { const TeamModel = this.models.get('Team') const teams = await TeamModel.find() diff --git a/app/models/Player.model.js b/app/models/Player.model.js new file mode 100644 index 0000000..8451596 --- /dev/null +++ b/app/models/Player.model.js @@ -0,0 +1,36 @@ +const { Model } = require('flitter-orm') + +/* + * Player Model + * ------------------------------------------------------------- + */ +class Player extends Model { + static get services() { + return [...super.services, 'output', 'models'] + } + + /* + * Define the flitter-orm schema of the model. + */ + static get schema() { + return { + player_number: String, + player_name: String, + player_position: String, + team_name: String, + image_url: String, + } + } + + async to_api() { + return { + player_number: this.player_number, + player_name: this.player_name, + player_position: this.player_position, + team_name: this.team_name, + image_url: this.image_url, + } + } +} + +module.exports = exports = Player diff --git a/app/models/Team.model.js b/app/models/Team.model.js index 87041b3..361a729 100644 --- a/app/models/Team.model.js +++ b/app/models/Team.model.js @@ -6,7 +6,7 @@ const { Model } = require('flitter-orm') */ class Team extends Model { static get services() { - return [...super.services, 'output'] + return [...super.services, 'output', 'models'] } /* @@ -20,6 +20,46 @@ class Team extends Model { player_ids: [String], } } + + /** + * Look up or create a team for the given user. + * @param {User} user + * @return {Promise} + */ + static async getForUser(user) { + // try to find an existing team first + const existing_team = await this.findOne({ user_id: user.id }) + if ( existing_team ) return existing_team + + // otherwise create a team for the user + const new_team = new this({ + user_id: user.id, + team_name: `${user.uid}'s team`, + player_ids: [], + }) + + // Generate the next team number + const highest_num_team = await this.sort('-team_num').findOne() + if ( highest_num_team ) { + new_team.team_num = highest_num_team.team_num + 1 + } else { + new_team.team_num = 1 + } + + await new_team.save() + return new_team + } + + async to_api() { + const User = this.models.get('auth:User') + + return { + user_id: this.user_id, + user_display: (await User.findById(this.user_id))?.uid || 'Unknown User', + team_name: this.team_name, + team_num: this.team_num, + } + } } module.exports = exports = Team diff --git a/app/routing/middleware/HomeLogger.middleware.js b/app/routing/middleware/HomeLogger.middleware.js deleted file mode 100644 index fbc452a..0000000 --- a/app/routing/middleware/HomeLogger.middleware.js +++ /dev/null @@ -1,32 +0,0 @@ -const { Middleware } = require('libflitter') - -/* - * HomeLogger Middleware - * ------------------------------------------------------------- - * This is a sample middleware. It simply prints a console message when - * the route that it is tied to is accessed. By default, it is called if - * the '/' route is accessed. It can be injected in routes globally using - * the middlewares service. - */ -class HomeLogger extends Middleware { - static get services() { - return [...super.services, 'output'] - } - - /* - * Run the middleware test. - * This method is required by all Flitter middleware. - * It should either call the next function in the stack, - * or it should handle the response accordingly. - */ - test(req, res, next, args) { - this.output.debug('Home was accessed!') - - /* - * Call the next function in the stack. - */ - next() - } -} - -module.exports = HomeLogger diff --git a/app/routing/middleware/InjectUserTeam.middleware.js b/app/routing/middleware/InjectUserTeam.middleware.js new file mode 100644 index 0000000..276db85 --- /dev/null +++ b/app/routing/middleware/InjectUserTeam.middleware.js @@ -0,0 +1,27 @@ +const { Middleware } = require('libflitter') + +/* + * InjectUserTeam Middleware + * ------------------------------------------------------------- + * For the authenticated user, looks up the associated Team instance + * and injects it as request.team. + */ +class InjectUserTeam extends Middleware { + static get services() { + return [...super.services, 'models'] + } + + /* + * Run the middleware test. + */ + async test(req, res, next, args = {}){ + if ( !req.user ) return res.redirect('/auth/login') + + const Team = this.models.get('Team') + req.user_team = await Team.getForUser(req.user) + + return next() + } +} + +module.exports = InjectUserTeam diff --git a/app/routing/routers/api.routes.js b/app/routing/routers/api.routes.js new file mode 100644 index 0000000..9e24363 --- /dev/null +++ b/app/routing/routers/api.routes.js @@ -0,0 +1,68 @@ +/* + * API Routes + * ------------------------------------------------------------- + * These routes are related to the AJAX API used by the front-end. + */ +const index = { + + /* + * Define the prefix applied to each of these routes. + * For example, if prefix is '/auth': + * '/' becomes '/auth' + * '/login' becomes '/auth/login' + */ + prefix: '/api/v1', + + /* + * Define middleware that should be applied to all + * routes defined in this file. Middleware should be + * included using its non-prefixed canonical name. + * + * You can pass arguments along to a middleware by + * specifying it as an array where the first element + * is the canonical name of the middleware and the + * second element is the argument passed to the + * handler's test() method. + */ + middleware: [ + // Require an authenticated user + 'auth:UserOnly', + + // Inject the user's team + 'InjectUserTeam', + ], + + /* + * Define GET routes. + * These routes are registered as GET methods. + * Handlers for these routes should be specified as + * an array of canonical references to controller methods + * or middleware that are applied in order. + */ + get: { + // handlers should be a list of either controller:: or middleware:: references + // e.g. middleware::HomeLogger + // e.g. controller::Home.welcome + '/': [ + 'controller::Home.welcome' + ], + + '/my-team': ['controller::Teams.get_my_team'], + }, + + /* + * Define POST routes. + * These routes are registered as POST methods. + * Handlers for these routes should be specified as + * an array of canonical references to controller methods + * or middleware that are applied in order. + */ + post: { + + }, + + // You can include other HTTP verbs here. + // Supported ones are: get, post, put, delete, copy, patch +} + +module.exports = exports = index diff --git a/app/routing/routers/index.routes.js b/app/routing/routers/index.routes.js index 5c2a30b..b72d53d 100644 --- a/app/routing/routers/index.routes.js +++ b/app/routing/routers/index.routes.js @@ -28,9 +28,6 @@ const index = { middleware: [ // Sets the locale scope ['i18n:Scope', {scope: 'common'}], - - ['HomeLogger', {note: 'arguments can be specified as the second element in this array'}], - // 'MiddlewareName', // Or without arguments ], /*