diff --git a/docs-web/src/main/java/com/sismics/docs/rest/resource/BaseResource.java b/docs-web/src/main/java/com/sismics/docs/rest/resource/BaseResource.java index ad3fe187..f05d6d56 100644 --- a/docs-web/src/main/java/com/sismics/docs/rest/resource/BaseResource.java +++ b/docs-web/src/main/java/com/sismics/docs/rest/resource/BaseResource.java @@ -21,6 +21,29 @@ import com.sismics.util.filter.TokenBasedSecurityFilter; * @author jtremeaux */ public abstract class BaseResource { + /** + * @apiDefine admin Admin + * Only the admin user can access this resource + */ + + /** + * @apiDefine user Authenticated user + * All authenticated users can access this resource + */ + + /** + * @apiDefine none Anonymous user + * This resource can be accessed anonymously + */ + + /** + * @apiDefine server Server error + */ + + /** + * @apiDefine client Client error + */ + /** * Injects the HTTP request. */ diff --git a/docs-web/src/main/java/com/sismics/docs/rest/resource/UserResource.java b/docs-web/src/main/java/com/sismics/docs/rest/resource/UserResource.java index 433812ec..fb4bb8ea 100644 --- a/docs-web/src/main/java/com/sismics/docs/rest/resource/UserResource.java +++ b/docs-web/src/main/java/com/sismics/docs/rest/resource/UserResource.java @@ -67,7 +67,21 @@ import com.sismics.util.totp.GoogleAuthenticatorKey; public class UserResource extends BaseResource { /** * Creates a new user. - * + * + * @api {put} /user Register a new user + * @apiName PutUser + * @apiGroup User + * @apiParam {String{3..50}} username Username + * @apiParam {String{8..50}} password Password + * @apiParam {String{1..100}} email E-mail + * @apiParam {Number} storage_quota Storage quota (in bytes) + * @apiSuccess {String} status Status OK + * @apiError (server) PrivateKeyError Error while generating a private key + * @apiError (client) AlreadyExistingUsername Login already used + * @apiError (server) UnknownError Unknown server error + * @apiPermission admin + * @apiVersion 1.0.0 + * * @param username User's username * @param password Password * @param email E-Mail @@ -88,7 +102,7 @@ public class UserResource extends BaseResource { username = ValidationUtil.validateLength(username, "username", 3, 50); ValidationUtil.validateAlphanumeric(username, "username"); password = ValidationUtil.validateLength(password, "password", 8, 50); - email = ValidationUtil.validateLength(email, "email", 3, 50); + email = ValidationUtil.validateLength(email, "email", 1, 100); Long storageQuota = ValidationUtil.validateLong(storageQuotaStr, "storage_quota"); ValidationUtil.validateEmail(email, "email"); @@ -115,7 +129,7 @@ public class UserResource extends BaseResource { if ("AlreadyExistingUsername".equals(e.getMessage())) { throw new ServerException("AlreadyExistingUsername", "Login already used", e); } else { - throw new ServerException("UnknownError", "Unknown Server Error", e); + throw new ServerException("UnknownError", "Unknown server error", e); } } @@ -126,8 +140,17 @@ public class UserResource extends BaseResource { } /** - * Updates user informations. - * + * Updates the current user informations. + * + * @api {post} /user Update the current user + * @apiName PostUser + * @apiGroup User + * @apiParam {String{8..50}} password Password + * @apiParam {String{1..100}} email E-mail + * @apiSuccess {String} status Status OK + * @apiPermission user + * @apiVersion 1.0.0 + * * @param password Password * @param email E-Mail * @return Response @@ -142,7 +165,7 @@ public class UserResource extends BaseResource { // Validate the input data password = ValidationUtil.validateLength(password, "password", 8, 50, true); - email = ValidationUtil.validateLength(email, "email", null, 100, true); + email = ValidationUtil.validateLength(email, "email", 1, 100, true); // Update the user UserDao userDao = new UserDao(); @@ -165,8 +188,20 @@ public class UserResource extends BaseResource { } /** - * Updates user informations. - * + * Updates a user informations. + * + * @api {post} /user/:username Update a user + * @apiName PostUserUsername + * @apiGroup User + * @apiParam {String} username Username + * @apiParam {String{8..50}} password Password + * @apiParam {String{1..100}} email E-mail + * @apiParam {Number} storage_quota Storage quota (in bytes) + * @apiSuccess {String} status Status OK + * @apiError (client) UserNotFound User not found + * @apiPermission admin + * @apiVersion 1.0.0 + * * @param username Username * @param password Password * @param email E-Mail @@ -186,7 +221,7 @@ public class UserResource extends BaseResource { // Validate the input data password = ValidationUtil.validateLength(password, "password", 8, 50, true); - email = ValidationUtil.validateLength(email, "email", null, 100, true); + email = ValidationUtil.validateLength(email, "email", 1, 100, true); // Check if the user exists UserDao userDao = new UserDao(); @@ -218,8 +253,17 @@ public class UserResource extends BaseResource { } /** - * Checks if a username is available. Search only on active accounts. - * + * Checks if a username is available. + * Search only on active accounts. + * + * @api {get} /user/check_username Check username availability + * @apiName GetUserCheckUsername + * @apiGroup User + * @apiParam {String} username Username + * @apiSuccess {String} status Status OK or KO + * @apiPermission none + * @apiVersion 1.0.0 + * * @param username Username to check * @return Response */ @@ -244,7 +288,21 @@ public class UserResource extends BaseResource { /** * This resource is used to authenticate the user and create a user session. * The "session" is only used to identify the user, no other data is stored in the session. - * + * + * @api {post} /user/login Login a user + * @apiDescription This resource creates an authentication token and gives it back in a cookie. + * All authenticated resources will check this cookie to find the user currently logged in. + * @apiName PostUserLogin + * @apiGroup User + * @apiParam {String} username Username + * @apiParam {String} password Password + * @apiParam {String} code TOTP validation code + * @apiParam {Boolean} remember If true, create a long lasted token + * @apiSuccess {String} auth_token A cookie named auth_token containing the token ID + * @apiError (client) ValidationCodeRequired A TOTP validation code is required + * @apiPermission none + * @apiVersion 1.0.0 + * * @param username Username * @param password Password * @param longLasted Remember the user next time, create a long lasted session. @@ -309,7 +367,16 @@ public class UserResource extends BaseResource { /** * Logs out the user and deletes the active session. - * + * + * @api {post} /user/logout Logout a user + * @apiDescription This resource deletes the authentication token created by POST /user/login and removes the cookie. + * @apiName PostUserLogout + * @apiGroup User + * @apiSuccess {String} auth_token An expired cookie named auth_token containing no value + * @apiError (server) AuthenticationTokenError Error deleting the authentication token + * @apiPermission user + * @apiVersion 1.0.0 + * * @return Response */ @POST @@ -337,7 +404,7 @@ public class UserResource extends BaseResource { try { authenticationTokenDao.delete(authToken); } catch (Exception e) { - throw new ServerException("AuthenticationTokenError", "Error deleting authentication token: " + authToken, e); + throw new ServerException("AuthenticationTokenError", "Error deleting the authentication token: " + authToken, e); } // Deletes the client token in the HTTP response @@ -347,8 +414,17 @@ public class UserResource extends BaseResource { } /** - * Delete a user. - * + * Deletes the current user. + * + * @api {delete} /user Delete the current user + * @apiDescription All associated entities will be deleted as well. + * @apiName DeleteUser + * @apiGroup User + * @apiSuccess {String} status Status OK + * @apiError (client) ForbiddenError The admin user cannot be deleted + * @apiPermission user + * @apiVersion 1.0.0 + * * @return Response */ @DELETE @@ -396,7 +472,17 @@ public class UserResource extends BaseResource { /** * Deletes a user. - * + * + * @api {delete} /user/:username Delete a user + * @apiDescription All associated entities will be deleted as well. + * @apiName DeleteUserUsername + * @apiGroup User + * @apiSuccess {String} status Status OK + * @apiError (client) UserNotFound The user does not exist + * @apiError (client) ForbiddenError The admin user cannot be deleted + * @apiPermission admin + * @apiVersion 1.0.0 + * * @param username Username * @return Response */ @@ -412,7 +498,7 @@ public class UserResource extends BaseResource { UserDao userDao = new UserDao(); User user = userDao.getActiveByUsername(username); if (user == null) { - throw new ClientException("UserNotFound", "The user doesn't exist"); + throw new ClientException("UserNotFound", "The user does not exist"); } // Ensure that the admin user is not deleted @@ -455,7 +541,22 @@ public class UserResource extends BaseResource { /** * Returns the information about the connected user. - * + * + * @api {get} /user Get the current user + * @apiName GetUser + * @apiGroup User + * @apiSuccess {Boolean} anonymous True if no user is connected + * @apiSuccess {Boolean} is_default_password True if the admin has the default password + * @apiSuccess {String} username Username + * @apiSuccess {String} email E-mail + * @apiSuccess {Number} storage_quota Storage quota (in bytes) + * @apiSuccess {Number} storage_current Quota used (in bytes) + * @apiSuccess {Boolean} totp_enabled True if TOTP authentication is enabled + * @apiSuccess {String[]} base_functions Base functions + * @apiSuccess {String[]} groups Groups + * @apiPermission none + * @apiVersion 1.0.0 + * * @return Response */ @GET @@ -513,7 +614,20 @@ public class UserResource extends BaseResource { /** * Returns the information about a user. - * + * + * @api {get} /user/:username Get a user + * @apiName GetUserUsername + * @apiGroup User + * @apiParam {String} username Username + * @apiSuccess {String} username Username + * @apiSuccess {String} email E-mail + * @apiSuccess {Number} storage_quota Storage quota (in bytes) + * @apiSuccess {Number} storage_current Quota used (in bytes) + * @apiSuccess {String[]} groups Groups + * @apiError (client) UserNotFound The user does not exist + * @apiPermission user + * @apiVersion 1.0.0 + * * @param username Username * @return Response */ @@ -528,7 +642,7 @@ public class UserResource extends BaseResource { UserDao userDao = new UserDao(); User user = userDao.getActiveByUsername(username); if (user == null) { - throw new ClientException("UserNotFound", "The user doesn't exist"); + throw new ClientException("UserNotFound", "The user does not exist"); } // Groups @@ -552,7 +666,21 @@ public class UserResource extends BaseResource { /** * Returns all active users. - * + * + * @api {get} /user/list Get users + * @apiName GetUserList + * @apiGroup User + * @apiParam {Number} sort_column Column index to sort on + * @apiSuccess {String[]} users List of users + * @apiSuccess {String} users.id ID + * @apiSuccess {String} users.username Username + * @apiSuccess {String} users.email E-mail + * @apiSuccess {Number} users.storage_quota Storage quota (in bytes) + * @apiSuccess {Number} users.storage_current Quota used (in bytes) + * @apiSuccess {Number} users.create_date Create date (timestamp) + * @apiPermission user + * @apiVersion 1.0.0 + * * @param sortColumn Sort index * @param asc If true, ascending sorting, else descending * @param groupName Only return users from this group @@ -600,7 +728,20 @@ public class UserResource extends BaseResource { /** * Returns all active sessions. - * + * + * @api {get} /user/session Get active sessions + * @apiDescription This resource lists all active token which can be used to log in to the current user account. + * @apiName GetUserSession + * @apiGroup User + * @apiSuccess {String[]} sessions List of sessions + * @apiSuccess {Number} create_date Create date of this token + * @apiSuccess {String} ip IP used to log in + * @apiSuccess {String} user_agent User agent used to log in + * @apiSuccess {Number} last_connection_date Last connection date (timestamp) + * @apiSuccess {Boolean} current If true, this token is the current one + * @apiPermission user + * @apiVersion 1.0.0 + * * @return Response */ @GET @@ -635,7 +776,15 @@ public class UserResource extends BaseResource { /** * Deletes all active sessions except the one used for this request. - * + * + * @api {delete} /user/session Delete all sessions + * @apiDescription This resource deletes all active token linked to this account, except the one used to make this request. + * @apiName DeleteUserSession + * @apiGroup User + * @apiSuccess {String} status Status OK + * @apiPermission user + * @apiVersion 1.0.0 + * * @return Response */ @DELETE @@ -660,7 +809,16 @@ public class UserResource extends BaseResource { /** * Enable time-based one-time password. - * + * + * @api {post} /user/enable_totp Enable TOTP authentication + * @apiDescription This resource enables the Time-based One-time Password authentication. + * All following login will need a validation code generated from the given secret seed. + * @apiName PostUserEnableTotp + * @apiGroup User + * @apiSuccess {String} secret Secret TOTP seed to initiate the algorithm + * @apiPermission user + * @apiVersion 1.0.0 + * * @return Response */ @POST @@ -687,7 +845,15 @@ public class UserResource extends BaseResource { /** * Disable time-based one-time password. - * + * + * @api {post} /user/disable_totp Disable TOTP authentication + * @apiName PostUserDisableTotp + * @apiGroup User + * @apiParam {String{1..100}} password Password + * @apiSuccess {String} status Status OK + * @apiPermission user + * @apiVersion 1.0.0 + * * @param password Password * @return Response */ @@ -720,7 +886,7 @@ public class UserResource extends BaseResource { /** * Returns the authentication token value. - * + * * @return Token value */ private String getAuthToken() { diff --git a/docs-web/src/main/java/com/sismics/docs/rest/resource/VocabularyResource.java b/docs-web/src/main/java/com/sismics/docs/rest/resource/VocabularyResource.java index 06ba5ee8..0c53384f 100644 --- a/docs-web/src/main/java/com/sismics/docs/rest/resource/VocabularyResource.java +++ b/docs-web/src/main/java/com/sismics/docs/rest/resource/VocabularyResource.java @@ -20,6 +20,24 @@ import java.util.List; */ @Path("/vocabulary") public class VocabularyResource extends BaseResource { + /** + * Get a vocabulary. + * + * @api {get} /vocabulary/:name Get a vocabulary + * @apiName GetVocabularyName + * @apiGroup Vocabulary + * @apiParam {String} name Vocabulary name + * @apiSuccess {String[]} entries List of vocabulary entries + * @apiSuccess {String} entries.id ID + * @apiSuccess {String} entries.name Name + * @apiSuccess {String} entries.value Value + * @apiSuccess {Number} entries.order Order + * @apiPermission user + * @apiVersion 1.0.0 + * + * @param name Name + * @return Response + */ @GET @Path("{name: [a-z0-9\\-]+}") public Response get(@PathParam("name") String name) { @@ -46,8 +64,21 @@ public class VocabularyResource extends BaseResource { } /** - * Add a vocabulary. - * + * Add a vocabulary entry. + * + * @api {put} /vocabulary Add a vocabulary entry + * @apiName PutVocabulary + * @apiGroup Vocabulary + * @apiParam {String{1..50}} name Vocabulary name + * @apiParam {String{1..500}} value Entry value + * @apiParam {Number} order Entry order + * @apiSuccess {String} id ID + * @apiSuccess {String} name Name + * @apiSuccess {String} value Value + * @apiSuccess {Number} order Order + * @apiPermission admin + * @apiVersion 1.0.0 + * * @param name Name * @param value Value * @param orderStr Order @@ -86,7 +117,21 @@ public class VocabularyResource extends BaseResource { } /** - * Update a vocabulary. + * Update a vocabulary entry. + * + * @api {post} /vocabulary/:id Update a vocabulary entry + * @apiName PostVocabularyId + * @apiGroup Vocabulary + * @apiParam {String} id Entry ID + * @apiParam {String{1..50}} name Vocabulary name + * @apiParam {String{1..500}} value Entry value + * @apiParam {Number} order Entry order + * @apiSuccess {String} id ID + * @apiSuccess {String} name Name + * @apiSuccess {String} value Value + * @apiSuccess {Number} order Order + * @apiPermission admin + * @apiVersion 1.0.0 * * @param id ID * @param name Name @@ -145,8 +190,16 @@ public class VocabularyResource extends BaseResource { } /** - * Delete a vocabulary. - * + * Delete a vocabulary entry. + * + * @api {delete} /vocabulary/:id Delete vocabulary entry + * @apiName DeleteVocabularyId + * @apiGroup Vocabulary + * @apiParam {String} id Entry ID + * @apiSuccess {String} status Status OK + * @apiPermission admin + * @apiVersion 1.0.0 + * * @param id ID * @return Response */ diff --git a/docs-web/src/main/webapp/Gruntfile.js b/docs-web/src/main/webapp/Gruntfile.js index 5dba6d2d..ec2c6404 100644 --- a/docs-web/src/main/webapp/Gruntfile.js +++ b/docs-web/src/main/webapp/Gruntfile.js @@ -4,9 +4,8 @@ module.exports = function(grunt) { grunt.initConfig({ pkg: grunt.file.readJSON('package.json'), clean: { - dist: { - src: ['dist'] - } + init: ['dist'], + after: ['dist/style.css', 'dist/docs.js', 'dist/share.js', 'dist/less.css', 'dist/app'] }, ngmin: { dist: { @@ -78,12 +77,6 @@ module.exports = function(grunt) { dest: 'dist/share.html' } }, - remove: { - dist: { - fileList: ['dist/style.css', 'dist/docs.js', 'dist/share.js', 'dist/less.css'], - dirList: ['dist/app'] - } - }, cleanempty: { options: { files: false, @@ -100,6 +93,12 @@ module.exports = function(grunt) { to: grunt.option('apiurl') || '../api' }] } + }, + apidoc: { + generate: { + src: '../java/', + dest: 'dist/apidoc/' + } } }); @@ -111,12 +110,12 @@ module.exports = function(grunt) { grunt.loadNpmTasks('grunt-htmlrefs'); grunt.loadNpmTasks('grunt-css'); grunt.loadNpmTasks('grunt-contrib-less'); - grunt.loadNpmTasks('grunt-remove'); grunt.loadNpmTasks('grunt-ngmin'); grunt.loadNpmTasks('grunt-text-replace'); + grunt.loadNpmTasks('grunt-apidoc'); // Default tasks. - grunt.registerTask('default', ['clean', 'ngmin', 'concat:docs', 'concat:share', 'less', 'concat:css', 'cssmin', - 'uglify:docs', 'uglify:share', 'copy', 'remove', 'cleanempty', 'htmlrefs:index', 'htmlrefs:share', 'replace']); + grunt.registerTask('default', ['clean:init', 'ngmin', 'concat:docs', 'concat:share', 'less', 'concat:css', 'cssmin', + 'uglify:docs', 'uglify:share', 'copy', 'clean:after', 'cleanempty', 'htmlrefs:index', 'htmlrefs:share', 'replace', 'apidoc']); }; \ No newline at end of file diff --git a/docs-web/src/main/webapp/package.json b/docs-web/src/main/webapp/package.json index 29eefd62..7bf35d4f 100644 --- a/docs-web/src/main/webapp/package.json +++ b/docs-web/src/main/webapp/package.json @@ -2,25 +2,34 @@ "name": "sismics-docs", "description": "Lightweight document management system", "readme": "See http://github.com/simics/docs for more informations.", - "version": "0.0.1", + "version": "1.5.0", "repository": { "type": "git", "url": "git://github.com/sismics/docs.git" }, + "apidoc": { + "name": "Sismics Docs API", + "title": "Sismics Docs API", + "url": "/api", + "template": { + "withCompare": false, + "withGenerator": false + } + }, "devDependencies": { - "grunt": "~0.4.2", - "grunt-contrib-uglify": "~0.3.2", - "grunt-contrib-concat": "~0.3.0", - "grunt-contrib-copy": "~0.5.0", - "grunt-contrib-clean": "~0.5.0", - "grunt-cleanempty": "~0.2.0", - "grunt-htmlrefs": "~0.5.0", - "grunt-css": "~0.5.4", - "grunt-contrib-less": "~0.9.0", - "grunt-remove": "~0.1.0", + "grunt": "^1.0.1", + "grunt-apidoc": "^0.11.0", + "grunt-cleanempty": "^1.0.4", + "grunt-contrib-clean": "^1.0.0", + "grunt-contrib-concat": "^1.0.1", + "grunt-contrib-copy": "^1.0.0", + "grunt-contrib-less": "^1.3.0", + "grunt-contrib-uglify": "^1.0.1", + "grunt-css": "^0.5.4", + "grunt-htmlrefs": "^0.5.0", "grunt-ngmin": "0.0.3", - "grunt-text-replace": "~0.3.11", - "protractor": "~3.2.2", - "selenium": "~2.20.0" + "grunt-text-replace": "^0.4.0", + "protractor": "^3.3.0", + "selenium": "^2.20.0" } } diff --git a/docs-web/src/main/webapp/src/partial/docs/document.default.html b/docs-web/src/main/webapp/src/partial/docs/document.default.html index 0d814030..c15b146b 100644 --- a/docs-web/src/main/webapp/src/partial/docs/document.default.html +++ b/docs-web/src/main/webapp/src/partial/docs/document.default.html @@ -51,6 +51,8 @@
diff --git a/docs-web/src/main/webapp/src/partial/docs/settings.user.edit.html b/docs-web/src/main/webapp/src/partial/docs/settings.user.edit.html index 6cd7fe70..d9033895 100644 --- a/docs-web/src/main/webapp/src/partial/docs/settings.user.edit.html +++ b/docs-web/src/main/webapp/src/partial/docs/settings.user.edit.html @@ -27,7 +27,7 @@
+ ng-minlength="1" ng-maxlength="100" placeholder="E-mail" ng-model="user.email"/>