Overview
Goodmorning Services contains the api stuff, manages various accounts, storage related things.
Api structure
Structured similar to a REST api, all paths can be found in /api/[service]/vX/[path...].
Some requires posts requests, some get requests, and sometimes multipart post if the client is trying to upload a file.
Requirements
To run this, use cargo r (--release):
- Edit the autogenerated config files in (root)
~/.config/gm/ - Have mongodb running as specified in
storage.yml.
If you are using this as a dependency (such as gmt-server):
- Run
goodmorning_services::init()at the beginning.
Note that other more specialised servers may have additional API endpoints.
Bindings
Accounts
/api/accounts
Account operations such as create, delete, login.
v1
/api/accounts/v1
POST /api/accounts/v1/create
Create an account
Request
{
"username": String,
"email": String,
"password": String
}
Response
Status code: 201
{
"type": "created",
"id": i64,
"token": String,
"verify": Boolean
}
Possible errors
invalid usernameusername takenemail takenexternal
POST /api/accounts/v1/delete
Delete an account
Request
{
"password": String,
"token": String
}
Response
Status code: 200
{
"type": "deleted"
}
Possible errors
invalid tokenpassword incorrectexternal
POST /api/accounts/v1/login
Get user ID and token from identifier and password.
Request
{
"identifier": String,
"identifier-type": "id"/"username"/"email",
"password": String
}
Response
Status code: 200
{
"type": "login",
"id": i64,
"token": String
}
Possible errors
no such userpassword incorrectexternal
POST /api/accounts/v1/regeneratetoken
Regenerate your token, invalidating all other logins.
Request
{
"token": String,
"password": String
}
Response
Status code: 200
{
"type": "regenerated",
"token": String
}
Possible errors
invalid tokenpassword incorrectexternal
POST /api/accounts/v1/rename
Change username.
Request
{
"token": String,
"new": String
}
Response
Status code: 200
{
"type": "renamed"
}
Possible errors
invalid usernameinvalid tokenpassword incorrectexternal
POST /api/accounts/v1/change-password
Regenerate your token, invalidating all other logins.
Request
{
"new": String, // the password you want to change to
"old": String,
"token": String
}
Response
Status code: 200
{
"type": "password changed"
}
Possible errors
password incorrectinvalid tokenexternal
POST /api/accounts/v1/change-email
Regenerate your token, invalidating all other logins.
Request
{
"new": String, // the email you want to change to
"token": String,
"password": String
}
Response
Status code: 200
{
"type": "email changed",
"verify": Boolean
}
Possible errors
email takenpassword incorrectinvalid tokencooldownexternal
POST /api/accounts/v1/resend-verify
Resend verification message to email.
Request
{
"token": String
}
Response
Status code: 200
{
"type": "verification sent"
}
Possible errors
invalid tokennothing changedcooldownexternal
POST /api/accounts/v1/set-status
Change user status.
Request
{
"token": String,
"new": String
}
Response
Status code: 200
{
"type": "profile updated"
}
Possible errors
invalid tokenexceeds maximum lengthexternal
POST /api/accounts/v1/access
View users with this access.
Request
{
"token": String,
"access_type": AccessType,
"identifier": String?,
"identifier-type": String?
}
AccessType includes file, blue, and access.
Response
Status code: 200
{
"type": "access",
"users": [
{
"id": Int,
"name": String
}
// ...
]
}
Possible errors
no such userinvalid tokenpermission deniedexternal
POST /api/accounts/v1/accessto
View users with this user have access to.
Request
{
"token": String,
"access_type": AccessType,
"identifier": String?,
"identifier-type": String?
}
AccessType includes file, blue, and access.
Response
Status code: 200
{
"type": "allowed access",
"users": [
{
"id": Int,
"name": String
}
// ...
]
}
Possible errors
no such userinvalid tokenpermission deniedexternal
POST /api/accounts/v1/allow
Allow access for a user.
Request
{
"token": String,
"identifier": String,
"identifier-type": "id"/"username"/"email",
"access_type": AccessType
}
Response
Status code: 200
{
"type": "allowed"
}
Possible errors
no such userinvalid tokenexternal
POST /api/accounts/v1/disallow
Remove access for a user.
Request
{
"token": String,
"identifier": String,
"identifier-type": "id"/"username"/"email",
"access_type": AccessType
}
Response
Status code: 200
{
"type": "disallowed"
}
Possible errors
no such userinvalid tokenexternal
Storage
/api/storage
User storage operations such as copy, upload, ls.
v1
/api/storage/v1
POST /api/storage/v1/copy or /api/storage/v1/copy-overwrite
Copy file to destination path, file can be owned by self or by others (only if the file is hidden or public).
Request
{
"token": String,
"from-userid": i64, (who to copy from, can be your own id)
"from": String,
"to": String
}
Response
Status code: 201
{
"type": "copied"
}
Possible errors
invalid tokennot verifiedpermission deniedpath occupied(non overwrite only)file not foundstorage fullexternal
POST /api/storage/v1/delete
Delete file.
Request
{
"token": String,
"path": String
}
Response
Status code: 200
{
"type": "deleted"
}
Possible errors
invalid tokennot verifiedpermission deniedfile not foundexternal
POST /api/storage/v1/delete-multiple
Delete multiple file in order.
Request
{
"token": String,
"paths": [String]
}
Response
Status code: 200
{
"type": "multi",
"res": [V1Response]
}
Possible errors
invalid tokennot verifiedpermission deniedfile not foundexternal
POST /api/storage/v1/exists
Check if file exists
Request
{
"token": String,
"path": String
}
Response
Status code: 200
{
"type": "exists",
"value": bool
}
Possible errors
invalid tokennot verifiedpermission deniedexternal
GET /api/storage/v1/diritems/[token]/[path]
List items in directory.
For example to access /dir/deeper in your storage, you GET /api/storage/v1/diritems/token-gibberish/dir/deeper, where /dir/deeper is a directory.
Response
Status code: 200
{
"type": "dir content",
"content": [
{
"visibility": {
"inherited": bool,
"visibility": "hidden"/"private"/"public"
},
"is_file": bool,
"name": String,
"last_modified": u64,
"size": u64
},
...
]
}
Possible errors
invalid tokennot verifiedpermission deniedfile not foundtype mismatchexternal
GET /api/storage/v1/tree/[token]/[path]
Tree items in directory.
Response
Status code: 200
{
"type": "tree",
"content": TreeNode
}
Where TreeNode can either be a directory:
{
"type": "dir",
"name": String,
"visibility": {
"inherited": bool,
"visibility": Visibility // public, hidden or private
}
}
or a file:
{
"type": "file",
"name": String,
"size": u64,
"last_modified": u64,
"visibility": {
"inherited": bool,
"visibility": Visibility,
}
}
For example
{
"type": "tree",
"content": {
"type": "dir",
"name": ".system",
"visibility": {
"inherited": true,
"visibility": public,
},
"content": [
{
"type": "file",
"name": "pfp.png",
"size": 1165233,
"last_modified": 1688643521,
"visibility": {
"inherited": true,
"visibility": "public",
}
}
]
}
}
Possible errors
invalid tokennot verifiedpermission deniedfile not foundtype mismatchexternal
GET /api/storage/v1/file/[token]/[path]
Returns file content.
For example to access /dir/file.txt in your storage, you GET /api/storage/v1/diritems/token-gibberish/dir/file.txt, where /dir/file.txt is a file.
Response
Status code: 200
[file content]
Possible errors
invalid tokennot verifiedpermission deniedfile not foundtype mismatchexternal
POST /api/storage/v1/mkdir
Creates a directory
Request
{
"token": String,
"path": String
}
Response
Status code: 201
{
"type": "file item created"
}
Possible errors
invalid tokennot verifiedpermission deniedexternal
POST /api/storage/v1/mkdir-multiple
Creates multiple directories in order
Request
{
"token": String,
"paths": [String]
}
Response
Status code: 201
{
"type": "multi",
"res": [V1Response]
}
Possible errors
invalid tokennot verifiedpermission deniedexternal
POST /api/storage/v1/move or /api/storage/v1/move-overwrite or /api/storage/v1/move-createdirs or /api/storage/v1/move-createdirs-overwrite
Move/rename file to destination path.
Request
{
"token": String,
"from": String,
"to": String
}
Response
Status code: 200
{
"type": "moved"
}
Possible errors
invalid tokennot verifiedpermission deniedpath occupied(non overwrite only)file not foundexternal
POST /api/storage/v1/set-visibility or /api/storage/v1/remove-visibility
Change file or directory visibility.
Request (set)
{
"token": String,
"path": String,
"visibility": "hidden"/"private"/"public"
}
Request (remove)
{
"token": String,
"path": String,
}
Response
Status code: 200
{
"type": "visibility changed"
}
or
Status code: 304
{
"type": "nothing changed"
}
Possible errors
invalid tokennot verifiedpermission deniedfile not foundexternal
POST /api/storage/v1/touch
Creates an empty file.
Request
{
"token": String,
"path": String
}
Response
Status code: 201
{
"type": "file item created"
}
Possible errors
invalid tokennot verifiedpermission deniedexternal
POST with multipart /api/storage/v1/upload/[token]/[path], /api/storage/v1/upload-createdirs/[token]/[path], /api/storage/v1/upload-overwrite/[token]/[path] and /api/storage/v1/upload-createdirs-overwrite/[token]/[path]
Upload a file to destination path.
uploadreturns an error if the directory the file is uploading to does not exist, or the file path is occupied.upload-overwriteoverwrites whatever is in the path.upload-createdirscreate parent directory for the upload target if it does not exist.upload-createdirs-overwritea mix of both
Request
[multipart file post]
Response
Status code: 201
{
"type": "file item created"
}
Possible errors
invalid tokennot verifiedpermission deniedpath occupied(non overwrite only)file not foundstorage fullexternal
Usercontent
/api/usercontent
View files created by other users.
v1
/api/usercontent/v1
GET /api/usercontent/v1/exists/id/[id]/[path]
Check if file exists
Response
Status code: 200
{
"type": "exists",
"value": bool
}
Possible errors
invalid tokennot verifiedpermission deniedexternal
GET /api/usercontent/v1/diritems/id/[userid]/[path]
List items in directory.
For example to access /dir/deeper in user with ID 1's storage, you GET /api/usercontent/v1/diritems/1/dir/deeper, where /dir/deeper is a directory.
Response
Status code: 200
{
"type": "dir content",
"content": [
{
"visibility": {
"inherited": bool,
"visibility": "hidden"/"private"/"public"
},
"is_file": bool,
"name": String,
"last_modified": u64,
"size": u64
},
...
]
}
Possible errors
permission deniedfile not foundtype mismatchexternal
GET /api/usercontent/v1/tree/id/[userid]/[path]
Tree items in directory.
Response
Status code: 200
{
"type": "tree",
"content": TreeNode
}
Where TreeNode can either be a directory:
{
"type": "dir",
"name": String,
"visibility": {
"inherited": bool,
"visibility": Visibility // public, hidden or private
}
}
or a file:
{
"type": "file",
"name": String,
"size": u64,
"last_modified": u64,
"visibility": {
"inherited": bool,
"visibility": Visibility,
}
}
For example
{
"type": "tree",
"content": {
"type": "dir",
"name": ".system",
"visibility": {
"inherited": true,
"visibility": public,
},
"content": [
{
"type": "file",
"name": "pfp.png",
"size": 1165233,
"last_modified": 1688643521,
"visibility": {
"inherited": true,
"visibility": "public",
}
}
]
}
}
Possible errors
permission deniedfile not foundtype mismatchexternal
GET /api/usercontent/v1/file/id/[userid]/[path]
Returns file content.
For example to access /dir/file.txt in user with ID 1's storage, you GET /api/usercontent/v1/file/id/1/dir/file.txt, where /dir/file.txt is a file.
Response
Status code: 200
[file content]
Possible errors
permission deniedfile not foundtype mismatchexternal
Triggers
/api/triggers
Urls that run trigger functions.
v1
/api/triggers/v1
GET /api/triggers/v1/use/[trigger id]
Uses trigger - and runs the code.
Response
Status code: 200
{
"type": "triggered"
}
Possible errors
trigger not foundexternal
GET /api/triggers/v1/use/[trigger id]
Revokes trigger so it can no longer be used.
Response
Status code: 200
{
"type": "revoked"
}
Possible errors
trigger not foundexternal
GET /api/triggers/v1/peek/[trigger id]
View trigger content without triggering it.
Response
Status code: 200
{
"type": "trigger peak",
"value": {
"type": "...",
...
}
}
Possible errors
trigger not foundexternal
POST /api/jobs/v1/jobs
List queued and running jobs.
Request
{
"token": String
}
Response
Status code: 200
{
"type": "jobs",
"current": [
{
"id": u64,
"task": {
"type": "compile",
"from": FromFormat,
"to": ToFormat,
"compiler": Compiler,
"path": String,
}
}
],
"queue": [
// ...
]
}
Possible errors
invalid tokenexternal
POST /api/jobs/v1/unqueue
Remove a queued job
Request
{
"token": String,
"id": u64
}
Response
Status code: 200
{
"type": "unqueued"
}
Possible errors
invalid tokenexternaljob not found