This repository contains the backend part of Tags Drive
The basic information and FAQ can be found in the tags-drive/tags-drive repository.
Usage
CL commands
./tags-drive
, ./tags-drive start
– launch Tags Drive
./tags-drive decrypt
– launch the Decryptor. You can find more information about Decryptor here
./tags-drive migrate
– launch the Migrator. You can find more information about Migrator here
Environment variables
Variable |
Default |
Description |
DEBUG |
false |
|
WEB_PORT |
80 |
Port for http server |
WEB_TLS |
true |
Enable HTTPS |
WEB_LOGIN |
user |
Set your login |
WEB_PASSWORD |
qwerty |
Set your password |
WEB_SKIP_LOGIN |
false |
Skip the log-in procedure |
WEB_MAX_TOKEN_LIFE |
1440h |
The max lifetime of a token (default lifetime is 60 days) |
STORAGE_ENCRYPT |
false |
Encrypt meta files. Uploaded files are encrypted only when STORAGE_FILES_TYPE=disk |
STORAGE_PASS_PHRASE |
"" |
A phrase for file encryption. Cannot be empty if ENCRYPT == true |
STORAGE_TIME_BEFORE_DELETING |
168h |
Time before deleting a file from the Trash (default delay is 7 days) |
STORAGE_FILES_TYPE |
disk |
Define the kind of File Storage. The available options are disk , s3 |
STORAGE_S3_ENDPOINT |
"" |
URL to object storage service |
STORAGE_S3_ACCESS_KEY_ID |
"" |
The user ID that uniquely identifies the account |
STORAGE_S3_SECRET_ACCESS_KEY |
"" |
Password to the account |
STORAGE_S3_SECURE |
false |
Enable secure (HTTPS) access |
STORAGE_S3_BUCKET_LOCATION |
"" |
S3 bucket location (can be empty) |
Technical details
File storage
Disk
Files are stored in var/data
and var/data/resized
folders. Files are encrypted according to STORAGE_ENCRYPT
env var.
S3
Files can be stored in S3 compatible storage in var-data
and var-data-resized
buckets. Tags Drive interacts with S3 compatible storage by github.com/minio/minio-go package.
Note: STORAGE_ENCRYPT
doesn't affect if S3 storage is used.
File structure
Var folder
-
auth_tokens.json
- contains valid tokens
Example
[
{
"token": "first-token",
"expire": "2018-12-13T17:13:02.7716523+03:00"
},
{
"token": "second-token",
"expire": "2019-01-02T15:35:18.7829909-08:00"
}
]
-
files.json
- contains a json map of all files
Example
{
"1": {
"id": 1,
"filename": "cute-cat.jpg",
"type": {
"ext": ".jpg",
"fileType": "image",
"supported": true,
"previewType": "image"
},
"origin": "data/1",
"preview": "data/resized/1",
"tags": [24,26],
"description": "very cute cat :)",
"size": 480900,
"addTime": "2018-12-29T16:45:07.4440863+03:00",
"deleted": false,
"timeToDelete": "0001-01-01T00:00:00Z"
},
}
-
tags.json
- contains a json map of all tags
Example
{
"12": {
"id": 12,
"name": "cute",
"color": "#55dcd4"
},
"15": {
"id": 15,
"name": "nature",
"color": "#c9f898"
}
}
-
share_tokens.json
- contains share tokens
Example
{
"some_token": [1, 2],
"another_token": [1, 2, 15, 27]
}
SSL folder
The ssl
folder contains TLS certificate files cert.cert
and key.key
Use this command to generate self-signed TLS certificate:
openssl req -x509 -nodes -newkey rsa:2048 -sha256 -keyout key.key -out cert.cert
Development
Run a local version
- scripts/run/go – run a local version with
go run
. You can set env vars by editing the .env file. It is the fastest way to launch the local version, but you need to have Go installed.
- scripts/run/docker – build a Docker image and run a container
Run tests
API
General endpoints
-
GET /
– main page
-
GET /mobile
– mobile version
-
GET /share?shareToken=token
- Tags Drive in share mode
-
GET /login
– login page
-
GET /data/{id}
– returns a file
-
GET /file-icons
– returns file icon
Params (at least one param must be specified):
- ext: extension of a file
- filename: name of a file
Auth
-
GET /api/user
– check if a user is authorized
Responses:
- if a user is authorized:
{ "authorized" : true }
- else:
401 Unauthorized
-
POST /api/login
– sets cookie with auth token
Params:
- login: user's login
- password: password (sha256 checksum repeated 11 times)
Response: -
-
POST /api/logout
– deletes auth cookie
Params: -
Response: -
Files
-
GET /api/file/{id}
– get file info
Params:
- id: id of a file
- shareToken (optional): allow to use this API method without auth (the response (files, tags) can be limited)
Response: json object of FileInfo
-
GET /api/files
– get a list of files
Params:
- expr: logical expression. Example:
!(12&15)&(12|15)
means all files that have single tag with the id 12
or 15
- search: a text/regexp search
- regexp: enable regexp search (it is
true
when regexp param is not an empty string)
- sort: name | size | time
- order: asc | desc
- offset: lower bound
[offset:]
- count: number of returned files (
[offset:offset+count]
). If count == 0, all files will be returned. Default value is 0
- shareToken (optional): allow to use this API method without auth (the response (files, tags) can be limited)
Response: json array of FileInfo
. Status code is 204
when offset is out of bounds.
-
GET /api/files/recent
– get a list of recent uploaded files
Params:
- number: number of returned files (5 is the default value)
Response: json array of FileInfo
-
GET /api/files/download
– download files in a zip archive
Params:
- ids: list of files ids for downloading separated by commas
ids=1,2,54,9
- shareToken (optional): allow to use this API method without auth (the response (files, tags) can be limited)
Response: zip archive
-
POST /api/files
– upload files
Params:
- tags: list of tags separated by commas (
tags=1,2,3
)
Body must be multipart/form-data
Response: json array of multiplyResponse
Changing file info
-
PUT /api/file/{id}/name
– update name of a file
Params:
- id: file id
- new-name: new filename
Response: updated file (json object of FileInfo
)
-
PUT /api/file/{id}/tags
– update tags of a file
Params:
- id: file id
- tags: updated list of tags separated by commas (
tags=1,2,3
)
Response: updated file (json object of FileInfo
)
-
PUT /api/file/{id}/description
– update description of a file
Params:
- id: file id
- description: updated description
Response: updated file (json object of FileInfo
)
Removing and recovering
-
DELETE /api/files
– remove files
Params:
- ids: list of files ids for deleting separated by commas
ids=1,2,54,9
- force: enable instant deletion (if not empty, files will be deleted immediately)
Response: json array of multiplyResponse
-
POST /api/files/recover
– recover files from the Trash
Params:
- ids: list of files ids for recovering (list of ids separated by comma
ids=1,2,54,9
)
Response: -
-
GET /api/tags
– get list of tags
Params:
- shareToken (optional): allow to use this API method without auth (the response (files, tags) can be limited)
Response: json object of Tags
-
POST /api/tags
– add a new tag
Params:
- name: name of a new tag
- color: color of a new tag (
#ffffff
by default)
- group: group of a new tag (empty by default)
Response: -
-
PUT /api/tag/{id}
– update a tag
Params:
- id: tag id
- name: new tag name (can be empty)
- color: new tag color (can be empty)
- group: new tag group (can be empty)
Response: updated tag (json object of Tag
)
-
DELETE /api/tags
– remove a tag
Params:
- id: tag id (one tag at a time)
Response: -
Share
-
GET /api/share/tokens
- returns all share tokens
Params: -
Response: json map with tokens and ids of shared files
{
"token1": [1, 2, 3],
"token2": [4, 5, 25],
}
-
GET /api/share/token/{token}
- returns ids of files shared by passed token
Params:
Response: json array with ids of shared files
-
POST /api/share/token
- create a new share token
Params:
- ids: list of ids of files to share separated by commas (example:
?ids=1,2,3
)
Response: returns new share token
{ "token": "created token" }
-
DELETE /api/share/token/{token}
- delete a share token
Params:
Response: -
Other
-
GET /api/version
– returns the version of the backend part
-
GET /api/ping
– ping Tags Drive
Response: http.StatusOK
(200)
Additional info
Security
Uploaded files can be encrypted. Tags Drive uses sha256 sum of the PASS_PHRASE
for encryption. Encryption is realized by minio/sio package.
General structures
FileInfo
type FileType string
type PreviewType string
// Ext is a struct which contains a type of the original file and a type for a preview
type Ext struct {
Ext string `json:"ext"`
FileType FileType `json:"fileType"`
Supported bool `json:"supported"`
PreviewType PreviewType `json:"previewType"`
}
type File struct {
ID int `json:"id"`
Filename string `json:"filename"`
Type Ext `json:"type"`
//
Tags []int `json:"tags"`
Description string `json:"description,omitempty"`
Size int64 `json:"size"`
AddTime time.Time `json:"addTime"`
//
Deleted bool `json:"deleted"`
TimeToDelete int64 `json:"timeToDelete,omitempty"`
}
Tag
type Tag struct {
ID int `json:"id"`
Name string `json:"name"`
Color string `json:"color"`
Group string `json:"group"`
}
type Tags map[int]Tag
multiplyResponse
type multiplyResponse struct {
Filename string `json:"filename"`
IsError bool `json:"isError"`
Error string `json:"error"`
Status string `json:"status"` // Status isn't empty when IsError == false
}