diff --git a/.gitignore b/.gitignore index 1e9697d56a..85200331f7 100644 --- a/.gitignore +++ b/.gitignore @@ -98,6 +98,8 @@ nbproject/ test.cpp.txt +.sass-cache + js/apps/* !js/apps/system !js/apps/system/* diff --git a/CHANGELOG b/CHANGELOG index d833fb9295..f1fcfce67b 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,6 +1,21 @@ v1.5.0 (XXXX-XX-XX) ------------------- +* slightly improved users management API in `/_api/user`: + + Previously, when creating a new user via HTTP POST, the username needed to be + passed in an attribute `username`. When users were returned via this API, + the usernames were returned in an attribute named `user`. This was slightly + confusing and was changed in 1.5 as follows: + + - when adding a user via HTTP POST, the username can be specified in an attribute + `user`. If this attribute is not used, the API will look into the attribute `username` + as before and use that value. + - when users are returned via HTTP GET, the usernames are still returned in an + attribute `user`. + + This change should be fully downwards-compatible with the previous version of the API. + * added AQL SLICE function to extract slices from lists * removed check-server binary diff --git a/UnitTests/HttpInterface/api-users-spec.rb b/UnitTests/HttpInterface/api-users-spec.rb index 72680c4a2c..aac8c8b6fb 100644 --- a/UnitTests/HttpInterface/api-users-spec.rb +++ b/UnitTests/HttpInterface/api-users-spec.rb @@ -51,7 +51,7 @@ describe ArangoDB do doc.parsed_response['errorNum'].should eq(1700) end - it "add user, empty username" do + it "add user, empty username, old API" do body = "{ \"username\" : \"\", \"passwd\" : \"fox\" }" doc = ArangoDB.log_post("#{prefix}-add", api, :body => body) @@ -61,8 +61,19 @@ describe ArangoDB do doc.parsed_response['code'].should eq(400) doc.parsed_response['errorNum'].should eq(1700) end + + it "add user, empty username" do + body = "{ \"user\" : \"\", \"passwd\" : \"fox\" }" + doc = ArangoDB.log_post("#{prefix}-add", api, :body => body) + + doc.code.should eq(400) + doc.headers['content-type'].should eq("application/json; charset=utf-8") + doc.parsed_response['error'].should eq(true) + doc.parsed_response['code'].should eq(400) + doc.parsed_response['errorNum'].should eq(1700) + end - it "add user, no passwd" do + it "add user, no passwd, old API" do body = "{ \"username\" : \"users-1\" }" doc = ArangoDB.log_post("#{prefix}-add", api, :body => body) @@ -78,8 +89,25 @@ describe ArangoDB do doc.parsed_response['user'].should eq("users-1") doc.parsed_response['active'].should eq(true) end + + it "add user, no passwd" do + body = "{ \"user\" : \"users-1\" }" + doc = ArangoDB.log_post("#{prefix}-add", api, :body => body) + + doc.code.should eq(201) + doc.headers['content-type'].should eq("application/json; charset=utf-8") + doc.parsed_response['error'].should eq(false) + doc.parsed_response['code'].should eq(201) + + doc = ArangoDB.get(api + "/users-1") + doc.code.should eq(200) + doc.parsed_response['error'].should eq(false) + doc.parsed_response['code'].should eq(200) + doc.parsed_response['user'].should eq("users-1") + doc.parsed_response['active'].should eq(true) + end - it "add user, username and passwd" do + it "add user, username and passwd, old API" do body = "{ \"username\" : \"users-1\", \"passwd\" : \"fox\" }" doc = ArangoDB.log_post("#{prefix}-add", api, :body => body) @@ -95,8 +123,25 @@ describe ArangoDB do doc.parsed_response['user'].should eq("users-1") doc.parsed_response['active'].should eq(true) end - - it "add user, username passwd, active, extra" do + + it "add user, username and passwd" do + body = "{ \"user\" : \"users-1\", \"passwd\" : \"fox\" }" + doc = ArangoDB.log_post("#{prefix}-add", api, :body => body) + + doc.code.should eq(201) + doc.headers['content-type'].should eq("application/json; charset=utf-8") + doc.parsed_response['error'].should eq(false) + doc.parsed_response['code'].should eq(201) + + doc = ArangoDB.get(api + "/users-1") + doc.code.should eq(200) + doc.parsed_response['error'].should eq(false) + doc.parsed_response['code'].should eq(200) + doc.parsed_response['user'].should eq("users-1") + doc.parsed_response['active'].should eq(true) + end + + it "add user, username passwd, active, extra, old API" do body = "{ \"username\" : \"users-2\", \"passwd\" : \"fox\", \"active\" : false, \"extra\" : { \"foo\" : true } }" doc = ArangoDB.log_post("#{prefix}-add", api, :body => body) @@ -114,7 +159,25 @@ describe ArangoDB do doc.parsed_response['extra'].should eq({ "foo" => true }) end - it "add user, duplicate username" do + it "add user, username passwd, active, extra" do + body = "{ \"user\" : \"users-2\", \"passwd\" : \"fox\", \"active\" : false, \"extra\" : { \"foo\" : true } }" + doc = ArangoDB.log_post("#{prefix}-add", api, :body => body) + + doc.code.should eq(201) + doc.headers['content-type'].should eq("application/json; charset=utf-8") + doc.parsed_response['error'].should eq(false) + doc.parsed_response['code'].should eq(201) + + doc = ArangoDB.get(api + "/users-2") + doc.code.should eq(200) + doc.parsed_response['error'].should eq(false) + doc.parsed_response['code'].should eq(200) + doc.parsed_response['user'].should eq("users-2") + doc.parsed_response['active'].should eq(false) + doc.parsed_response['extra'].should eq({ "foo" => true }) + end + + it "add user, duplicate username, old API" do body = "{ \"username\" : \"users-1\", \"passwd\" : \"fox\" }" doc = ArangoDB.log_post("#{prefix}-add", api, :body => body) @@ -131,6 +194,24 @@ describe ArangoDB do doc.parsed_response['code'].should eq(400) doc.parsed_response['errorNum'].should eq(1702) end + + it "add user, duplicate username" do + body = "{ \"user\" : \"users-1\", \"passwd\" : \"fox\" }" + doc = ArangoDB.log_post("#{prefix}-add", api, :body => body) + + doc.code.should eq(201) + doc.headers['content-type'].should eq("application/json; charset=utf-8") + doc.parsed_response['error'].should eq(false) + doc.parsed_response['code'].should eq(201) + + doc = ArangoDB.log_post("#{prefix}-add", api, :body => body) + + doc.code.should eq(400) + doc.headers['content-type'].should eq("application/json; charset=utf-8") + doc.parsed_response['error'].should eq(true) + doc.parsed_response['code'].should eq(400) + doc.parsed_response['errorNum'].should eq(1702) + end end ################################################################################ @@ -153,7 +234,7 @@ describe ArangoDB do end it "replace already removed user" do - body = "{ \"username\" : \"users-1\", \"passwd\" : \"fox\", \"active\" : true, \"extra\" : { \"foo\" : true } }" + body = "{ \"user\" : \"users-1\", \"passwd\" : \"fox\", \"active\" : true, \"extra\" : { \"foo\" : true } }" doc = ArangoDB.log_post("#{prefix}-replace-removed", api, :body => body) doc.code.should eq(201) @@ -172,7 +253,7 @@ describe ArangoDB do end it "replace, empty body" do - body = "{ \"username\" : \"users-1\", \"passwd\" : \"fox\", \"active\" : true, \"extra\" : { \"foo\" : true } }" + body = "{ \"user\" : \"users-1\", \"passwd\" : \"fox\", \"active\" : true, \"extra\" : { \"foo\" : true } }" doc = ArangoDB.log_post("#{prefix}-replace-empty", api, :body => body) # replace @@ -191,7 +272,7 @@ describe ArangoDB do end it "replace existing user, no passwd" do - body = "{ \"username\" : \"users-1\", \"passwd\" : \"fox\", \"active\" : true, \"extra\" : { \"foo\" : true } }" + body = "{ \"user\" : \"users-1\", \"passwd\" : \"fox\", \"active\" : true, \"extra\" : { \"foo\" : true } }" doc = ArangoDB.log_post("#{prefix}-replace-nopass", api, :body => body) # replace @@ -211,7 +292,7 @@ describe ArangoDB do end it "replace existing user" do - body = "{ \"username\" : \"users-1\", \"passwd\" : \"fox\", \"active\" : true, \"extra\" : { \"foo\" : true } }" + body = "{ \"user\" : \"users-1\", \"passwd\" : \"fox\", \"active\" : true, \"extra\" : { \"foo\" : true } }" doc = ArangoDB.log_post("#{prefix}-replace-exists", api, :body => body) # replace @@ -252,7 +333,7 @@ describe ArangoDB do end it "update already removed user" do - body = "{ \"username\" : \"users-1\", \"passwd\" : \"fox\", \"active\" : true, \"extra\" : { \"foo\" : true } }" + body = "{ \"user\" : \"users-1\", \"passwd\" : \"fox\", \"active\" : true, \"extra\" : { \"foo\" : true } }" doc = ArangoDB.log_post("#{prefix}-update", api, :body => body) doc.code.should eq(201) @@ -271,7 +352,7 @@ describe ArangoDB do end it "update, empty body" do - body = "{ \"username\" : \"users-1\", \"passwd\" : \"fox\", \"active\" : true, \"extra\" : { \"foo\" : true } }" + body = "{ \"user\" : \"users-1\", \"passwd\" : \"fox\", \"active\" : true, \"extra\" : { \"foo\" : true } }" doc = ArangoDB.log_post("#{prefix}-update", api, :body => body) # update @@ -291,7 +372,7 @@ describe ArangoDB do end it "update existing user, no passwd" do - body = "{ \"username\" : \"users-1\", \"passwd\" : \"fox\", \"active\" : true, \"extra\" : { \"foo\" : true } }" + body = "{ \"user\" : \"users-1\", \"passwd\" : \"fox\", \"active\" : true, \"extra\" : { \"foo\" : true } }" doc = ArangoDB.log_post("#{prefix}-update", api, :body => body) # update @@ -311,7 +392,7 @@ describe ArangoDB do end it "update existing user" do - body = "{ \"username\" : \"users-1\", \"passwd\" : \"fox\", \"active\" : true, \"extra\" : { \"foo\" : true } }" + body = "{ \"user\" : \"users-1\", \"passwd\" : \"fox\", \"active\" : true, \"extra\" : { \"foo\" : true } }" doc = ArangoDB.log_post("#{prefix}-update", api, :body => body) # update @@ -352,7 +433,7 @@ describe ArangoDB do end it "remove already removed user" do - body = "{ \"username\" : \"users-1\", \"passwd\" : \"fox\", \"active\" : true, \"extra\" : { \"foo\" : true } }" + body = "{ \"user\" : \"users-1\", \"passwd\" : \"fox\", \"active\" : true, \"extra\" : { \"foo\" : true } }" doc = ArangoDB.log_post("#{prefix}-delete", api, :body => body) doc.code.should eq(201) @@ -371,7 +452,7 @@ describe ArangoDB do end it "remove existing user" do - body = "{ \"username\" : \"users-1\", \"passwd\" : \"fox\", \"active\" : true, \"extra\" : { \"foo\" : true } }" + body = "{ \"user\" : \"users-1\", \"passwd\" : \"fox\", \"active\" : true, \"extra\" : { \"foo\" : true } }" doc = ArangoDB.log_post("#{prefix}-delete", api, :body => body) # remove @@ -409,7 +490,7 @@ describe ArangoDB do end it "fetches users, requires some created users" do - body = "{ \"username\" : \"users-1\", \"passwd\" : \"fox\", \"active\" : false, \"extra\" : { \"meow\" : false } }" + body = "{ \"user\" : \"users-1\", \"passwd\" : \"fox\", \"active\" : false, \"extra\" : { \"meow\" : false } }" ArangoDB.log_post("#{prefix}-fetch-existing", api, :body => body) doc = ArangoDB.log_get("#{prefix}-fetch-existing", api) @@ -444,7 +525,7 @@ describe ArangoDB do end it "fetch user" do - body = "{ \"username\" : \"users-2\", \"passwd\" : \"fox\", \"active\" : false, \"extra\" : { \"foo\" : true } }" + body = "{ \"user\" : \"users-2\", \"passwd\" : \"fox\", \"active\" : false, \"extra\" : { \"foo\" : true } }" doc = ArangoDB.log_post("#{prefix}-fetch", api, :body => body) doc.code.should eq(201) diff --git a/js/actions/api-user.js b/js/actions/api-user.js index 5bca0536ef..2b181eb212 100644 --- a/js/actions/api-user.js +++ b/js/actions/api-user.js @@ -44,11 +44,11 @@ var users = require("org/arangodb/users"); //////////////////////////////////////////////////////////////////////////////// /// @brief fetch a user /// -/// @RESTHEADER{GET /_api/user/{username},fetches a user} +/// @RESTHEADER{GET /_api/user/{user},fetches a user} /// /// @RESTURLPARAMETERS /// -/// @RESTURLPARAM{username,string,required} +/// @RESTURLPARAM{user,string,required} /// The name of the user. /// /// @RESTDESCRIPTION @@ -58,7 +58,7 @@ var users = require("org/arangodb/users"); /// The call will return a JSON document with at least the following attributes /// on success: /// -/// - `username`: The name of the user as a string. +/// - `user`: The name of the user as a string. /// /// - `active`: an optional flag that specifies whether the user is active. /// @@ -71,7 +71,7 @@ var users = require("org/arangodb/users"); /// The user was found. /// /// @RESTRETURNCODE{404} -/// The user with `username` does not exist. +/// The user with `user` does not exist. /// //////////////////////////////////////////////////////////////////////////////// @@ -86,9 +86,10 @@ function get_api_user (req, res) { return; } - var username = decodeURIComponent(req.suffix[0]); + var user = decodeURIComponent(req.suffix[0]); + try { - var result = users.document(username); + var result = users.document(user); actions.resultOk(req, res, actions.HTTP_OK, result); } catch (err) { @@ -113,7 +114,7 @@ function get_api_user (req, res) { /// The following data need to be passed in a JSON representation in the body of /// the POST request: /// -/// - `username`: The name of the user as a string. This is mandatory. +/// - `user`: The name of the user as a string. This is mandatory. /// /// - `passwd`: The user password as a string. If no password is specified, /// the empty string will be used. @@ -166,7 +167,13 @@ function post_api_user (req, res) { return; } - users.save(json.username, json.passwd, json.active, json.extra); + var user = json.user; + if (user === undefined && json.hasOwnProperty("username")) { + // deprecated usage + user = json.username; + } + + users.save(user, json.passwd, json.active, json.extra); users.reload(); actions.resultOk(req, res, actions.HTTP_CREATED, { }); @@ -175,11 +182,11 @@ function post_api_user (req, res) { //////////////////////////////////////////////////////////////////////////////// /// @brief replace an existing user /// -/// @RESTHEADER{PUT /_api/user/{username},replaces user} +/// @RESTHEADER{PUT /_api/user/{user},replaces user} /// /// @RESTURLPARAMETERS /// -/// @RESTURLPARAM{username,string,required} +/// @RESTURLPARAM{user,string,required} /// The name of the user. /// /// @RESTBODYPARAM{body,json,required} @@ -187,7 +194,7 @@ function post_api_user (req, res) { /// @RESTDESCRIPTION /// /// Replaces the data of an existing user. The name of an existing user must -/// be specified in `username`. +/// be specified in `user`. /// /// The following data can to be passed in a JSON representation in the body of /// the POST request: @@ -245,7 +252,7 @@ function put_api_user (req, res) { return; } - var username = decodeURIComponent(req.suffix[0]); + var user = decodeURIComponent(req.suffix[0]); var json = actions.getJsonBody(req, res, actions.HTTP_BAD); @@ -254,7 +261,7 @@ function put_api_user (req, res) { } try { - users.replace(username, json.passwd, json.active, json.extra); + users.replace(user, json.passwd, json.active, json.extra); users.reload(); actions.resultOk(req, res, actions.HTTP_OK, { }); @@ -272,11 +279,11 @@ function put_api_user (req, res) { //////////////////////////////////////////////////////////////////////////////// /// @brief partially update an existing user /// -/// @RESTHEADER{PATCH /_api/user/{username},updates user} +/// @RESTHEADER{PATCH /_api/user/{user},updates user} /// /// @RESTURLPARAMETERS /// -/// @RESTURLPARAM{username,string,required} +/// @RESTURLPARAM{user,string,required} /// The name of the user. /// /// @RESTBODYPARAM{body,json,required} @@ -284,7 +291,7 @@ function put_api_user (req, res) { /// @RESTDESCRIPTION /// /// Partially updates the data of an existing user. The name of an existing user -/// must be specified in `username`. +/// must be specified in `user`. /// /// The following data can be passed in a JSON representation in the body of /// the POST request: @@ -344,8 +351,7 @@ function patch_api_user (req, res) { return; } - var username = decodeURIComponent(req.suffix[0]); - + var user = decodeURIComponent(req.suffix[0]); var json = actions.getJsonBody(req, res, actions.HTTP_BAD); if (json === undefined) { @@ -353,7 +359,7 @@ function patch_api_user (req, res) { } try { - users.update(username, json.passwd, json.active, json.extra); + users.update(user, json.passwd, json.active, json.extra); users.reload(); actions.resultOk(req, res, actions.HTTP_OK, { }); } @@ -370,16 +376,16 @@ function patch_api_user (req, res) { //////////////////////////////////////////////////////////////////////////////// /// @brief remove an existing user /// -/// @RESTHEADER{DELETE /_api/user/{username},removes a user} +/// @RESTHEADER{DELETE /_api/user/{user},removes a user} /// /// @RESTURLPARAMETERS /// -/// @RESTURLPARAM{username,string,required} +/// @RESTURLPARAM{user,string,required} /// The name of the user. /// /// @RESTDESCRIPTION /// -/// Removes an existing user, identified by `username`. +/// Removes an existing user, identified by `user`. /// /// If the user can be removed, the server will respond with `HTTP 202`. /// @@ -420,9 +426,9 @@ function delete_api_user (req, res) { return; } - var username = decodeURIComponent(req.suffix[0]); + var user = decodeURIComponent(req.suffix[0]); try { - users.remove(username); + users.remove(user); users.reload(); actions.resultOk(req, res, actions.HTTP_ACCEPTED, { }); } diff --git a/js/apps/system/aardvark/frontend/css/bootstrap.css b/js/apps/system/aardvark/frontend/css/bootstrap.css index 6fc54a33b5..186878c289 100644 --- a/js/apps/system/aardvark/frontend/css/bootstrap.css +++ b/js/apps/system/aardvark/frontend/css/bootstrap.css @@ -2853,17 +2853,6 @@ table th[class*="span"], outline: 0; } -.caret { - display: inline-block; - width: 0; - height: 0; - vertical-align: top; - border-top: 4px solid #000000; - border-right: 4px solid transparent; - border-left: 4px solid transparent; - content: ""; -} - .dropdown .caret { margin-top: 8px; margin-left: 2px; diff --git a/js/apps/system/aardvark/frontend/css/documentsView.css b/js/apps/system/aardvark/frontend/css/documentsView.css index 07c651e579..54bc0867da 100644 --- a/js/apps/system/aardvark/frontend/css/documentsView.css +++ b/js/apps/system/aardvark/frontend/css/documentsView.css @@ -171,8 +171,14 @@ color:#FFFFFF; } -.pagination-mini ul > li.disabled:last-child > a, .pagination-small ul > li.disabled:last-child > a, .pagination-mini ul > li.disabled:last-child > span, .pagination-small ul > li.disabled:last-child > span, -.pagination-mini ul > li.disabled:first-child > a, .pagination-small ul > li.disabled:first-child > a, .pagination-mini ul > li.disabled:first-child > span, .pagination-small ul > li.disabled:first-child > span { +.pagination-mini ul > li.disabled:last-child > a, +.pagination-small ul > li.disabled:last-child > a, +.pagination-mini ul > li.disabled:last-child > span, +.pagination-small ul > li.disabled:last-child > span, +.pagination-mini ul > li.disabled:first-child > a, +.pagination-small ul > li.disabled:first-child > a, +.pagination-mini ul > li.disabled:first-child > span, +.pagination-small ul > li.disabled:first-child > span { pointer-events: none; cursor: default; background-color: ##777; @@ -193,7 +199,7 @@ border-radius:0; } -.badge-success, .badge-success, .badge-important, .badge-inverse { +.badge-success, .badge-important, .badge-inverse { background: none; padding-left: 0px; padding-right: 0px; diff --git a/js/apps/system/aardvark/frontend/css/graphlayout.css b/js/apps/system/aardvark/frontend/css/graphlayout.css index 71f1ce9a29..7c638b7db9 100644 --- a/js/apps/system/aardvark/frontend/css/graphlayout.css +++ b/js/apps/system/aardvark/frontend/css/graphlayout.css @@ -378,9 +378,3 @@ div.queryline div.searchByAttribute > ul.dropdown-menu { display: none; /* background-color: #8F8D8C; */ } - -/* Temporary */ -#transparentPlaceholder { - margin-right: -100%; -} - diff --git a/js/apps/system/aardvark/frontend/html/body.html.part b/js/apps/system/aardvark/frontend/html/body.html.part index 4b36a21af0..82ad661fc9 100644 --- a/js/apps/system/aardvark/frontend/html/body.html.part +++ b/js/apps/system/aardvark/frontend/html/body.html.part @@ -1,5 +1,5 @@ + - HHALO