diff --git a/website/server/controllers/api-v3/user.js b/website/server/controllers/api-v3/user.js index 9903d007d3..c0418264ba 100644 --- a/website/server/controllers/api-v3/user.js +++ b/website/server/controllers/api-v3/user.js @@ -27,8 +27,39 @@ let api = {}; * @apiName UserGet * @apiGroup User * + * @apiDescription The user profile contains data related to the authenticated user including (but not limited to); + * Achievements + * Authentications (including types and timestamps) + * Challenges + * Flags (including armoire, tutorial, tour etc...) + * Guilds + * History (including timestamps and values) + * Inbox (includes message history) + * Invitations (to parties/guilds) + * Items (character's full inventory) + * New Messages (flags for groups/guilds that have new messages) + * Notifications + * Party (includes current quest information) + * Preferences (user selected prefs) + * Profile (name, photo url, blurb) + * Purchased (includes purchase history, gem purchased items, plans) + * PushDevices (identifiers for mobile devices authorized) + * Stats (standard RPG stats, class, buffs, xp, etc..) + * Tags + * TasksOrder (list of all ids for dailys, habits, rewards and todos) + * * @apiSuccess {Object} data The user object - */ + * + * @apiSuccessExample {json} Result: + * { + * "success": true, + * "data": { + * -- User data included here, for details of the user model see: + * -- https://github.com/HabitRPG/habitica/tree/develop/website/server/models/user + * } + * } + * +*/ api.getUser = { method: 'GET', middlewares: [authWithHeaders()], @@ -46,11 +77,30 @@ api.getUser = { }; /** - * @api {get} /api/v3/user/inventory/buy Get the gear items available for purchase for the current user + * @api {get} /api/v3/user/inventory/buy Get the gear items available for purchase for the authenticated user * @apiName UserGetBuyList * @apiGroup User * - * @apiSuccess {Object} data The buy list + * @apiSuccessExample {json} Success-Response: + * { + * "success": true, + * "data": [ + * { + * "text": "Training Sword", + * "notes": "Practice weapon. Confers no benefit.", + * "value": 1, + * "type": "weapon", + * "key": "weapon_warrior_0", + * "set": "warrior-0", + * "klass": "warrior", + * "index": "0", + * "str": 0, + * "int": 0, + * "per": 0, + * "con": 0 + * } + * ] + * } */ api.getBuyList = { method: 'GET', @@ -142,11 +192,31 @@ let checkPreferencePurchase = (user, path, item) => { /** * @api {put} /api/v3/user Update the user - * @apiDescription Example body: {'stats.hp':50, 'preferences.background': 'beach'} * @apiName UserUpdate * @apiGroup User * - * @apiSuccess {Object} data The updated user object + * @apiDescription Some of the user items can be updated, such as preferences, flags and stats. + ^ + * @apiParamExample {json} Request-Example: + * { + * "achievements.habitBirthdays": 2, + * "profile.name": "MadPink", + * "stats.hp": 53, + * "flags.warnedLowHealth":false, + * "preferences.allocationMode":"flat", + * "preferences.hair.bangs": 3 + * } + * + * @apiSuccess {Object} data The updated user object, the result is identical to the get user call + * + * @apiError (401) {NotAuthorized} messageUserOperationProtected Returned if the change is not allowed. + * + * @apiErrorExample {json} Error-Response: + * { + * "success": false, + * "error": "NotAuthorized", + * "message": "path `stats.class` was not saved, as it's a protected path." + * } */ api.updateUser = { method: 'PUT', @@ -179,9 +249,32 @@ api.updateUser = { * @apiName UserDelete * @apiGroup User * - * @apiParam {String} password The user's password (unless it's a Facebook account) + * @apiParam {String} password The user's password if the account uses local authentication * * @apiSuccess {Object} data An empty Object + * + * @apiSuccessExample {json} Result: + * { + * "success": true, + * "data": {} + * } + * + * @apiError {BadRequest} MissingPassword The password was not included in the request + * @apiError {BadRequest} NotAuthorized There is no account that uses those credentials. + * + * @apiErrorExample {json} + * { + * "success": false, + * "error": "BadRequest", + * "message": "Invalid request parameters.", + * "errors": [ + * { + * "message": "Missing password.", + * "param": "password" + * } + * ] + * } + * */ api.deleteUser = { method: 'DELETE', @@ -240,8 +333,17 @@ function _cleanChecklist (task) { * @apiName UserGetAnonymized * @apiGroup User * + * @apiDescription Returns the user's data without: + * Authentication information + * NewMessages/Invitations/Inbox + * Profile + * Purchased information + * Contributor information + * Special items + * Webhooks + * * @apiSuccess {Object} data.user - * @apiSuccess {Array} data.tasks + * @apiSuccess {Object} data.tasks **/ api.getUserAnonymized = { method: 'GET', @@ -306,11 +408,15 @@ const partyMembersFields = 'profile.name stats achievements items.special'; * @apiGroup User * * @apiParam {String=fireball, mpHeal, earth, frost, smash, defensiveStance, valorousPresence, intimidate, pickPocket, backStab, toolsOfTrade, stealth, heal, protectAura, brightness, healAll} spellId The skill to cast. - * @apiParam {UUID} targetId Optional query parameter, the id of the target when casting a skill on a party member or a task + * @apiParam (Body) {UUID} targetId Query parameter, necessary if the spell is cast on a party member or task. Not used if the spell is case on onesself or the user's current party. + * @apiParamExample {json} Query example: + * { + * "targetId":"fd427623-9a69-4aac-9852-13deb9c190c3" + * } * * @apiSuccess data Will return the modified targets. For party members only the necessary fields will be populated. The user is always returned. * - * @apiExample Skill Key to Name Mapping + * @apiDescription Skill Key to Name Mapping * Mage * fireball: "Burst of Flames" * mpHeal: "Ethereal Surge" @@ -335,10 +441,10 @@ const partyMembersFields = 'profile.name stats achievements items.special'; * brightness: "Searing Brightness" * healAll: "Blessing" * + * @apiError (400) {NotAuthorized} Not enough mana. * @apiUse TaskNotFound * @apiUse PartyNotFound * @apiUse UserNotFound - * */ api.castSpell = { method: 'POST', @@ -501,7 +607,15 @@ api.castSpell = { * @apiName UserSleep * @apiGroup User * + * @apiDescription Toggles the sleep key under user preference true and false. + * * @apiSuccess {boolean} data user.preferences.sleep + * + * @apiSuccessExample {json} Return-example + * { + * "success": true, + * "data": false + * } */ api.sleep = { method: 'POST', @@ -516,13 +630,25 @@ api.sleep = { }; /** - * @api {post} /api/v3/user/allocate Allocate an attribute point + * @api {post} /api/v3/user/allocate Allocate a single attribute point * @apiName UserAllocate * @apiGroup User * - * @apiParam {String} stat Query parameter - Defaults to 'str', mast be one of be of str, con, int or per + * @apiParam (Body) {String="str","con","int","per"} stat Query parameter - Default ='str' * - * @apiSuccess {Object} data user.stats + * @apiParamExample {json} Example request + * {"stat":"int"} + * + * @apiSuccess {Object} data Returns stats from the user profile + * + * @apiError {NotAuthorized} NoPoints Not enough attribute points to increment a stat. + * + * @apiErrorExample {json} + * { + * "success": false, + * "error": "NotAuthorized", + * "message": "You don't have enough attribute points." + * } */ api.allocate = { method: 'POST', @@ -538,10 +664,46 @@ api.allocate = { /** * @api {post} /api/v3/user/allocate-now Allocate all attribute points - * @apiDescription Uses the user's chosen automatic allocation method, or if none, assigns all to STR. + * @apiDescription Uses the user's chosen automatic allocation method, or if none, assigns all to STR. Note: will return success, even if there are 0 points to allocate. * @apiName UserAllocateNow * @apiGroup User * + * @apiSuccessExample {json} Success-Response: + * { + * "success": true, + * "data": { + * "hp": 50, + * "mp": 38, + * "exp": 7, + * "gp": 284.8637271160258, + * "lvl": 10, + * "class": "rogue", + * "points": 0, + * "str": 2, + * "con": 2, + * "int": 3, + * "per": 3, + * "buffs": { + * "str": 0, + * "int": 0, + * "per": 0, + * "con": 0, + * "stealth": 0, + * "streaks": false, + * "snowball": false, + * "spookySparkles": false, + * "shinySeed": false, + * "seafoam": false + * }, + * "training": { + * "int": 0, + * "per": 0, + * "str": 0, + * "con": 0 + * } + * } + * } + * * @apiSuccess {Object} data user.stats */ api.allocateNow = { @@ -563,6 +725,27 @@ api.allocateNow = { * @apiGroup User * * @apiParam {String} key The item to buy + * + * @apiSuccess data User's data profile + * @apiSuccess message Item purchased + * + * @apiSuccessExample {json} Purchased a rogue short sword for example: + * { + * "success": true, + * "data": { + * ---TRUNCATED USER RECORD--- + * }, + * "message": "Bought Short Sword" + * } + * + * @apiError (400) {NotAuthorized} messageAlreadyOwnGear Already own equipment + * @apiError (400) {NotAuthorized} messageNotEnoughGold Not enough gold for the purchase + * + * @apiErrorExample {json} NotAuthorized Already own + * {"success":false,"error":"NotAuthorized","message":"You already own that piece of equipment"} + * + * @apiErrorExample {json} NotAuthorized Not enough gold + * {"success":false,"error":"NotAuthorized","message":"Not Enough Gold"} */ api.buy = { method: 'POST',