The Research Drive Dashboard includes an API, which supports the same requests to be made as via web environment.
For the API, the same rights apply to your account as apply to the web environment as well.
On this page we describe some examples, just based on CURL.
With some programming, for example with the Programming Language Python, this API endpoint be used really simply.
All possible calls can be found on the special API documentation page, where you will also find some example requests.
The API documentation page can be founded at https://<your-environment-url>/dashboard/api/documentation
To access the Dashboard API, you must create an access token by your account details.
1. Click on your username in the right upper corner, to direct access your account details.
2. By your account details, you can enable the API.
3. Save your API token. It is shown once.
With your API access token, you're able to request your account details.
curl -X 'GET' 'https://<environment_url>/dashboard/api/me' \ -H 'accept: application/json' \ -H 'Accept-Language: en' \ -H 'Authorization: Bearer <your-access-token>'
Example response;
{ "data": { "id": 2075, "username": "dashboardadmin1", "name": "dashboardadmin1", "email": "None", "backend": { "value": "local", "trans": "Local" }, "mfa": { "value": "disabled", "trans": "Disabled" }, "description": null, "last_login": null, "status": { "value": "active", "trans": "Active" }, "inviter": false, "max_groups": null, "create_date": "2022-12-06 15:01:02", "change_date": "2023-02-06 13:40:37", "is_application_account": true, "is_surf_admin": false, "is_portal_admin": true, "is_contract_admin": false, "application_account": { "id": 790, "username": "dashboardadmin1", "role": { "value": "portal_admin", "trans": "Portal admin" }, "is_surf_admin": false, "is_portal_admin": true }, "groups": [ { "id": 2294, "username": "project_x", "name": "Project-X", "email": "None", "backend": { "value": "local", "trans": "Local" }, "mfa": null, "description": "This is test", "last_login": null, "status": { "value": "active", "trans": "Active" }, "inviter": false, "max_groups": null, "create_date": "2023-01-30 23:17:39", "change_date": "2023-02-06 13:40:37", "groups_membership": { "id": 55865204, "shared_from": 2294, "shared_with": 2075, "role": { "value": "member", "trans": "Member" }, "is_projectfolder_owner": false, "is_member": true } } ], "contracts": [] }, "auth": { "can_store_account": true, "can_store_contract": true, "can_store_any_functional_account": true }, "message": "Successfully retrieved user." }
Retrieval of all account, including configuration and usage information.
curl -X 'GET' 'https://<environment_url>/dashboard/api/account' \ -H 'accept: application/json' \ -H 'Accept-Language: en' \ -H 'Authorization: Bearer <your-access-token>'
Example response;
{ "data": [ { "id": 2339, "username": "JfDa1eozv7ZvPpG4Y73XDiEHQ982FEnYMYTDOjKY", "name": "John Doe", "email": "john@doe.nl", "backend": null, "mfa": null, "description": null, "last_login": null, "status": { "value": "new", "trans": "New" }, "inviter": false, "max_groups": null, "create_date": "2023-02-16 09:28:47", "change_date": null, "contract_id": "KlantX" }, { "id": 2168, "username": "pietje@puk.nl", "name": "Pietje Puk", "email": "pietje@puk.nl", "backend": { "value": "institutional", "trans": "Institutional" }, "mfa": null, "description": "wijzig meerdere velden tegelijk", "last_login": null, "status": { "value": "active", "trans": "Active" }, "inviter": false, "max_groups": null, "create_date": "2022-12-16 09:24:55", "change_date": "2023-02-06 13:40:37", "contract_id": "default", "end_date": "2020-03-28" }, .. .. ], "order_directions": [ { "value": "asc" }, { "value": "desc" } ], "message": "Accounts retrieved." }
Retrieval of all local or guest accounts, which have MFA not configured (disabled).
curl -X 'GET' 'https://<environment_url>/dashboard/api/account?status[]=active&backend[]=local&backend[]=guest&mfa[]=disabled' \ -H 'accept: application/json' \ -H 'Accept-Language: en' \ -H 'Authorization: Bearer <your-access-token>'
Example response;
{ "data": [ { "id": 2339, "username": "j.doe@username.here", "name": "John Doe", "email": "john@doe.nl", "backend": { "value": "local", "trans": "Local" }, "mfa": { "value": "disabled", "trans": "Disabled" }, "last_login": "2023-10-20 09:12:50", "status": { "value": "active", "trans": "Active" }, "description": null, "inviter": false, "max_groups": null, "create_date": "2023-02-16 09:28:47", "change_date": null, "contract_id": "KlantX" }, .. .. ], "order_directions": [ { "value": "asc" }, { "value": "desc" } ], "message": "Accounts retrieved." }
Retrieval of a specific account, including configuration and usage information.
curl -X 'GET' 'https://<environment_url>/dashboard/api/account/2168' \ -H 'accept: application/json' \ -H 'Accept-Language: en' \ -H 'Authorization: Bearer <your-access-token>'
Example response;
{ "data": { "id": 2168, "username": "pietje@puk.nl", "name": "Pietje Puk", "email": "pietje@puk.nl", "backend": { "value": "institutional", "trans": "Institutional" }, "mfa": null, "description": "wijzig meerdere velden tegelijk", "last_login": null, "status": { "value": "active", "trans": "Active" }, "invited_by": { "id": 628, "username": "johnd", "name": "John Doe", "email": "John.Doe@surf.nl", "backend": { "value": "local", "trans": "Local" }, "mfa": { "value": "disabled", "trans": "Disabled" }, "description": null, "last_login": null, "status": { "value": "active", "trans": "Active" }, "inviter": false, "max_groups": null, "create_date": "2020-01-13 11:54:01", "change_date": "2023-02-06 13:40:37" }, "inviter": false, "max_groups": null, "create_date": "2022-12-16 09:24:55", "change_date": "2023-02-06 13:40:37", "is_application_account": null, "is_surf_admin": null, "is_portal_admin": null, "application_account": null, "storage": { "id": 2138, "type": { "value": "personal", "trans": "Personal" }, "usage": { "value": 0, "trans": "0.00 GB" }, "quotum": { "value": 0, "trans": "0.00 GB" }, "status": { "value": "active", "trans": "Active" }, "last_update": null, "contract": { "id": 6, "contract_id": "default", "owner": "Jane Doe", "owner_email": "Jane@Doe.nl", "contact": null, "description": "Default contract", "quotum": { "value": 30000, "trans": "30 TB" }, "start_date": "2019-03-14", "end_date": "2020-03-28", "status": { "value": "active", "trans": "Active" }, "internal": 0, "ocgroup": null, "remove_period": { "value": 90 }, "inviter": true, "strictaudit": false, "invitation_whitelist": null, "quotum_option": [ { "value": 1, "trans": "500 GB", "quotum": 500 }, { "value": 2, "trans": "1000 GB", "quotum": 1000 }, { "value": 16, "trans": "10 GB", "quotum": 10 }, { "value": 32, "trans": "25 GB", "quotum": 25 }, { "value": 64, "trans": "50 GB", "quotum": 50 }, { "value": 128, "trans": "Custom input", "quotum": null }, { "value": 256, "trans": "100 GB", "quotum": 100 } ], "max_groups": 0, "accounts": [], "storages_sum_usage": { "value": 320.238141642, "trans": "320.24 GB" }, "storages_sum_quotum": { "value": 28399, "trans": "28.4 TB" } } }, "services": [ { "id": 6, "service": "Jupyter Hub", "description": "", "ocgroup": "jupyter" }, { "id": 9, "service": "Dashboard", "description": "Research Drive Dashboard", "ocgroup": "dashboard" }, { "id": 12, "service": "OnlyOffice", "description": "OnlyOffice Collaborative Editing", "ocgroup": "onlyoffice" }, ], "groups": [ { "id": 2309, "username": "pietjespuk_atvnistz", "name": "PietjesPuk", "email": "None", "backend": { "value": "local", "trans": "Local" }, "mfa": null, "description": "Test Example", "last_login": null, "status": { "value": "active", "trans": "Active" }, "inviter": false, "max_groups": null, "create_date": "2023-02-03 08:39:38", "change_date": "2023-02-06 13:40:37", "groups_membership": { "id": 55865228, "shared_from": 2309, "shared_with": 2168, "role": { "value": "projectfolder_owner", "trans": "Projectfolder owner" }, "is_projectfolder_owner": true, "is_member": false } }, { "id": 2312, "username": "test_uzgqfkiz", "name": "Test", "email": "None", "backend": { "value": "local", "trans": "Local" }, "mfa": null, "description": null, "last_login": null, "status": { "value": "active", "trans": "Active" }, "inviter": false, "max_groups": null, "create_date": "2023-02-03 10:50:19", "change_date": "2023-02-06 13:40:37", "groups_membership": { "id": 55865231, "shared_from": 2312, "shared_with": 2168, "role": { "value": "projectfolder_owner", "trans": "Projectfolder owner" }, "is_projectfolder_owner": true, "is_member": false } } ] }, "auth": { "is_inviter": false, "is_contract_admin": false, "can_update": true, "can_update_status": [ { "value": "inactive", "trans": "Inactive" }, { "value": "remove", "trans": "Remove" } ], "can_attach_contract": true, "can_attach_any_service": true, "can_store_personal_access_token": false, "can_destroy_personal_access_token": false, "can_update_setting": true, "can_store_invite": false, "can_destroy_mfa": false, "can_update_password": false }, "message": "Account retrieved." }
Update the account status of a specific account.
- userid: Replace userid with the uniq numeric userid of the user account. Example: 2168
- status: Replace status with the intended status. This can be; active, inactive, remove or force_remove
curl -X 'PUT' 'https://<environment_url>/dashboard/api/account/<userid>/status/<status>' \ -H 'accept: application/json' \ -H 'Accept-Language: en' \ -H 'Authorization: Bearer <your-access-token>'
Example response;
{ "message": "Account blocked." }
Send a new user invite to user John Doe
curl -X 'POST' 'https://<environment_url>/dashboard/api/account' \ -H 'accept: application/json' \ -H 'Accept-Language: en' \ -H 'Authorization: Bearer <your-access-token>' \ -H 'Content-Type: application/json' \ -d '{ "name": "John Doe", "email": "John@Doe.nl" }'
Example response;
{ "message": "Account stored." }
Retrieval of all account, including configuration and usage information.
curl -X 'GET' 'https://<environment_url>/dashboard/api/functional-account' \ -H 'accept: application/json' \ -H 'Accept-Language: en' \ -H 'Authorization: Bearer <your-access-token>'
Example response;
{ "data": [ { "id": 14060, "name": "Team Space", "description": "Project space", "owner_name": "Janssen, J.J. (Jan)", "status": { "value": "active", "trans": "Active" }, "usage": { "value": 0, "trans": "0.00 GB" }, "quotum": { "value": 5000, "trans": "5 TB" }, "strictaudit": { "value": 0, "trans": "No" }, "change_date": "2023-10-19 00:17:08", "contract_id": "Contract_XYZ", "contract_end_date": "2025-08-25", "create_date": "2023-10-19 00:05:21", "end_date": null, "costcenter": null }, { "id": 14050, "name": "Researchdrive projectfolder", "description": null, "owner_name": "J. Doe", "status": { "value": "active", "trans": "Active" }, "usage": { "value": 152.6502245, "trans": "152.65 GB" }, "quotum": { "value": 5000, "trans": "5 TB" }, "strictaudit": { "value": 0, "trans": "No" }, "change_date": "2023-10-16 14:17:48", "contract_id": "ContractABC", "contract_end_date": "2024-10-03", "create_date": "2023-10-16 13:16:46", "end_date": null, "costcenter": null }, .. .. ], "order_directions": [ { "value": "asc" }, { "value": "desc" } ], "message": "Accounts retrieved." }
In the example below, we create a new project folder. An explanation of the values;
- Name: Projectfolder name
- Account.id: May be the unique id or the username of the account which will become project folder admin
- Description: Project description, visible only in Dashboard. (Not a required field)
- contract.id: The unique id of the contract, to which it can be attached.
Note: the contract must be active, have sufficient storage available and an end date in the future. - Quotum: amount of allocated storage capacity in GB
curl -X 'POST' 'https://<environment_url>/dashboard/api/functional-account' \ -H 'accept: application/json' \ -H 'Accept-Language: en' \ -H 'Authorization: Bearer <your-access-token>' \ -H 'Content-Type: application/json' \ -d '{ "name": "NameOfMyProject", "account": { "id": "j.doe@username.here" }, "description": "Project Description Which is not Requird", "contract": { "id": 123 }, "quotum": 10 }'
Example response;
{ "message": "Projectfolder stored." }
Retrieval of all contracts, including configuration and usage information.
curl -X 'GET' 'https://<environment_url>/dashboard/api/contract' \ -H 'accept: application/json' \ -H 'Accept-Language: en' \ -H 'Authorization: Bearer <your-access-token>'
Example response;
{ "data": [ { "id": 149, "contract_id": "test8", "owner": "dashboardadmin1", "owner_email": "dash@admin.nl", "contact": [], "description": "test", "quotum": { "value": 500, "trans": "500 GB" }, "start_date": "2023-02-15", "end_date": "2023-03-08", "status": { "value": "active", "trans": "Active" }, "internal": 0, "ocgroup": null, "remove_period": { "value": 30 }, "inviter": true, "strictaudit": false, "invitation_whitelist": null, "quotum_option": [ { "value": 256, "trans": "100 GB", "quotum": 100 } ], "max_groups": 2, "storages_sum_usage": { "value": 0, "trans": "0.00 GB" }, "storages_sum_quotum": { "value": 200, "trans": "200 GB" } }, { "id": 146, "contract_id": "Test123", "owner": "tom", ... ... ], "order_directions": [ { "value": "asc" }, { "value": "desc" } ], "message": "Accounts retrieved." }
The API is limited to being able to return up to a maximum of 1000 records in once. This is done because loading the many relation takes some time.
It is faster to loop over multiple lists with smaller number of records.
Example what could work;
for i in `seq 1 $(curl -s -X GET '<environment_url>/dashboard/api/account?per_page=250' \ -H 'accept: application/json' -H 'Accept-Language: en' \ -H 'Authorization: <your-access-token>' | jq .meta.last_page)` do echo "Loop over page: ${i}" curl -X GET "https://<environment_url>/dashboard/api/account?page=${i}&per_page=250" \ -H "accept: application/json" \ -H "Accept-Language: en" \ -H "Authorization: <your-access-token>" | jq .data done
The above was done on a Unix machine. In this example we make use of the JSON processor JQ (https://jqlang.github.io/jq/)
Explaining what happens here;
We do an first request to the endpoint, where we parse the total number op pages.
curl -s -X GET '<environment_url>/dashboard/api/account?per_page=250' \ -H 'accept: application/json' -H 'Accept-Language: en' \ -H 'Authorization: <your-access-token>' | jq .meta.last_page
We loop over the result of this number of pages;
for i in `seq 1 $(curl -s -X GET '<environment_url>/dashboard/api/account?per_page=250' \ -H 'accept: application/json' -H 'Accept-Language: en' \ -H 'Authorization: <your-access-token>' | jq .meta.last_page)` do echo "Loop over page: ${i}" done
Collect the data records of each page
for i in `seq 1 $(curl -s -X GET '<environment_url>/dashboard/api/account?per_page=250' \ -H 'accept: application/json' -H 'Accept-Language: en' \ -H 'Authorization: <your-access-token>' | jq .meta.last_page)` do echo "Loop over page: ${i}" curl -X GET "https://<environment_url>/dashboard/api/account?page=${i}&per_page=250" \ -H "accept: application/json" \ -H "Accept-Language: en" \ -H "Authorization: <your-access-token>" | jq .data >> /tmp/api_results.json done
This is just a small example with CURL. With languages like Python, this can easily be used.
Dit is een voorbeeld om met gebruik van de programmeertaal Python een account van status te kunnen wisselen.
Dit is een in 5-minuten in elkaar gezet script, gebruik dit niet in productie omdat fout afhandeling er niet in zit!
Een snel voorbeeld ;
#!/usr/bin/env python import os import argparse import requests import json ### # Variables ### env_url = "environment_url" # Your Environment URL Here api_token = "" # Your AccessToken Here ### # Argument Parser from command-line ### parser = argparse.ArgumentParser() parser.add_argument("-d", "--debug", action="count", default=0, help="Enable debug output") parser.add_argument("--active", action="count", default=0, help="Activate user") parser.add_argument("--remove", action="count", default=0, help="Remove user") parser.add_argument("--disable", action="count", default=0, help="Disable user") parser.add_argument("-u", "--user", type=str, required=True, help="Username of user to lookup") args = parser.parse_args() # Set input in readable string debug = args.debug input_user = args.user activate_account = args.active remove_account = args.remove disable_account = args.disable ### # Lookup where an user lives based on emailaddress or username ### def get_user_by_username(user): try: if debug == 1: print(f"DEBUG - try to lookup user: {user}") url = f"https://{env_url}/dashboard/api/account?search={user}" headers = { 'Accept': 'application/json', 'Authorization': 'Bearer ' +str(api_token ), } response = requests.get(url, headers=headers) response_code = response.raise_for_status() if debug == 1: print("DEBUG - Status Code", response.status_code) print("DEBUG - Response ", response.text) # load the json to a string api_json = json.dumps(response.json()) api_resp = json.loads(api_json) return(api_resp['data']) except requests.exceptions.HTTPError as err: raise SystemExit(err) def set_user_status_by_id(userid,status): try: if debug == 1: print(f"DEBUG - try to set user {userid} to status {status}") url = f"https://{env_url}/dashboard/api/account/{userid}/status/{status}" headers = { 'Accept': 'application/json', 'Authorization': 'Bearer ' +str(api_token ), } response = requests.put(url, headers=headers) response_code = response.raise_for_status() if debug == 1: print("DEBUG - Status Code", response.status_code) print("DEBUG - Response ", response.text) if not response.status_code in [100, 200, 201]: print(f"Request for {userid} was unsuccesful.") raise return(response.text) except requests.exceptions.HTTPError as err: raise SystemExit(err) ### # Main ### def main(): account = get_user_by_username(input_user) if debug == 1: print(f"Account details: {account}") if len(account) > 1: print(f"Got more then 1 result.") exit() try: account_id = account[0]['id'] print(f"Handle account {input_user} with uniq account id: {account_id}") if activate_account == 1: status = 'active' set_user_status_by_id(account_id,status) elif disable_account == 1: status = 'inactive' set_user_status_by_id(account_id,status) elif remove_account == 1: status = 'remove' set_user_status_by_id(account_id,status) except Exception as e: print(f"Error during account handling. Error was {e}") if __name__ == '__main__': main()
Dit is een in 5-minuten in elkaar gezet script, gebruik dit niet in productie omdat fout afhandeling er niet in zit!
- No labels