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
This commit is contained in:
Nicola Murino 2021-04-28 19:16:15 +02:00
parent 32db0787bb
commit 00f97aabb4
No known key found for this signature in database
GPG key ID: 2F1FB59433D5A8CB
4 changed files with 42 additions and 8 deletions

View file

@ -24,7 +24,7 @@ fields_to_update = {"status":0, "quota_files": 1000, "additional_info":"updated
# get a JWT token # get a JWT token
auth = requests.auth.HTTPBasicAuth(admin_user, admin_password) 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: if r.status_code != 200:
print("error getting access token: {}".format(r.text)) print("error getting access token: {}".format(r.text))
sys.exit(1) sys.exit(1)
@ -33,14 +33,14 @@ auth_header = {"Authorization": "Bearer " + access_token}
for username in users_to_update: for username in users_to_update:
r = requests.get(urlparse.urljoin(base_url, posixpath.join("api/v2/users", username)), 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: if r.status_code != 200:
print("error getting user {}: {}".format(username, r.text)) print("error getting user {}: {}".format(username, r.text))
continue continue
user = r.json() user = r.json()
user.update(fields_to_update) user.update(fields_to_update)
r = requests.put(urlparse.urljoin(base_url, posixpath.join("api/v2/users", username)), 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: if r.status_code == 200:
print("user {} updated".format(username)) print("user {} updated".format(username))
else: else:

View file

@ -50,7 +50,7 @@ class UpdateQuota:
return return
auth = requests.auth.HTTPBasicAuth(admin_user, admin_password) 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: if r.status_code != 200:
self.printLog("error getting access token: {}".format(r.text)) self.printLog("error getting access token: {}".format(r.text))
sys.exit(1) sys.exit(1)
@ -65,7 +65,8 @@ class UpdateQuota:
def waitForQuotaUpdate(self, username): def waitForQuotaUpdate(self, username):
while True: while True:
auth_header = self.getAuthHeader() 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: if r.status_code != 200:
self.printLog("error getting quota scans while waiting for {}: {}".format(username, r.text)) self.printLog("error getting quota scans while waiting for {}: {}".format(username, r.text))
sys.exit(1) sys.exit(1)
@ -85,7 +86,7 @@ class UpdateQuota:
self.printLog("starting quota update for user {}".format(username)) self.printLog("starting quota update for user {}".format(username))
auth_header = self.getAuthHeader() auth_header = self.getAuthHeader()
r = requests.post(urlparse.urljoin(base_url, "api/v2/quota-scans"), headers=auth_header, 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: if r.status_code != 202:
self.printLog("error starting quota scan for user {}: {}".format(username, r.text)) self.printLog("error starting quota scan for user {}: {}".format(username, r.text))
sys.exit(1) sys.exit(1)
@ -97,7 +98,7 @@ class UpdateQuota:
auth_header = self.getAuthHeader() auth_header = self.getAuthHeader()
payload = {"limit":self.limit, "offset":self.offset} payload = {"limit":self.limit, "offset":self.offset}
r = requests.get(urlparse.urljoin(base_url, "api/v2/users"), headers=auth_header, params=payload, 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: if r.status_code != 200:
self.printLog("error getting users: {}".format(r.text)) self.printLog("error getting users: {}".format(r.text))
sys.exit(1) sys.exit(1)

View file

@ -3596,6 +3596,7 @@ func TestUpdateUserQuotaUsageMock(t *testing.T) {
usedQuotaSize := int64(65535) usedQuotaSize := int64(65535)
u.UsedQuotaFiles = usedQuotaFiles u.UsedQuotaFiles = usedQuotaFiles
u.UsedQuotaSize = usedQuotaSize u.UsedQuotaSize = usedQuotaSize
u.QuotaFiles = 100
userAsJSON := getUserAsJSON(t, u) userAsJSON := getUserAsJSON(t, u)
req, _ := http.NewRequest(http.MethodPost, userPath, bytes.NewBuffer(userAsJSON)) req, _ := http.NewRequest(http.MethodPost, userPath, bytes.NewBuffer(userAsJSON))
setBearerForReq(req, token) setBearerForReq(req, token)
@ -3615,6 +3616,37 @@ func TestUpdateUserQuotaUsageMock(t *testing.T) {
assert.NoError(t, err) assert.NoError(t, err)
assert.Equal(t, usedQuotaFiles, user.UsedQuotaFiles) assert.Equal(t, usedQuotaFiles, user.UsedQuotaFiles)
assert.Equal(t, usedQuotaSize, user.UsedQuotaSize) 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"))) req, _ = http.NewRequest(http.MethodPut, updateUsedQuotaPath, bytes.NewBuffer([]byte("string")))
setBearerForReq(req, token) setBearerForReq(req, token)
rr = executeRequest(req) rr = executeRequest(req)

View file

@ -14,6 +14,7 @@ info:
description: SFTPGo REST API description: SFTPGo REST API
version: 2.0.5 version: 2.0.5
contact: contact:
name: API support
url: 'https://github.com/drakkan/sftpgo' url: 'https://github.com/drakkan/sftpgo'
license: license:
name: AGPLv3 name: AGPLv3
@ -375,7 +376,7 @@ paths:
example: reset example: reset
requestBody: requestBody:
required: true 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: content:
application/json: application/json:
schema: schema: