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 username
username taken
email taken
external
POST /api/accounts/v1/delete
Delete an account
Request
{
"password": String,
"token": String
}
Response
Status code: 200
{
"type": "deleted"
}
Possible errors
invalid token
password incorrect
external
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 user
password incorrect
external
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 token
password incorrect
external
POST /api/accounts/v1/rename
Change username.
Request
{
"token": String,
"new": String
}
Response
Status code: 200
{
"type": "renamed"
}
Possible errors
invalid username
invalid token
password incorrect
external
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 incorrect
invalid token
external
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 taken
password incorrect
invalid token
cooldown
external
POST /api/accounts/v1/resend-verify
Resend verification message to email.
Request
{
"token": String
}
Response
Status code: 200
{
"type": "verification sent"
}
Possible errors
invalid token
nothing changed
cooldown
external
POST /api/accounts/v1/set-status
Change user status.
Request
{
"token": String,
"new": String
}
Response
Status code: 200
{
"type": "profile updated"
}
Possible errors
invalid token
exceeds maximum length
external
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 user
invalid token
permission denied
external
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 user
invalid token
permission denied
external
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 user
invalid token
external
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 user
invalid token
external
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 token
not verified
permission denied
path occupied
(non overwrite only)file not found
storage full
external
POST /api/storage/v1/delete
Delete file.
Request
{
"token": String,
"path": String
}
Response
Status code: 200
{
"type": "deleted"
}
Possible errors
invalid token
not verified
permission denied
file not found
external
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 token
not verified
permission denied
file not found
external
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 token
not verified
permission denied
external
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 token
not verified
permission denied
file not found
type mismatch
external
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 token
not verified
permission denied
file not found
type mismatch
external
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 token
not verified
permission denied
file not found
type mismatch
external
POST /api/storage/v1/mkdir
Creates a directory
Request
{
"token": String,
"path": String
}
Response
Status code: 201
{
"type": "file item created"
}
Possible errors
invalid token
not verified
permission denied
external
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 token
not verified
permission denied
external
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 token
not verified
permission denied
path occupied
(non overwrite only)file not found
external
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 token
not verified
permission denied
file not found
external
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 token
not verified
permission denied
external
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.
upload
returns an error if the directory the file is uploading to does not exist, or the file path is occupied.upload-overwrite
overwrites whatever is in the path.upload-createdirs
create parent directory for the upload target if it does not exist.upload-createdirs-overwrite
a mix of both
Request
[multipart file post]
Response
Status code: 201
{
"type": "file item created"
}
Possible errors
invalid token
not verified
permission denied
path occupied
(non overwrite only)file not found
storage full
external
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 token
not verified
permission denied
external
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 denied
file not found
type mismatch
external
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 denied
file not found
type mismatch
external
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 denied
file not found
type mismatch
external
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 found
external
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 found
external
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 found
external
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 token
external
POST /api/jobs/v1/unqueue
Remove a queued job
Request
{
"token": String,
"id": u64
}
Response
Status code: 200
{
"type": "unqueued"
}
Possible errors
invalid token
external
job not found