From 00f97aabb4bf1c113d001b868e9ae5234b89ec82 Mon Sep 17 00:00:00 2001 From: Nicola Murino Date: Wed, 28 Apr 2021 19:16:15 +0200 Subject: [PATCH] OpenAPI: document that quota-update support partial updates If the update mode is "add" and you pass only used_quota_size or only used_quota_files the missing field will remain unchanged --- examples/bulkupdate/bulkuserupdate | 6 +++--- examples/quotascan/scanuserquota | 9 +++++---- httpd/httpd_test.go | 32 ++++++++++++++++++++++++++++++ httpd/schema/openapi.yaml | 3 ++- 4 files changed, 42 insertions(+), 8 deletions(-) diff --git a/examples/bulkupdate/bulkuserupdate b/examples/bulkupdate/bulkuserupdate index 5e68ece2..656ad57e 100755 --- a/examples/bulkupdate/bulkuserupdate +++ b/examples/bulkupdate/bulkuserupdate @@ -24,7 +24,7 @@ fields_to_update = {"status":0, "quota_files": 1000, "additional_info":"updated # get a JWT token auth = requests.auth.HTTPBasicAuth(admin_user, admin_password) -r = requests.get(urlparse.urljoin(base_url, "api/v2/token"), auth=auth, verify=verify_tls_cert) +r = requests.get(urlparse.urljoin(base_url, "api/v2/token"), auth=auth, verify=verify_tls_cert, timeout=10) if r.status_code != 200: print("error getting access token: {}".format(r.text)) sys.exit(1) @@ -33,14 +33,14 @@ auth_header = {"Authorization": "Bearer " + access_token} for username in users_to_update: r = requests.get(urlparse.urljoin(base_url, posixpath.join("api/v2/users", username)), - headers=auth_header, verify=verify_tls_cert) + headers=auth_header, verify=verify_tls_cert, timeout=10) if r.status_code != 200: print("error getting user {}: {}".format(username, r.text)) continue user = r.json() user.update(fields_to_update) r = requests.put(urlparse.urljoin(base_url, posixpath.join("api/v2/users", username)), - headers=auth_header, verify=verify_tls_cert, json=user) + headers=auth_header, verify=verify_tls_cert, json=user, timeout=10) if r.status_code == 200: print("user {} updated".format(username)) else: diff --git a/examples/quotascan/scanuserquota b/examples/quotascan/scanuserquota index db5b62b9..9312d50b 100755 --- a/examples/quotascan/scanuserquota +++ b/examples/quotascan/scanuserquota @@ -50,7 +50,7 @@ class UpdateQuota: return auth = requests.auth.HTTPBasicAuth(admin_user, admin_password) - r = requests.get(urlparse.urljoin(base_url, "api/v2/token"), auth=auth, verify=verify_tls_cert) + r = requests.get(urlparse.urljoin(base_url, "api/v2/token"), auth=auth, verify=verify_tls_cert, timeout=10) if r.status_code != 200: self.printLog("error getting access token: {}".format(r.text)) sys.exit(1) @@ -65,7 +65,8 @@ class UpdateQuota: def waitForQuotaUpdate(self, username): while True: auth_header = self.getAuthHeader() - r = requests.get(urlparse.urljoin(base_url, "api/v2/quota-scans"), headers=auth_header, verify=verify_tls_cert) + r = requests.get(urlparse.urljoin(base_url, "api/v2/quota-scans"), headers=auth_header, verify=verify_tls_cert, + timeout=10) if r.status_code != 200: self.printLog("error getting quota scans while waiting for {}: {}".format(username, r.text)) sys.exit(1) @@ -85,7 +86,7 @@ class UpdateQuota: self.printLog("starting quota update for user {}".format(username)) auth_header = self.getAuthHeader() r = requests.post(urlparse.urljoin(base_url, "api/v2/quota-scans"), headers=auth_header, - json={"username":username}, verify=verify_tls_cert) + json={"username":username}, verify=verify_tls_cert, timeout=10) if r.status_code != 202: self.printLog("error starting quota scan for user {}: {}".format(username, r.text)) sys.exit(1) @@ -97,7 +98,7 @@ class UpdateQuota: auth_header = self.getAuthHeader() payload = {"limit":self.limit, "offset":self.offset} r = requests.get(urlparse.urljoin(base_url, "api/v2/users"), headers=auth_header, params=payload, - verify=verify_tls_cert) + verify=verify_tls_cert, timeout=10) if r.status_code != 200: self.printLog("error getting users: {}".format(r.text)) sys.exit(1) diff --git a/httpd/httpd_test.go b/httpd/httpd_test.go index da68b631..e706831b 100644 --- a/httpd/httpd_test.go +++ b/httpd/httpd_test.go @@ -3596,6 +3596,7 @@ func TestUpdateUserQuotaUsageMock(t *testing.T) { usedQuotaSize := int64(65535) u.UsedQuotaFiles = usedQuotaFiles u.UsedQuotaSize = usedQuotaSize + u.QuotaFiles = 100 userAsJSON := getUserAsJSON(t, u) req, _ := http.NewRequest(http.MethodPost, userPath, bytes.NewBuffer(userAsJSON)) setBearerForReq(req, token) @@ -3615,6 +3616,37 @@ func TestUpdateUserQuotaUsageMock(t *testing.T) { assert.NoError(t, err) assert.Equal(t, usedQuotaFiles, user.UsedQuotaFiles) assert.Equal(t, usedQuotaSize, user.UsedQuotaSize) + // now update only quota size + u.UsedQuotaFiles = 0 + userAsJSON = getUserAsJSON(t, u) + req, _ = http.NewRequest(http.MethodPut, updateUsedQuotaPath+"?mode=add", bytes.NewBuffer(userAsJSON)) + setBearerForReq(req, token) + rr = executeRequest(req) + checkResponseCode(t, http.StatusOK, rr) + req, _ = http.NewRequest(http.MethodGet, path.Join(userPath, user.Username), nil) + setBearerForReq(req, token) + rr = executeRequest(req) + checkResponseCode(t, http.StatusOK, rr) + err = render.DecodeJSON(rr.Body, &user) + assert.NoError(t, err) + assert.Equal(t, usedQuotaFiles, user.UsedQuotaFiles) + assert.Equal(t, usedQuotaSize*2, user.UsedQuotaSize) + // only quota files + u.UsedQuotaFiles = usedQuotaFiles + u.UsedQuotaSize = 0 + userAsJSON = getUserAsJSON(t, u) + req, _ = http.NewRequest(http.MethodPut, updateUsedQuotaPath+"?mode=add", bytes.NewBuffer(userAsJSON)) + setBearerForReq(req, token) + rr = executeRequest(req) + checkResponseCode(t, http.StatusOK, rr) + req, _ = http.NewRequest(http.MethodGet, path.Join(userPath, user.Username), nil) + setBearerForReq(req, token) + rr = executeRequest(req) + checkResponseCode(t, http.StatusOK, rr) + err = render.DecodeJSON(rr.Body, &user) + assert.NoError(t, err) + assert.Equal(t, usedQuotaFiles*2, user.UsedQuotaFiles) + assert.Equal(t, usedQuotaSize*2, user.UsedQuotaSize) req, _ = http.NewRequest(http.MethodPut, updateUsedQuotaPath, bytes.NewBuffer([]byte("string"))) setBearerForReq(req, token) rr = executeRequest(req) diff --git a/httpd/schema/openapi.yaml b/httpd/schema/openapi.yaml index d416b995..17cab74b 100644 --- a/httpd/schema/openapi.yaml +++ b/httpd/schema/openapi.yaml @@ -14,6 +14,7 @@ info: description: SFTPGo REST API version: 2.0.5 contact: + name: API support url: 'https://github.com/drakkan/sftpgo' license: name: AGPLv3 @@ -375,7 +376,7 @@ paths: example: reset requestBody: required: true - description: 'The only user mandatory fields are username, used_quota_size and used_quota_files. Please note that if the quota fields are missing they will default to 0' + description: 'The only user mandatory fields are username, used_quota_size and used_quota_files. Please note that if the quota fields are missing they will default to 0, this means that if mode is "add" the current value will remain unchanged, if mode is "reset" the missing field is set to 0' content: application/json: schema: