import express from "express" ; import authenticate from "../middlewares/authenticate" ; import Track from "../models/track" ; import pick from "lodash.pick" ; const router = express . Router ( ) ; param { string } name param { number } year param { boolean } open param { number } playerId param { number } prePlayerId returns { Object [ ] } router . get ( "/" , authenticate ( [ ] ) , async ( req , res , next ) => { const query = pick ( req . query , [ "name" , "year" , "open" , "playerId" , "preOpen" , "prePlayerId" , ] ) ; if ( query . open ) query . open = query . open == "true" ; if ( query . open ) query . preOpen = query . preOpen == "true" ; if ( query . year ) query . year = parseFloat ( query . year ) ; if ( query . playerId ) query . players = parseFloat ( query . playerId ) ; if ( query . prePlayerId ) query . prePlayers = parseFloat ( query . prePlayerId ) ; delete query . playerId ; delete query . prePlayerId ; try { const tracks = await Track . find ( query , "-_id -__v -players -prePlayers" ) ; res . json ( tracks ) ; } catch ( e ) { next ( e ) ; } } ) ; param { string } name param { number } year param { number } description returns router . post ( "/" , authenticate ( [ "root" , "admin" ] ) , async ( req , res , next ) => { const { name , year , description , open , preOpen } = pick ( req . body , [ "name" , "year" , "description" , "open" , "preOpen" , ] ) ; try { const newTrack = new Track ( { name , year , description , open , preOpen , players : [ ] , prePlayers : [ ] , } ) ; const result = await newTrack . save ( ) ; res . setHeader ( "Location" , `/v1/tracks/${ result . id }` ) ; res . status ( 201 ) . end ( ) ; } catch ( err ) { next ( err ) ; } } ) ; param { number } id param { string } name param { number } year param { number } description param { boolean } open param { boolean } preOpen returns router . put ( "/:id" , authenticate ( [ "root" , "admin" ] ) , async ( req , res , next ) => { const id = req . params . id ; const query = pick ( req . body , [ "name" , "year" , "description" , "open" , "preOpen" , ] ) ; try { await Track . updateOne ( { id } , { $set : query } ) ; res . status ( 204 ) . end ( ) ; } catch ( err ) { next ( err ) ; } } ) ; param { number } id param { number } playerId returns router . post ( "/:id/players" , authenticate ( [ "root" , "admin" , "self" ] ) , async ( req , res , next ) => { const playerId = req . body . playerId ; const trackId = req . params . id ; if ( req . auth . selfCheckRequired ) { if ( parseFloat ( playerId ) !== req . auth . id ) { return res . status ( 401 ) . send ( "401 Unauthorized: Permission denied" ) ; } } try { const track = await Track . findOne ( { id : trackId } ) ; if ( ! track ) return res . status ( 404 ) . send ( "404 Not Found: Track not found." ) ; if ( ! track . open && req . auth . selfCheckRequired ) return res . status ( 403 ) . send ( "403 Forbidden: Track not opened." ) ; if ( track . prePlayers . indexOf ( playerId ) == - 1 && req . auth . selfCheckRequired ) return res . status ( 403 ) . send ( "403 Forbidden: You cannot join a track without joining its pre contest" ) ; const old = await Track . findOne ( { players : playerId , year : track . year , } ) ; if ( old ) return res . status ( 409 ) . send ( "409 Conflict: You should not join multiple tracks." ) ; await Track . findOneAndUpdate ( { id : trackId , players : { $ne : playerId } } , { $push : { players : playerId } } ) ; return res . status ( 204 ) . end ( ) ; } catch ( err ) { next ( err ) ; } } ) ; param { number } id param { number } playerId returns router . post ( "/:id/prePlayers" , authenticate ( [ "root" , "admin" , "self" ] ) , async ( req , res , next ) => { const playerId = req . body . playerId ; const trackId = req . params . id ; if ( req . auth . selfCheckRequired ) { if ( parseFloat ( playerId ) !== req . auth . id ) { return res . status ( 401 ) . send ( "401 Unauthorized: Permission denied" ) ; } } try { const track = await Track . findOne ( { id : trackId } ) ; if ( ! track ) return res . status ( 404 ) . send ( "404 Not Found: Track not found." ) ; if ( ! track . preOpen && req . auth . selfCheckRequired ) return res . status ( 403 ) . send ( "403 Forbidden: Track not pre-opened." ) ; await Track . findOneAndUpdate ( { id : trackId , players : { $ne : playerId } } , { $push : { prePlayers : playerId } } ) ; return res . status ( 204 ) . end ( ) ; } catch ( err ) { next ( err ) ; } } ) ; param { number } id param { number } playerId returns router . get ( "/:id/players/:playerId" , authenticate ( [ ] ) , async ( req , res ) => { const playerId = parseInt ( req . params . playerId , 10 ) ; const trackId = parseInt ( req . params . id , 10 ) ; const track = await Track . findOne ( { id : trackId , players : playerId } ) ; if ( track ) return res . status ( 200 ) . end ( ) ; return res . status ( 404 ) . send ( "404 Not Found: Track not found or player is not in" ) ; } ) ; param { number } id param { number } playerId returns router . get ( "/:id/prePlayers/:playerId" , authenticate ( [ ] ) , async ( req , res ) => { const playerId = parseInt ( req . params . playerId , 10 ) ; const trackId = parseInt ( req . params . id , 10 ) ; const track = await Track . findOne ( { id : trackId , prePlayers : playerId } ) ; if ( track ) return res . status ( 200 ) . end ( ) ; return res . status ( 404 ) . send ( "404 Not Found: Track not found or player is not in its pre-contest" ) ; } ) ; param { number } id param { number } playerId returns router . delete ( "/:id/players/:playerId" , authenticate ( [ "root" , "admin" , "self" ] ) , async ( req , res , next ) => { const playerId = parseInt ( req . params . playerId , 10 ) ; const trackId = parseInt ( req . params . id , 10 ) ; if ( req . auth . selfCheckRequired ) { if ( playerId !== req . auth . id ) { return res . status ( 401 ) . send ( "401 Unauthorized: Permission denied" ) ; } } try { const playersQuery = { players : playerId } ; const track = await Track . findOne ( { id : trackId , ... playersQuery } ) ; if ( ! track ) return res . status ( 404 ) . send ( "404 Not Found: Track not existed" ) ; if ( ! track . open && req . auth . selfCheckRequired ) return res . status ( 403 ) . send ( "403 Forbidden: Track not opened." ) ; await Track . findOneAndUpdate ( { id : trackId } , { $pull : playersQuery } ) ; return res . status ( 204 ) . end ( ) ; } catch ( err ) { next ( err ) ; } } ) ; param { number } id param { number } playerId returns router . delete ( "/:id/prePlayers/:playerId" , authenticate ( [ "root" , "admin" , "self" ] ) , async ( req , res , next ) => { const playerId = parseInt ( req . params . playerId , 10 ) ; const trackId = parseInt ( req . params . id , 10 ) ; if ( req . auth . selfCheckRequired ) { if ( playerId !== req . auth . id ) { return res . status ( 401 ) . send ( "401 Unauthorized: Permission denied" ) ; } } try { const playersQuery = { prePlayers : playerId } ; const track = await Track . findOne ( { id : trackId , ... playersQuery } ) ; if ( ! track ) return res . status ( 404 ) . send ( "404 Not Found: Track not existed" ) ; if ( ! track . preOpen && req . auth . selfCheckRequired ) return res . status ( 403 ) . send ( "403 Forbidden: Track not opened." ) ; await Track . findOneAndUpdate ( { id : trackId } , { $pull : playersQuery } ) ; return res . status ( 204 ) . end ( ) ; } catch ( err ) { next ( err ) ; } } ) ; param { number } id param { boolean } playerInfo param { boolean } prePlayerInfo returns { Object } router . get ( "/:id" , authenticate ( [ ] ) , async ( req , res , next ) => { const id = req . params . id ; const playerInfo = req . query . playerInfo || false ; const prePlayerInfo = req . query . prePlayerInfo || false ; try { let query = "-_id -__v" ; if ( ! playerInfo ) query += " -players" ; if ( ! prePlayerInfo ) query += " -prePlayers" ; const result = await Track . findOne ( { id } , query ) ; if ( ! result ) return res . status ( 404 ) . send ( "404 Not Found: Track not found." ) ; return res . json ( result ) ; } catch ( e ) { next ( e ) ; } } ) ; param { string } id returns router . delete ( "/:id" , authenticate ( [ "root" , "admin" ] ) , async ( req , res , next ) => { try { const deleteTrack = await Track . findOneAndDelete ( { id : req . params . id , } ) ; if ( ! deleteTrack ) { return res . status ( 404 ) . send ( "404 Not Found: Track does not exist" ) ; } res . status ( 204 ) . end ( ) ; } catch ( err ) { next ( err ) ; } } ) ; export default router ;