mirror of
https://github.com/mattermost/focalboard.git
synced 2025-01-11 18:13:52 +02:00
Add Swagger / OpenAPI docs
This commit is contained in:
parent
13d48c5a8f
commit
1ad985232d
1
.gitignore
vendored
1
.gitignore
vendored
@ -59,3 +59,4 @@ win/temp
|
||||
win/dist
|
||||
webapp/cypress/screenshots
|
||||
webapp/cypress/videos
|
||||
server/swagger/clients
|
||||
|
12
Makefile
12
Makefile
@ -133,6 +133,18 @@ linux-app: server-linux webapp
|
||||
cd linux/temp; tar -zcf ../dist/focalboard-linux.tar.gz focalboard-app
|
||||
rm -rf linux/temp
|
||||
|
||||
swagger:
|
||||
mkdir -p server/swagger/docs
|
||||
mkdir -p server/swagger/clients
|
||||
cd server && swagger generate spec -m -o ./swagger/swagger.yml
|
||||
|
||||
cd server/swagger && openapi-generator generate -i swagger.yml -g html2 -o docs/html
|
||||
cd server/swagger && openapi-generator generate -i swagger.yml -g go -o clients/go
|
||||
cd server/swagger && openapi-generator generate -i swagger.yml -g javascript -o clients/javascript
|
||||
cd server/swagger && openapi-generator generate -i swagger.yml -g typescript-fetch -o clients/typescript
|
||||
cd server/swagger && openapi-generator generate -i swagger.yml -g swift5 -o clients/swift
|
||||
cd server/swagger && openapi-generator generate -i swagger.yml -g python -o clients/python
|
||||
|
||||
clean:
|
||||
rm -rf bin
|
||||
rm -rf dist
|
||||
|
@ -20,29 +20,29 @@ func (a *API) handleAdminSetPassword(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
requestBody, err := ioutil.ReadAll(r.Body)
|
||||
if err != nil {
|
||||
errorResponse(w, http.StatusInternalServerError, nil, err)
|
||||
errorResponse(w, http.StatusInternalServerError, "", err)
|
||||
return
|
||||
}
|
||||
|
||||
var requestData AdminSetPasswordData
|
||||
err = json.Unmarshal(requestBody, &requestData)
|
||||
if err != nil {
|
||||
errorResponse(w, http.StatusInternalServerError, nil, err)
|
||||
errorResponse(w, http.StatusInternalServerError, "", err)
|
||||
return
|
||||
}
|
||||
|
||||
if !strings.Contains(requestData.Password, "") {
|
||||
errorResponse(w, http.StatusInternalServerError, map[string]string{"error": "password is required"}, err)
|
||||
errorResponse(w, http.StatusBadRequest, "password is required", err)
|
||||
return
|
||||
}
|
||||
|
||||
err = a.app().UpdateUserPassword(username, requestData.Password)
|
||||
if err != nil {
|
||||
errorResponse(w, http.StatusInternalServerError, map[string]string{"error": err.Error()}, err)
|
||||
errorResponse(w, http.StatusInternalServerError, "", err)
|
||||
return
|
||||
}
|
||||
|
||||
log.Printf("AdminSetPassword, username: %s", username)
|
||||
|
||||
jsonBytesResponse(w, http.StatusOK, nil)
|
||||
jsonStringResponse(w, http.StatusOK, "{}")
|
||||
}
|
||||
|
@ -83,7 +83,7 @@ func (a *API) requireCSRFToken(next http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
if !a.checkCSRFToken(r) {
|
||||
log.Println("checkCSRFToken FAILED")
|
||||
errorResponse(w, http.StatusBadRequest, nil, nil)
|
||||
errorResponse(w, http.StatusBadRequest, "", nil)
|
||||
return
|
||||
}
|
||||
|
||||
@ -102,13 +102,45 @@ func (a *API) checkCSRFToken(r *http.Request) bool {
|
||||
}
|
||||
|
||||
func (a *API) handleGetBlocks(w http.ResponseWriter, r *http.Request) {
|
||||
// swagger:operation GET /api/v1/blocks getBlocks
|
||||
//
|
||||
// Returns blocks
|
||||
//
|
||||
// ---
|
||||
// produces:
|
||||
// - application/json
|
||||
// parameters:
|
||||
// - name: parent_id
|
||||
// in: query
|
||||
// description: ID of parent block, omit to specify all blocks
|
||||
// required: false
|
||||
// type: string
|
||||
// - name: type
|
||||
// in: query
|
||||
// description: Type of blocks to return, omit to specify all types
|
||||
// required: false
|
||||
// type: string
|
||||
// security:
|
||||
// - BearerAuth: []
|
||||
// responses:
|
||||
// '200':
|
||||
// description: success
|
||||
// schema:
|
||||
// type: array
|
||||
// items:
|
||||
// "$ref": "#/definitions/Block"
|
||||
// default:
|
||||
// description: internal error
|
||||
// schema:
|
||||
// "$ref": "#/definitions/ErrorResponse"
|
||||
|
||||
query := r.URL.Query()
|
||||
parentID := query.Get("parent_id")
|
||||
blockType := query.Get("type")
|
||||
|
||||
blocks, err := a.app().GetBlocks(parentID, blockType)
|
||||
if err != nil {
|
||||
errorResponse(w, http.StatusInternalServerError, nil, err)
|
||||
errorResponse(w, http.StatusInternalServerError, "", err)
|
||||
return
|
||||
}
|
||||
|
||||
@ -116,7 +148,7 @@ func (a *API) handleGetBlocks(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
json, err := json.Marshal(blocks)
|
||||
if err != nil {
|
||||
errorResponse(w, http.StatusInternalServerError, nil, err)
|
||||
errorResponse(w, http.StatusInternalServerError, "", err)
|
||||
return
|
||||
}
|
||||
|
||||
@ -137,9 +169,35 @@ func stampModifiedByUser(r *http.Request, blocks []model.Block) {
|
||||
}
|
||||
|
||||
func (a *API) handlePostBlocks(w http.ResponseWriter, r *http.Request) {
|
||||
// swagger:operation POST /api/v1/blocks updateBlocks
|
||||
//
|
||||
// Insert or update blocks
|
||||
//
|
||||
// ---
|
||||
// produces:
|
||||
// - application/json
|
||||
// parameters:
|
||||
// - name: Body
|
||||
// in: body
|
||||
// description: array of blocks to insert or update
|
||||
// required: true
|
||||
// schema:
|
||||
// type: array
|
||||
// items:
|
||||
// "$ref": "#/definitions/Block"
|
||||
// security:
|
||||
// - BearerAuth: []
|
||||
// responses:
|
||||
// '200':
|
||||
// description: success
|
||||
// default:
|
||||
// description: internal error
|
||||
// schema:
|
||||
// "$ref": "#/definitions/ErrorResponse"
|
||||
|
||||
requestBody, err := ioutil.ReadAll(r.Body)
|
||||
if err != nil {
|
||||
errorResponse(w, http.StatusInternalServerError, nil, err)
|
||||
errorResponse(w, http.StatusInternalServerError, "", err)
|
||||
return
|
||||
}
|
||||
|
||||
@ -147,27 +205,27 @@ func (a *API) handlePostBlocks(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
err = json.Unmarshal(requestBody, &blocks)
|
||||
if err != nil {
|
||||
errorResponse(w, http.StatusInternalServerError, nil, err)
|
||||
errorResponse(w, http.StatusInternalServerError, "", err)
|
||||
return
|
||||
}
|
||||
|
||||
for _, block := range blocks {
|
||||
// Error checking
|
||||
if len(block.Type) < 1 {
|
||||
errorData := map[string]string{"description": "missing type", "id": block.ID}
|
||||
errorResponse(w, http.StatusBadRequest, errorData, nil)
|
||||
message := fmt.Sprintf("missing type for block id %s", block.ID)
|
||||
errorResponse(w, http.StatusBadRequest, message, nil)
|
||||
return
|
||||
}
|
||||
|
||||
if block.CreateAt < 1 {
|
||||
errorData := map[string]string{"description": "invalid createAt", "id": block.ID}
|
||||
errorResponse(w, http.StatusBadRequest, errorData, nil)
|
||||
message := fmt.Sprintf("invalid createAt for block id %s", block.ID)
|
||||
errorResponse(w, http.StatusBadRequest, message, nil)
|
||||
return
|
||||
}
|
||||
|
||||
if block.UpdateAt < 1 {
|
||||
errorData := map[string]string{"description": "invalid UpdateAt", "id": block.ID}
|
||||
errorResponse(w, http.StatusBadRequest, errorData, nil)
|
||||
message := fmt.Sprintf("invalid UpdateAt for block id %s", block.ID)
|
||||
errorResponse(w, http.StatusBadRequest, message, nil)
|
||||
return
|
||||
}
|
||||
}
|
||||
@ -176,7 +234,7 @@ func (a *API) handlePostBlocks(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
err = a.app().InsertBlocks(blocks)
|
||||
if err != nil {
|
||||
errorResponse(w, http.StatusInternalServerError, nil, err)
|
||||
errorResponse(w, http.StatusInternalServerError, "", err)
|
||||
return
|
||||
}
|
||||
|
||||
@ -185,25 +243,69 @@ func (a *API) handlePostBlocks(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
func (a *API) handleGetUser(w http.ResponseWriter, r *http.Request) {
|
||||
// swagger:operation GET /api/v1/users/{userID} getUser
|
||||
//
|
||||
// Returns a user
|
||||
//
|
||||
// ---
|
||||
// produces:
|
||||
// - application/json
|
||||
// parameters:
|
||||
// - name: userID
|
||||
// in: path
|
||||
// description: User ID
|
||||
// required: true
|
||||
// type: string
|
||||
// security:
|
||||
// - BearerAuth: []
|
||||
// responses:
|
||||
// '200':
|
||||
// description: success
|
||||
// schema:
|
||||
// "$ref": "#/definitions/User"
|
||||
// default:
|
||||
// description: internal error
|
||||
// schema:
|
||||
// "$ref": "#/definitions/ErrorResponse"
|
||||
|
||||
vars := mux.Vars(r)
|
||||
userID := vars["userID"]
|
||||
|
||||
user, err := a.app().GetUser(userID)
|
||||
if err != nil {
|
||||
errorResponse(w, http.StatusInternalServerError, nil, err)
|
||||
errorResponse(w, http.StatusInternalServerError, "", err)
|
||||
return
|
||||
}
|
||||
|
||||
userData, err := json.Marshal(user)
|
||||
if err != nil {
|
||||
errorResponse(w, http.StatusInternalServerError, nil, err)
|
||||
errorResponse(w, http.StatusInternalServerError, "", err)
|
||||
return
|
||||
}
|
||||
|
||||
jsonStringResponse(w, http.StatusOK, string(userData))
|
||||
jsonBytesResponse(w, http.StatusOK, userData)
|
||||
}
|
||||
|
||||
func (a *API) handleGetMe(w http.ResponseWriter, r *http.Request) {
|
||||
// swagger:operation GET /api/v1/users/me getMe
|
||||
//
|
||||
// Returns the currently logged-in user
|
||||
//
|
||||
// ---
|
||||
// produces:
|
||||
// - application/json
|
||||
// security:
|
||||
// - BearerAuth: []
|
||||
// responses:
|
||||
// '200':
|
||||
// description: success
|
||||
// schema:
|
||||
// "$ref": "#/definitions/User"
|
||||
// default:
|
||||
// description: internal error
|
||||
// schema:
|
||||
// "$ref": "#/definitions/ErrorResponse"
|
||||
|
||||
ctx := r.Context()
|
||||
session := ctx.Value("session").(*model.Session)
|
||||
var user *model.User
|
||||
@ -221,21 +323,44 @@ func (a *API) handleGetMe(w http.ResponseWriter, r *http.Request) {
|
||||
} else {
|
||||
user, err = a.app().GetUser(session.UserID)
|
||||
if err != nil {
|
||||
errorResponse(w, http.StatusInternalServerError, nil, err)
|
||||
errorResponse(w, http.StatusInternalServerError, "", err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
userData, err := json.Marshal(user)
|
||||
if err != nil {
|
||||
errorResponse(w, http.StatusInternalServerError, nil, err)
|
||||
errorResponse(w, http.StatusInternalServerError, "", err)
|
||||
return
|
||||
}
|
||||
|
||||
jsonStringResponse(w, http.StatusOK, string(userData))
|
||||
jsonBytesResponse(w, http.StatusOK, userData)
|
||||
}
|
||||
|
||||
func (a *API) handleDeleteBlock(w http.ResponseWriter, r *http.Request) {
|
||||
// swagger:operation DELETE /api/v1/blocks/{blockID} deleteBlock
|
||||
//
|
||||
// Deletes a block
|
||||
//
|
||||
// ---
|
||||
// produces:
|
||||
// - application/json
|
||||
// parameters:
|
||||
// - name: blockID
|
||||
// in: path
|
||||
// description: ID of block to delete
|
||||
// required: true
|
||||
// type: string
|
||||
// security:
|
||||
// - BearerAuth: []
|
||||
// responses:
|
||||
// '200':
|
||||
// description: success
|
||||
// default:
|
||||
// description: internal error
|
||||
// schema:
|
||||
// "$ref": "#/definitions/ErrorResponse"
|
||||
|
||||
ctx := r.Context()
|
||||
session := ctx.Value("session").(*model.Session)
|
||||
userID := session.UserID
|
||||
@ -245,7 +370,7 @@ func (a *API) handleDeleteBlock(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
err := a.app().DeleteBlock(blockID, userID)
|
||||
if err != nil {
|
||||
errorResponse(w, http.StatusInternalServerError, nil, err)
|
||||
errorResponse(w, http.StatusInternalServerError, "", err)
|
||||
|
||||
return
|
||||
}
|
||||
@ -255,6 +380,40 @@ func (a *API) handleDeleteBlock(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
func (a *API) handleGetSubTree(w http.ResponseWriter, r *http.Request) {
|
||||
// swagger:operation GET /api/v1/blocks/{blockID}/subtree getSubTree
|
||||
//
|
||||
// Returns the blocks of a subtree
|
||||
//
|
||||
// ---
|
||||
// produces:
|
||||
// - application/json
|
||||
// parameters:
|
||||
// - name: blockID
|
||||
// in: path
|
||||
// description: The ID of the root block of the subtree
|
||||
// required: true
|
||||
// type: string
|
||||
// - name: l
|
||||
// in: query
|
||||
// description: The number of levels to return. 2 or 3. Defaults to 2.
|
||||
// required: false
|
||||
// type: integer
|
||||
// minimum: 2
|
||||
// maximum: 3
|
||||
// security:
|
||||
// - BearerAuth: []
|
||||
// responses:
|
||||
// '200':
|
||||
// description: success
|
||||
// schema:
|
||||
// type: array
|
||||
// items:
|
||||
// "$ref": "#/definitions/Block"
|
||||
// default:
|
||||
// description: internal error
|
||||
// schema:
|
||||
// "$ref": "#/definitions/ErrorResponse"
|
||||
|
||||
vars := mux.Vars(r)
|
||||
blockID := vars["blockID"]
|
||||
|
||||
@ -267,18 +426,18 @@ func (a *API) handleGetSubTree(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
// Require read token
|
||||
if len(readToken) < 1 {
|
||||
errorResponse(w, http.StatusUnauthorized, map[string]string{"error": "No read_token"}, nil)
|
||||
errorResponse(w, http.StatusBadRequest, "No read_token", nil)
|
||||
return
|
||||
}
|
||||
|
||||
isValid, err := a.app().IsValidReadToken(blockID, readToken)
|
||||
if err != nil {
|
||||
errorResponse(w, http.StatusInternalServerError, nil, err)
|
||||
errorResponse(w, http.StatusInternalServerError, "", err)
|
||||
return
|
||||
}
|
||||
|
||||
if !isValid {
|
||||
errorResponse(w, http.StatusUnauthorized, nil, nil)
|
||||
errorResponse(w, http.StatusUnauthorized, "", nil)
|
||||
return
|
||||
}
|
||||
}
|
||||
@ -291,21 +450,20 @@ func (a *API) handleGetSubTree(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
if levels != 2 && levels != 3 {
|
||||
log.Printf(`ERROR Invalid levels: %d`, levels)
|
||||
errorData := map[string]string{"description": "invalid levels"}
|
||||
errorResponse(w, http.StatusInternalServerError, errorData, nil)
|
||||
errorResponse(w, http.StatusBadRequest, "invalid levels", nil)
|
||||
return
|
||||
}
|
||||
|
||||
blocks, err := a.app().GetSubTree(blockID, int(levels))
|
||||
if err != nil {
|
||||
errorResponse(w, http.StatusInternalServerError, nil, err)
|
||||
errorResponse(w, http.StatusInternalServerError, "", err)
|
||||
return
|
||||
}
|
||||
|
||||
log.Printf("GetSubTree (%v) blockID: %s, %d result(s)", levels, blockID, len(blocks))
|
||||
json, err := json.Marshal(blocks)
|
||||
if err != nil {
|
||||
errorResponse(w, http.StatusInternalServerError, nil, err)
|
||||
errorResponse(w, http.StatusInternalServerError, "", err)
|
||||
return
|
||||
}
|
||||
|
||||
@ -313,9 +471,30 @@ func (a *API) handleGetSubTree(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
func (a *API) handleExport(w http.ResponseWriter, r *http.Request) {
|
||||
// swagger:operation GET /api/v1/blocks/export exportBlocks
|
||||
//
|
||||
// Returns all blocks
|
||||
//
|
||||
// ---
|
||||
// produces:
|
||||
// - application/json
|
||||
// security:
|
||||
// - BearerAuth: []
|
||||
// responses:
|
||||
// '200':
|
||||
// description: success
|
||||
// schema:
|
||||
// type: array
|
||||
// items:
|
||||
// "$ref": "#/definitions/Block"
|
||||
// default:
|
||||
// description: internal error
|
||||
// schema:
|
||||
// "$ref": "#/definitions/ErrorResponse"
|
||||
|
||||
blocks, err := a.app().GetAllBlocks()
|
||||
if err != nil {
|
||||
errorResponse(w, http.StatusInternalServerError, nil, err)
|
||||
errorResponse(w, http.StatusInternalServerError, "", err)
|
||||
return
|
||||
}
|
||||
|
||||
@ -325,7 +504,7 @@ func (a *API) handleExport(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
json, err := json.Marshal(blocks)
|
||||
if err != nil {
|
||||
errorResponse(w, http.StatusInternalServerError, nil, err)
|
||||
errorResponse(w, http.StatusInternalServerError, "", err)
|
||||
return
|
||||
}
|
||||
|
||||
@ -377,9 +556,35 @@ func arrayContainsBlockWithID(array []model.Block, blockID string) bool {
|
||||
}
|
||||
|
||||
func (a *API) handleImport(w http.ResponseWriter, r *http.Request) {
|
||||
// swagger:operation POST /api/v1/blocks/import importBlocks
|
||||
//
|
||||
// Import blocks
|
||||
//
|
||||
// ---
|
||||
// produces:
|
||||
// - application/json
|
||||
// parameters:
|
||||
// - name: Body
|
||||
// in: body
|
||||
// description: array of blocks to import
|
||||
// required: true
|
||||
// schema:
|
||||
// type: array
|
||||
// items:
|
||||
// "$ref": "#/definitions/Block"
|
||||
// security:
|
||||
// - BearerAuth: []
|
||||
// responses:
|
||||
// '200':
|
||||
// description: success
|
||||
// default:
|
||||
// description: internal error
|
||||
// schema:
|
||||
// "$ref": "#/definitions/ErrorResponse"
|
||||
|
||||
requestBody, err := ioutil.ReadAll(r.Body)
|
||||
if err != nil {
|
||||
errorResponse(w, http.StatusInternalServerError, nil, err)
|
||||
errorResponse(w, http.StatusInternalServerError, "", err)
|
||||
return
|
||||
}
|
||||
|
||||
@ -387,8 +592,7 @@ func (a *API) handleImport(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
err = json.Unmarshal(requestBody, &blocks)
|
||||
if err != nil {
|
||||
errorResponse(w, http.StatusInternalServerError, nil, err)
|
||||
|
||||
errorResponse(w, http.StatusInternalServerError, "", err)
|
||||
return
|
||||
}
|
||||
|
||||
@ -396,8 +600,7 @@ func (a *API) handleImport(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
err = a.app().InsertBlocks(blocks)
|
||||
if err != nil {
|
||||
errorResponse(w, http.StatusInternalServerError, nil, err)
|
||||
|
||||
errorResponse(w, http.StatusInternalServerError, "", err)
|
||||
return
|
||||
}
|
||||
|
||||
@ -408,29 +611,83 @@ func (a *API) handleImport(w http.ResponseWriter, r *http.Request) {
|
||||
// Sharing
|
||||
|
||||
func (a *API) handleGetSharing(w http.ResponseWriter, r *http.Request) {
|
||||
// swagger:operation GET /api/v1/sharing/{rootID} getSharing
|
||||
//
|
||||
// Returns sharing information for a root block
|
||||
//
|
||||
// ---
|
||||
// produces:
|
||||
// - application/json
|
||||
// parameters:
|
||||
// - name: rootID
|
||||
// in: path
|
||||
// description: ID of the root block
|
||||
// required: true
|
||||
// type: string
|
||||
// security:
|
||||
// - BearerAuth: []
|
||||
// responses:
|
||||
// '200':
|
||||
// description: success
|
||||
// schema:
|
||||
// "$ref": "#/definitions/Sharing"
|
||||
// default:
|
||||
// description: internal error
|
||||
// schema:
|
||||
// "$ref": "#/definitions/ErrorResponse"
|
||||
|
||||
vars := mux.Vars(r)
|
||||
rootID := vars["rootID"]
|
||||
|
||||
sharing, err := a.app().GetSharing(rootID)
|
||||
if err != nil {
|
||||
errorResponse(w, http.StatusInternalServerError, nil, err)
|
||||
errorResponse(w, http.StatusInternalServerError, "", err)
|
||||
return
|
||||
}
|
||||
|
||||
sharingData, err := json.Marshal(sharing)
|
||||
if err != nil {
|
||||
errorResponse(w, http.StatusInternalServerError, nil, err)
|
||||
errorResponse(w, http.StatusInternalServerError, "", err)
|
||||
return
|
||||
}
|
||||
|
||||
log.Printf("GET sharing %s", rootID)
|
||||
jsonStringResponse(w, http.StatusOK, string(sharingData))
|
||||
jsonBytesResponse(w, http.StatusOK, sharingData)
|
||||
}
|
||||
|
||||
func (a *API) handlePostSharing(w http.ResponseWriter, r *http.Request) {
|
||||
// swagger:operation POST /api/v1/sharing/{rootID} postSharing
|
||||
//
|
||||
// Sets sharing information for a root block
|
||||
//
|
||||
// ---
|
||||
// produces:
|
||||
// - application/json
|
||||
// parameters:
|
||||
// - name: rootID
|
||||
// in: path
|
||||
// description: ID of the root block
|
||||
// required: true
|
||||
// type: string
|
||||
// - name: Body
|
||||
// in: body
|
||||
// description: sharing information for a root block
|
||||
// required: true
|
||||
// schema:
|
||||
// "$ref": "#/definitions/Sharing"
|
||||
// security:
|
||||
// - BearerAuth: []
|
||||
// responses:
|
||||
// '200':
|
||||
// description: success
|
||||
// default:
|
||||
// description: internal error
|
||||
// schema:
|
||||
// "$ref": "#/definitions/ErrorResponse"
|
||||
|
||||
requestBody, err := ioutil.ReadAll(r.Body)
|
||||
if err != nil {
|
||||
errorResponse(w, http.StatusInternalServerError, nil, err)
|
||||
errorResponse(w, http.StatusInternalServerError, "", err)
|
||||
return
|
||||
}
|
||||
|
||||
@ -438,7 +695,7 @@ func (a *API) handlePostSharing(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
err = json.Unmarshal(requestBody, &sharing)
|
||||
if err != nil {
|
||||
errorResponse(w, http.StatusInternalServerError, nil, err)
|
||||
errorResponse(w, http.StatusInternalServerError, "", err)
|
||||
return
|
||||
}
|
||||
|
||||
@ -453,7 +710,7 @@ func (a *API) handlePostSharing(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
err = a.app().UpsertSharing(sharing)
|
||||
if err != nil {
|
||||
errorResponse(w, http.StatusInternalServerError, nil, err)
|
||||
errorResponse(w, http.StatusInternalServerError, "", err)
|
||||
return
|
||||
}
|
||||
|
||||
@ -464,25 +721,61 @@ func (a *API) handlePostSharing(w http.ResponseWriter, r *http.Request) {
|
||||
// Workspace
|
||||
|
||||
func (a *API) handleGetWorkspace(w http.ResponseWriter, r *http.Request) {
|
||||
// swagger:operation GET /api/v1/workspace getWorkspace
|
||||
//
|
||||
// Returns information of the root workspace
|
||||
//
|
||||
// ---
|
||||
// produces:
|
||||
// - application/json
|
||||
// security:
|
||||
// - BearerAuth: []
|
||||
// responses:
|
||||
// '200':
|
||||
// description: success
|
||||
// schema:
|
||||
// "$ref": "#/definitions/Workspace"
|
||||
// default:
|
||||
// description: internal error
|
||||
// schema:
|
||||
// "$ref": "#/definitions/ErrorResponse"
|
||||
|
||||
workspace, err := a.app().GetRootWorkspace()
|
||||
if err != nil {
|
||||
errorResponse(w, http.StatusInternalServerError, nil, err)
|
||||
errorResponse(w, http.StatusInternalServerError, "", err)
|
||||
return
|
||||
}
|
||||
|
||||
workspaceData, err := json.Marshal(workspace)
|
||||
if err != nil {
|
||||
errorResponse(w, http.StatusInternalServerError, nil, err)
|
||||
errorResponse(w, http.StatusInternalServerError, "", err)
|
||||
return
|
||||
}
|
||||
|
||||
jsonStringResponse(w, http.StatusOK, string(workspaceData))
|
||||
jsonBytesResponse(w, http.StatusOK, workspaceData)
|
||||
}
|
||||
|
||||
func (a *API) handlePostWorkspaceRegenerateSignupToken(w http.ResponseWriter, r *http.Request) {
|
||||
// swagger:operation POST /api/v1/workspace/regenerate_signup_token regenerateSignupToken
|
||||
//
|
||||
// Regenerates the signup token for the root workspace
|
||||
//
|
||||
// ---
|
||||
// produces:
|
||||
// - application/json
|
||||
// security:
|
||||
// - BearerAuth: []
|
||||
// responses:
|
||||
// '200':
|
||||
// description: success
|
||||
// default:
|
||||
// description: internal error
|
||||
// schema:
|
||||
// "$ref": "#/definitions/ErrorResponse"
|
||||
|
||||
workspace, err := a.app().GetRootWorkspace()
|
||||
if err != nil {
|
||||
errorResponse(w, http.StatusInternalServerError, nil, err)
|
||||
errorResponse(w, http.StatusInternalServerError, "", err)
|
||||
return
|
||||
}
|
||||
|
||||
@ -490,7 +783,7 @@ func (a *API) handlePostWorkspaceRegenerateSignupToken(w http.ResponseWriter, r
|
||||
|
||||
err = a.app().UpsertWorkspaceSignupToken(*workspace)
|
||||
if err != nil {
|
||||
errorResponse(w, http.StatusInternalServerError, nil, err)
|
||||
errorResponse(w, http.StatusInternalServerError, "", err)
|
||||
return
|
||||
}
|
||||
|
||||
@ -500,6 +793,31 @@ func (a *API) handlePostWorkspaceRegenerateSignupToken(w http.ResponseWriter, r
|
||||
// File upload
|
||||
|
||||
func (a *API) handleServeFile(w http.ResponseWriter, r *http.Request) {
|
||||
// swagger:operation GET /files/{fileID} getFile
|
||||
//
|
||||
// Returns the contents of an uploaded file
|
||||
//
|
||||
// ---
|
||||
// produces:
|
||||
// - application/json
|
||||
// - image/jpg
|
||||
// - image/png
|
||||
// parameters:
|
||||
// - name: fileID
|
||||
// in: path
|
||||
// description: ID of the file
|
||||
// required: true
|
||||
// type: string
|
||||
// security:
|
||||
// - BearerAuth: []
|
||||
// responses:
|
||||
// '200':
|
||||
// description: success
|
||||
// default:
|
||||
// description: internal error
|
||||
// schema:
|
||||
// "$ref": "#/definitions/ErrorResponse"
|
||||
|
||||
vars := mux.Vars(r)
|
||||
filename := vars["filename"]
|
||||
|
||||
@ -516,8 +834,40 @@ func (a *API) handleServeFile(w http.ResponseWriter, r *http.Request) {
|
||||
http.ServeFile(w, r, filePath)
|
||||
}
|
||||
|
||||
// FileUploadResponse is the response to a file upload
|
||||
// swagger:model
|
||||
type FileUploadResponse struct {
|
||||
// The URL to retrieve the uploaded file
|
||||
// required: true
|
||||
URL string `json:"url"`
|
||||
}
|
||||
|
||||
func (a *API) handleUploadFile(w http.ResponseWriter, r *http.Request) {
|
||||
fmt.Println(`handleUploadFile`)
|
||||
// swagger:operation POST /api/v1/files uploadFile
|
||||
//
|
||||
// Upload a binary file
|
||||
//
|
||||
// ---
|
||||
// consumes:
|
||||
// - multipart/form-data
|
||||
// produces:
|
||||
// - application/json
|
||||
// parameters:
|
||||
// - name: uploaded file
|
||||
// in: formData
|
||||
// type: file
|
||||
// description: The file to upload
|
||||
// security:
|
||||
// - BearerAuth: []
|
||||
// responses:
|
||||
// '200':
|
||||
// description: success
|
||||
// schema:
|
||||
// "$ref": "#/definitions/FileUploadResponse"
|
||||
// default:
|
||||
// description: internal error
|
||||
// schema:
|
||||
// "$ref": "#/definitions/ErrorResponse"
|
||||
|
||||
file, handle, err := r.FormFile("file")
|
||||
if err != nil {
|
||||
@ -527,18 +877,20 @@ func (a *API) handleUploadFile(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
log.Printf(`handleUploadFile, filename: %s`, handle.Filename)
|
||||
|
||||
url, err := a.app().SaveFile(file, handle.Filename)
|
||||
if err != nil {
|
||||
jsonStringResponse(w, http.StatusInternalServerError, `{}`)
|
||||
|
||||
errorResponse(w, http.StatusInternalServerError, "", err)
|
||||
return
|
||||
}
|
||||
|
||||
log.Printf(`saveFile, url: %s`, url)
|
||||
json := fmt.Sprintf(`{ "url": "%s" }`, url)
|
||||
jsonStringResponse(w, http.StatusOK, json)
|
||||
log.Printf("uploadFile, filename: %s, url: %s", handle.Filename, url)
|
||||
data, err := json.Marshal(FileUploadResponse{URL: url})
|
||||
if err != nil {
|
||||
errorResponse(w, http.StatusInternalServerError, "", err)
|
||||
return
|
||||
}
|
||||
|
||||
jsonBytesResponse(w, http.StatusOK, data)
|
||||
}
|
||||
|
||||
// Response helpers
|
||||
@ -555,10 +907,10 @@ func jsonBytesResponse(w http.ResponseWriter, code int, json []byte) {
|
||||
w.Write(json)
|
||||
}
|
||||
|
||||
func errorResponse(w http.ResponseWriter, code int, message map[string]string, sourceError error) {
|
||||
func errorResponse(w http.ResponseWriter, code int, message string, sourceError error) {
|
||||
log.Printf("API ERROR %d, err: %v\n", code, sourceError)
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
data, err := json.Marshal(message)
|
||||
data, err := json.Marshal(model.ErrorResponse{Error: message})
|
||||
if err != nil {
|
||||
data = []byte("{}")
|
||||
}
|
||||
|
@ -17,22 +17,60 @@ import (
|
||||
"github.com/mattermost/focalboard/server/services/auth"
|
||||
)
|
||||
|
||||
type LoginData struct {
|
||||
// LoginRequest is a login request
|
||||
// swagger:model
|
||||
type LoginRequest struct {
|
||||
// Type of login, currently must be set to "normal"
|
||||
// required: true
|
||||
Type string `json:"type"`
|
||||
|
||||
// If specified, login using username
|
||||
// required: false
|
||||
Username string `json:"username"`
|
||||
|
||||
// If specified, login using email
|
||||
// required: false
|
||||
Email string `json:"email"`
|
||||
|
||||
// Password
|
||||
// required: true
|
||||
Password string `json:"password"`
|
||||
|
||||
// MFA token
|
||||
// required: false
|
||||
// swagger:ignore
|
||||
MfaToken string `json:"mfa_token"`
|
||||
}
|
||||
|
||||
type RegisterData struct {
|
||||
Username string `json:"username"`
|
||||
Email string `json:"email"`
|
||||
Password string `json:"password"`
|
||||
// LoginResponse is a login response
|
||||
// swagger:model
|
||||
type LoginResponse struct {
|
||||
// Session token
|
||||
// required: true
|
||||
Token string `json:"token"`
|
||||
}
|
||||
|
||||
func (rd *RegisterData) IsValid() error {
|
||||
// RegisterRequest is a user registration request
|
||||
// swagger:model
|
||||
type RegisterRequest struct {
|
||||
// User name
|
||||
// required: true
|
||||
Username string `json:"username"`
|
||||
|
||||
// User's email
|
||||
// required: true
|
||||
Email string `json:"email"`
|
||||
|
||||
// Password
|
||||
// required: true
|
||||
Password string `json:"password"`
|
||||
|
||||
// Registration authorization token
|
||||
// required: true
|
||||
Token string `json:"token"`
|
||||
}
|
||||
|
||||
func (rd *RegisterRequest) IsValid() error {
|
||||
if rd.Username == "" {
|
||||
return errors.New("Username is required")
|
||||
}
|
||||
@ -51,12 +89,20 @@ func (rd *RegisterData) IsValid() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
type ChangePasswordData struct {
|
||||
// ChangePasswordRequest is a user password change request
|
||||
// swagger:model
|
||||
type ChangePasswordRequest struct {
|
||||
// Old password
|
||||
// required: true
|
||||
OldPassword string `json:"oldPassword"`
|
||||
|
||||
// New password
|
||||
// required: true
|
||||
NewPassword string `json:"newPassword"`
|
||||
}
|
||||
|
||||
func (rd *ChangePasswordData) IsValid() error {
|
||||
// IsValid validates a password change request
|
||||
func (rd *ChangePasswordRequest) IsValid() error {
|
||||
if rd.OldPassword == "" {
|
||||
return errors.New("Old password is required")
|
||||
}
|
||||
@ -78,34 +124,62 @@ func isValidPassword(password string) error {
|
||||
}
|
||||
|
||||
func (a *API) handleLogin(w http.ResponseWriter, r *http.Request) {
|
||||
// swagger:operation POST /api/v1/login login
|
||||
//
|
||||
// Login user
|
||||
//
|
||||
// ---
|
||||
// produces:
|
||||
// - application/json
|
||||
// parameters:
|
||||
// - name: body
|
||||
// in: body
|
||||
// description: Login request
|
||||
// required: true
|
||||
// schema:
|
||||
// "$ref": "#/definitions/LoginRequest"
|
||||
// responses:
|
||||
// '200':
|
||||
// description: success
|
||||
// schema:
|
||||
// "$ref": "#/definitions/LoginResponse"
|
||||
// '401':
|
||||
// description: invalid login
|
||||
// schema:
|
||||
// "$ref": "#/definitions/ErrorResponse"
|
||||
// '500':
|
||||
// description: internal error
|
||||
// schema:
|
||||
// "$ref": "#/definitions/ErrorResponse"
|
||||
|
||||
if len(a.singleUserToken) > 0 {
|
||||
// Not permitted in single-user mode
|
||||
errorResponse(w, http.StatusUnauthorized, nil, nil)
|
||||
errorResponse(w, http.StatusUnauthorized, "", nil)
|
||||
return
|
||||
}
|
||||
|
||||
requestBody, err := ioutil.ReadAll(r.Body)
|
||||
if err != nil {
|
||||
errorResponse(w, http.StatusInternalServerError, nil, err)
|
||||
errorResponse(w, http.StatusInternalServerError, "", err)
|
||||
return
|
||||
}
|
||||
|
||||
var loginData LoginData
|
||||
var loginData LoginRequest
|
||||
err = json.Unmarshal(requestBody, &loginData)
|
||||
if err != nil {
|
||||
errorResponse(w, http.StatusInternalServerError, nil, err)
|
||||
errorResponse(w, http.StatusInternalServerError, "", err)
|
||||
return
|
||||
}
|
||||
|
||||
if loginData.Type == "normal" {
|
||||
token, err := a.app().Login(loginData.Username, loginData.Email, loginData.Password, loginData.MfaToken)
|
||||
if err != nil {
|
||||
errorResponse(w, http.StatusInternalServerError, map[string]string{"error": err.Error()}, err)
|
||||
errorResponse(w, http.StatusUnauthorized, "incorrect login", err)
|
||||
return
|
||||
}
|
||||
json, err := json.Marshal(map[string]string{"token": token})
|
||||
json, err := json.Marshal(LoginResponse{Token: token})
|
||||
if err != nil {
|
||||
errorResponse(w, http.StatusInternalServerError, nil, err)
|
||||
errorResponse(w, http.StatusInternalServerError, "", err)
|
||||
return
|
||||
}
|
||||
|
||||
@ -113,26 +187,50 @@ func (a *API) handleLogin(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
errorResponse(w, http.StatusInternalServerError, map[string]string{"error": "Unknown login type"}, nil)
|
||||
errorResponse(w, http.StatusBadRequest, "invalid login type", nil)
|
||||
}
|
||||
|
||||
func (a *API) handleRegister(w http.ResponseWriter, r *http.Request) {
|
||||
// swagger:operation POST /api/v1/register register
|
||||
//
|
||||
// Register new user
|
||||
//
|
||||
// ---
|
||||
// produces:
|
||||
// - application/json
|
||||
// parameters:
|
||||
// - name: body
|
||||
// in: body
|
||||
// description: Register request
|
||||
// required: true
|
||||
// schema:
|
||||
// "$ref": "#/definitions/RegisterRequest"
|
||||
// responses:
|
||||
// '200':
|
||||
// description: success
|
||||
// '401':
|
||||
// description: invalid registration token
|
||||
// '500':
|
||||
// description: internal error
|
||||
// schema:
|
||||
// "$ref": "#/definitions/ErrorResponse"
|
||||
|
||||
if len(a.singleUserToken) > 0 {
|
||||
// Not permitted in single-user mode
|
||||
errorResponse(w, http.StatusUnauthorized, nil, nil)
|
||||
errorResponse(w, http.StatusUnauthorized, "", nil)
|
||||
return
|
||||
}
|
||||
|
||||
requestBody, err := ioutil.ReadAll(r.Body)
|
||||
if err != nil {
|
||||
errorResponse(w, http.StatusInternalServerError, nil, err)
|
||||
errorResponse(w, http.StatusInternalServerError, "", err)
|
||||
return
|
||||
}
|
||||
|
||||
var registerData RegisterData
|
||||
var registerData RegisterRequest
|
||||
err = json.Unmarshal(requestBody, ®isterData)
|
||||
if err != nil {
|
||||
errorResponse(w, http.StatusInternalServerError, nil, err)
|
||||
errorResponse(w, http.StatusInternalServerError, "", err)
|
||||
return
|
||||
}
|
||||
|
||||
@ -140,45 +238,78 @@ func (a *API) handleRegister(w http.ResponseWriter, r *http.Request) {
|
||||
if len(registerData.Token) > 0 {
|
||||
workspace, err := a.app().GetRootWorkspace()
|
||||
if err != nil {
|
||||
errorResponse(w, http.StatusInternalServerError, nil, err)
|
||||
errorResponse(w, http.StatusInternalServerError, "", err)
|
||||
return
|
||||
}
|
||||
|
||||
if registerData.Token != workspace.SignupToken {
|
||||
errorResponse(w, http.StatusUnauthorized, nil, nil)
|
||||
errorResponse(w, http.StatusUnauthorized, "", nil)
|
||||
return
|
||||
}
|
||||
} else {
|
||||
// No signup token, check if no active users
|
||||
userCount, err := a.app().GetRegisteredUserCount()
|
||||
if err != nil {
|
||||
errorResponse(w, http.StatusInternalServerError, nil, err)
|
||||
errorResponse(w, http.StatusInternalServerError, "", err)
|
||||
return
|
||||
}
|
||||
if userCount > 0 {
|
||||
errorResponse(w, http.StatusUnauthorized, nil, nil)
|
||||
errorResponse(w, http.StatusUnauthorized, "", nil)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if err = registerData.IsValid(); err != nil {
|
||||
errorResponse(w, http.StatusInternalServerError, map[string]string{"error": err.Error()}, err)
|
||||
errorResponse(w, http.StatusBadRequest, err.Error(), err)
|
||||
return
|
||||
}
|
||||
|
||||
err = a.app().RegisterUser(registerData.Username, registerData.Email, registerData.Password)
|
||||
if err != nil {
|
||||
errorResponse(w, http.StatusInternalServerError, map[string]string{"error": err.Error()}, err)
|
||||
errorResponse(w, http.StatusBadRequest, err.Error(), err)
|
||||
return
|
||||
}
|
||||
|
||||
jsonBytesResponse(w, http.StatusOK, nil)
|
||||
jsonStringResponse(w, http.StatusOK, "{}")
|
||||
}
|
||||
|
||||
func (a *API) handleChangePassword(w http.ResponseWriter, r *http.Request) {
|
||||
// swagger:operation POST /api/v1/users/{userID}/changepassword changePassword
|
||||
//
|
||||
// Change a user's password
|
||||
//
|
||||
// ---
|
||||
// produces:
|
||||
// - application/json
|
||||
// parameters:
|
||||
// - name: userID
|
||||
// in: path
|
||||
// description: User ID
|
||||
// required: true
|
||||
// type: string
|
||||
// - name: body
|
||||
// in: body
|
||||
// description: Change password request
|
||||
// required: true
|
||||
// schema:
|
||||
// "$ref": "#/definitions/ChangePasswordRequest"
|
||||
// security:
|
||||
// - BearerAuth: []
|
||||
// responses:
|
||||
// '200':
|
||||
// description: success
|
||||
// '400':
|
||||
// description: invalid request
|
||||
// schema:
|
||||
// "$ref": "#/definitions/ErrorResponse"
|
||||
// '500':
|
||||
// description: internal error
|
||||
// schema:
|
||||
// "$ref": "#/definitions/ErrorResponse"
|
||||
|
||||
if len(a.singleUserToken) > 0 {
|
||||
// Not permitted in single-user mode
|
||||
errorResponse(w, http.StatusUnauthorized, nil, nil)
|
||||
errorResponse(w, http.StatusUnauthorized, "", nil)
|
||||
return
|
||||
}
|
||||
|
||||
@ -187,27 +318,27 @@ func (a *API) handleChangePassword(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
requestBody, err := ioutil.ReadAll(r.Body)
|
||||
if err != nil {
|
||||
errorResponse(w, http.StatusInternalServerError, nil, err)
|
||||
errorResponse(w, http.StatusInternalServerError, "", err)
|
||||
return
|
||||
}
|
||||
|
||||
var requestData ChangePasswordData
|
||||
var requestData ChangePasswordRequest
|
||||
if err := json.Unmarshal(requestBody, &requestData); err != nil {
|
||||
errorResponse(w, http.StatusInternalServerError, nil, err)
|
||||
errorResponse(w, http.StatusInternalServerError, "", err)
|
||||
return
|
||||
}
|
||||
|
||||
if err = requestData.IsValid(); err != nil {
|
||||
errorResponse(w, http.StatusInternalServerError, map[string]string{"error": err.Error()}, err)
|
||||
errorResponse(w, http.StatusBadRequest, err.Error(), err)
|
||||
return
|
||||
}
|
||||
|
||||
if err = a.app().ChangePassword(userID, requestData.OldPassword, requestData.NewPassword); err != nil {
|
||||
errorResponse(w, http.StatusInternalServerError, map[string]string{"error": err.Error()}, err)
|
||||
errorResponse(w, http.StatusBadRequest, err.Error(), err)
|
||||
return
|
||||
}
|
||||
|
||||
jsonBytesResponse(w, http.StatusOK, nil)
|
||||
jsonStringResponse(w, http.StatusOK, "{}")
|
||||
}
|
||||
|
||||
func (a *API) sessionRequired(handler func(w http.ResponseWriter, r *http.Request)) func(w http.ResponseWriter, r *http.Request) {
|
||||
@ -221,7 +352,7 @@ func (a *API) attachSession(handler func(w http.ResponseWriter, r *http.Request)
|
||||
log.Printf(`Single User: %v`, len(a.singleUserToken) > 0)
|
||||
if len(a.singleUserToken) > 0 {
|
||||
if required && (token != a.singleUserToken) {
|
||||
errorResponse(w, http.StatusUnauthorized, nil, nil)
|
||||
errorResponse(w, http.StatusUnauthorized, "", nil)
|
||||
return
|
||||
}
|
||||
|
||||
@ -241,7 +372,7 @@ func (a *API) attachSession(handler func(w http.ResponseWriter, r *http.Request)
|
||||
session, err := a.app().GetSession(token)
|
||||
if err != nil {
|
||||
if required {
|
||||
errorResponse(w, http.StatusUnauthorized, nil, err)
|
||||
errorResponse(w, http.StatusUnauthorized, "", err)
|
||||
return
|
||||
}
|
||||
|
||||
@ -258,7 +389,7 @@ func (a *API) adminRequired(handler func(w http.ResponseWriter, r *http.Request)
|
||||
// Currently, admin APIs require local unix connections
|
||||
conn := serverContext.GetContextConn(r)
|
||||
if _, isUnix := conn.(*net.UnixConn); !isUnix {
|
||||
errorResponse(w, http.StatusUnauthorized, nil, nil)
|
||||
errorResponse(w, http.StatusUnauthorized, "", nil)
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -1,3 +1,28 @@
|
||||
// Package classification Focalboard Server
|
||||
//
|
||||
// Server for Focalboard
|
||||
//
|
||||
// Schemes: http, https
|
||||
// Host: localhost
|
||||
// BasePath: /api/v1
|
||||
// Version: 0.5.0
|
||||
// License: Custom https://github.com/mattermost/focalboard/blob/main/LICENSE.txt
|
||||
// Contact: Focalboard<api@focalboard.com> https://www.focalboard.com
|
||||
//
|
||||
// Consumes:
|
||||
// - application/json
|
||||
//
|
||||
// Produces:
|
||||
// - application/json
|
||||
//
|
||||
// securityDefinitions:
|
||||
// BearerAuth:
|
||||
// type: apiKey
|
||||
// name: Authorization
|
||||
// in: header
|
||||
// description: 'Pass session token using Bearer authentication, e.g. set header "Authorization: Bearer <session token>"'
|
||||
//
|
||||
// swagger:meta
|
||||
package main
|
||||
|
||||
import (
|
||||
|
@ -5,18 +5,51 @@ import (
|
||||
"io"
|
||||
)
|
||||
|
||||
// Block is the basic data unit.
|
||||
// Block is the basic data unit
|
||||
// swagger:model
|
||||
type Block struct {
|
||||
// The id for this block
|
||||
// required: true
|
||||
ID string `json:"id"`
|
||||
|
||||
// The id for this block's parent block. Empty for root blocks
|
||||
// required: false
|
||||
ParentID string `json:"parentId"`
|
||||
|
||||
// The id for this block's root block
|
||||
// required: true
|
||||
RootID string `json:"rootId"`
|
||||
|
||||
// The id for user who last modified this block
|
||||
// required: true
|
||||
ModifiedBy string `json:"modifiedBy"`
|
||||
|
||||
// The schema version of this block
|
||||
// required: true
|
||||
Schema int64 `json:"schema"`
|
||||
|
||||
// The block type
|
||||
// required: true
|
||||
Type string `json:"type"`
|
||||
|
||||
// The display title
|
||||
// required: false
|
||||
Title string `json:"title"`
|
||||
|
||||
// The block fields
|
||||
// required: false
|
||||
Fields map[string]interface{} `json:"fields"`
|
||||
|
||||
// The creation time
|
||||
// required: true
|
||||
CreateAt int64 `json:"createAt"`
|
||||
|
||||
// The last modified time
|
||||
// required: true
|
||||
UpdateAt int64 `json:"updateAt"`
|
||||
|
||||
// The deleted time. Set to indicate this block is deleted
|
||||
// required: false
|
||||
DeleteAt int64 `json:"deleteAt"`
|
||||
}
|
||||
|
||||
|
9
server/model/errorResponse.go
Normal file
9
server/model/errorResponse.go
Normal file
@ -0,0 +1,9 @@
|
||||
package model
|
||||
|
||||
// ErrorResponse is an error response
|
||||
// swagger:model
|
||||
type ErrorResponse struct {
|
||||
// The error message
|
||||
// required: false
|
||||
Error string `json:"error"`
|
||||
}
|
@ -5,11 +5,27 @@ import (
|
||||
"io"
|
||||
)
|
||||
|
||||
// Sharing is sharing information for a root block
|
||||
// swagger:model
|
||||
type Sharing struct {
|
||||
// ID of the root block
|
||||
// required: true
|
||||
ID string `json:"id"`
|
||||
|
||||
// Is sharing enabled
|
||||
// required: true
|
||||
Enabled bool `json:"enabled"`
|
||||
|
||||
// Access token
|
||||
// required: true
|
||||
Token string `json:"token"`
|
||||
|
||||
// ID of the user who last modified this
|
||||
// required: true
|
||||
ModifiedBy string `json:"modifiedBy"`
|
||||
|
||||
// Updated time
|
||||
// required: true
|
||||
UpdateAt int64 `json:"update_at,omitempty"`
|
||||
}
|
||||
|
||||
|
@ -1,16 +1,46 @@
|
||||
package model
|
||||
|
||||
// User is a user
|
||||
// swagger:model
|
||||
type User struct {
|
||||
// The user ID
|
||||
// required: true
|
||||
ID string `json:"id"`
|
||||
|
||||
// The user name
|
||||
// required: true
|
||||
Username string `json:"username"`
|
||||
|
||||
// The user's email
|
||||
// required: true
|
||||
Email string `json:"email"`
|
||||
|
||||
// swagger:ignore
|
||||
Password string `json:"-"`
|
||||
|
||||
// swagger:ignore
|
||||
MfaSecret string `json:"-"`
|
||||
|
||||
// swagger:ignore
|
||||
AuthService string `json:"-"`
|
||||
|
||||
// swagger:ignore
|
||||
AuthData string `json:"-"`
|
||||
|
||||
// User settings
|
||||
// required: true
|
||||
Props map[string]interface{} `json:"props"`
|
||||
|
||||
// Created time
|
||||
// required: true
|
||||
CreateAt int64 `json:"create_at,omitempty"`
|
||||
|
||||
// Updated time
|
||||
// required: true
|
||||
UpdateAt int64 `json:"update_at,omitempty"`
|
||||
|
||||
// Deleted time, set to indicate user is deleted
|
||||
// required: true
|
||||
DeleteAt int64 `json:"delete_at"`
|
||||
}
|
||||
|
||||
|
@ -1,9 +1,25 @@
|
||||
package model
|
||||
|
||||
// Workspace is information global to a workspace
|
||||
// swagger:model
|
||||
type Workspace struct {
|
||||
// ID of the workspace
|
||||
// required: true
|
||||
ID string `json:"id"`
|
||||
|
||||
// Token required to register new users
|
||||
// required: true
|
||||
SignupToken string `json:"signupToken"`
|
||||
|
||||
// Workspace settings
|
||||
// required: false
|
||||
Settings map[string]interface{} `json:"settings"`
|
||||
|
||||
// ID of user who last modified this
|
||||
// required: true
|
||||
ModifiedBy string `json:"modifiedBy"`
|
||||
|
||||
// Updated time
|
||||
// required: true
|
||||
UpdateAt int64 `json:"updateAt"`
|
||||
}
|
||||
|
14
server/swagger/README.md
Normal file
14
server/swagger/README.md
Normal file
@ -0,0 +1,14 @@
|
||||
# Swagger / OpenAPI 2.0 auto-generated files
|
||||
|
||||
This folder is generated by the `make swagger` command from comments in the server code.
|
||||
|
||||
Prerequisites:
|
||||
1. [go-swagger](https://goswagger.io/install.html)
|
||||
2. [openapi-generator](https://github.com/OpenAPITools/openapi-generator)
|
||||
|
||||
These can be installed via Homebrew:
|
||||
```
|
||||
brew tap go-swagger/go-swagger
|
||||
brew install go-swagger
|
||||
brew install openapi-generator
|
||||
```
|
23
server/swagger/docs/html/.openapi-generator-ignore
Normal file
23
server/swagger/docs/html/.openapi-generator-ignore
Normal file
@ -0,0 +1,23 @@
|
||||
# OpenAPI Generator Ignore
|
||||
# Generated by openapi-generator https://github.com/openapitools/openapi-generator
|
||||
|
||||
# Use this file to prevent files from being overwritten by the generator.
|
||||
# The patterns follow closely to .gitignore or .dockerignore.
|
||||
|
||||
# As an example, the C# client generator defines ApiClient.cs.
|
||||
# You can make changes and tell OpenAPI Generator to ignore just this file by uncommenting the following line:
|
||||
#ApiClient.cs
|
||||
|
||||
# You can match any string of characters against a directory, file or extension with a single asterisk (*):
|
||||
#foo/*/qux
|
||||
# The above matches foo/bar/qux and foo/baz/qux, but not foo/bar/baz/qux
|
||||
|
||||
# You can recursively match patterns against a directory, file or extension with a double asterisk (**):
|
||||
#foo/**/qux
|
||||
# This matches foo/bar/qux, foo/baz/qux, and foo/bar/baz/qux
|
||||
|
||||
# You can also negate patterns with an exclamation (!).
|
||||
# For example, you can ignore all files in a docs folder with the file extension .md:
|
||||
#docs/*.md
|
||||
# Then explicitly reverse the ignore rule for a single file:
|
||||
#!docs/README.md
|
1
server/swagger/docs/html/.openapi-generator/VERSION
Normal file
1
server/swagger/docs/html/.openapi-generator/VERSION
Normal file
@ -0,0 +1 @@
|
||||
5.0.1
|
10306
server/swagger/docs/html/index.html
Normal file
10306
server/swagger/docs/html/index.html
Normal file
File diff suppressed because one or more lines are too long
693
server/swagger/swagger.yml
Normal file
693
server/swagger/swagger.yml
Normal file
@ -0,0 +1,693 @@
|
||||
basePath: /api/v1
|
||||
consumes:
|
||||
- application/json
|
||||
definitions:
|
||||
Block:
|
||||
description: Block is the basic data unit
|
||||
properties:
|
||||
createAt:
|
||||
description: The creation time
|
||||
format: int64
|
||||
type: integer
|
||||
x-go-name: CreateAt
|
||||
deleteAt:
|
||||
description: The deleted time. Set to indicate this block is deleted
|
||||
format: int64
|
||||
type: integer
|
||||
x-go-name: DeleteAt
|
||||
fields:
|
||||
additionalProperties:
|
||||
type: object
|
||||
description: The block fields
|
||||
type: object
|
||||
x-go-name: Fields
|
||||
id:
|
||||
description: The id for this block
|
||||
type: string
|
||||
x-go-name: ID
|
||||
modifiedBy:
|
||||
description: The id for user who last modified this block
|
||||
type: string
|
||||
x-go-name: ModifiedBy
|
||||
parentId:
|
||||
description: The id for this block's parent block. Empty for root blocks
|
||||
type: string
|
||||
x-go-name: ParentID
|
||||
rootId:
|
||||
description: The id for this block's root block
|
||||
type: string
|
||||
x-go-name: RootID
|
||||
schema:
|
||||
description: The schema version of this block
|
||||
format: int64
|
||||
type: integer
|
||||
x-go-name: Schema
|
||||
title:
|
||||
description: The display title
|
||||
type: string
|
||||
x-go-name: Title
|
||||
type:
|
||||
description: The block type
|
||||
type: string
|
||||
x-go-name: Type
|
||||
updateAt:
|
||||
description: The last modified time
|
||||
format: int64
|
||||
type: integer
|
||||
x-go-name: UpdateAt
|
||||
required:
|
||||
- id
|
||||
- rootId
|
||||
- modifiedBy
|
||||
- schema
|
||||
- type
|
||||
- createAt
|
||||
- updateAt
|
||||
type: object
|
||||
x-go-package: github.com/mattermost/focalboard/server/model
|
||||
ChangePasswordRequest:
|
||||
description: ChangePasswordRequest is a user password change request
|
||||
properties:
|
||||
newPassword:
|
||||
description: New password
|
||||
type: string
|
||||
x-go-name: NewPassword
|
||||
oldPassword:
|
||||
description: Old password
|
||||
type: string
|
||||
x-go-name: OldPassword
|
||||
required:
|
||||
- oldPassword
|
||||
- newPassword
|
||||
type: object
|
||||
x-go-package: github.com/mattermost/focalboard/server/api
|
||||
ErrorResponse:
|
||||
description: ErrorResponse is an error response
|
||||
properties:
|
||||
error:
|
||||
description: The error message
|
||||
type: string
|
||||
x-go-name: Error
|
||||
type: object
|
||||
x-go-package: github.com/mattermost/focalboard/server/model
|
||||
FileUploadResponse:
|
||||
description: FileUploadResponse is the response to a file upload
|
||||
properties:
|
||||
url:
|
||||
description: The URL to retrieve the uploaded file
|
||||
type: string
|
||||
x-go-name: URL
|
||||
required:
|
||||
- url
|
||||
type: object
|
||||
x-go-package: github.com/mattermost/focalboard/server/api
|
||||
LoginRequest:
|
||||
description: LoginRequest is a login request
|
||||
properties:
|
||||
email:
|
||||
description: If specified, login using email
|
||||
type: string
|
||||
x-go-name: Email
|
||||
password:
|
||||
description: Password
|
||||
type: string
|
||||
x-go-name: Password
|
||||
type:
|
||||
description: Type of login, currently must be set to "normal"
|
||||
type: string
|
||||
x-go-name: Type
|
||||
username:
|
||||
description: If specified, login using username
|
||||
type: string
|
||||
x-go-name: Username
|
||||
required:
|
||||
- type
|
||||
- password
|
||||
type: object
|
||||
x-go-package: github.com/mattermost/focalboard/server/api
|
||||
LoginResponse:
|
||||
description: LoginResponse is a login response
|
||||
properties:
|
||||
token:
|
||||
description: Session token
|
||||
type: string
|
||||
x-go-name: Token
|
||||
required:
|
||||
- token
|
||||
type: object
|
||||
x-go-package: github.com/mattermost/focalboard/server/api
|
||||
RegisterRequest:
|
||||
description: RegisterRequest is a user registration request
|
||||
properties:
|
||||
email:
|
||||
description: User's email
|
||||
type: string
|
||||
x-go-name: Email
|
||||
password:
|
||||
description: Password
|
||||
type: string
|
||||
x-go-name: Password
|
||||
token:
|
||||
description: Registration authorization token
|
||||
type: string
|
||||
x-go-name: Token
|
||||
username:
|
||||
description: User name
|
||||
type: string
|
||||
x-go-name: Username
|
||||
required:
|
||||
- username
|
||||
- email
|
||||
- password
|
||||
- token
|
||||
type: object
|
||||
x-go-package: github.com/mattermost/focalboard/server/api
|
||||
Sharing:
|
||||
description: Sharing is sharing information for a root block
|
||||
properties:
|
||||
enabled:
|
||||
description: Is sharing enabled
|
||||
type: boolean
|
||||
x-go-name: Enabled
|
||||
id:
|
||||
description: ID of the root block
|
||||
type: string
|
||||
x-go-name: ID
|
||||
modifiedBy:
|
||||
description: ID of the user who last modified this
|
||||
type: string
|
||||
x-go-name: ModifiedBy
|
||||
token:
|
||||
description: Access token
|
||||
type: string
|
||||
x-go-name: Token
|
||||
update_at:
|
||||
description: Updated time
|
||||
format: int64
|
||||
type: integer
|
||||
x-go-name: UpdateAt
|
||||
required:
|
||||
- id
|
||||
- enabled
|
||||
- token
|
||||
- modifiedBy
|
||||
- update_at
|
||||
type: object
|
||||
x-go-package: github.com/mattermost/focalboard/server/model
|
||||
User:
|
||||
description: User is a user
|
||||
properties:
|
||||
create_at:
|
||||
description: Created time
|
||||
format: int64
|
||||
type: integer
|
||||
x-go-name: CreateAt
|
||||
delete_at:
|
||||
description: Deleted time, set to indicate user is deleted
|
||||
format: int64
|
||||
type: integer
|
||||
x-go-name: DeleteAt
|
||||
email:
|
||||
description: The user's email
|
||||
type: string
|
||||
x-go-name: Email
|
||||
id:
|
||||
description: The user ID
|
||||
type: string
|
||||
x-go-name: ID
|
||||
props:
|
||||
additionalProperties:
|
||||
type: object
|
||||
description: User settings
|
||||
type: object
|
||||
x-go-name: Props
|
||||
update_at:
|
||||
description: Updated time
|
||||
format: int64
|
||||
type: integer
|
||||
x-go-name: UpdateAt
|
||||
username:
|
||||
description: The user name
|
||||
type: string
|
||||
x-go-name: Username
|
||||
required:
|
||||
- id
|
||||
- username
|
||||
- email
|
||||
- props
|
||||
- create_at
|
||||
- update_at
|
||||
- delete_at
|
||||
type: object
|
||||
x-go-package: github.com/mattermost/focalboard/server/model
|
||||
Workspace:
|
||||
description: Workspace is information global to a workspace
|
||||
properties:
|
||||
id:
|
||||
description: ID of the workspace
|
||||
type: string
|
||||
x-go-name: ID
|
||||
modifiedBy:
|
||||
description: ID of user who last modified this
|
||||
type: string
|
||||
x-go-name: ModifiedBy
|
||||
settings:
|
||||
additionalProperties:
|
||||
type: object
|
||||
description: Workspace settings
|
||||
type: object
|
||||
x-go-name: Settings
|
||||
signupToken:
|
||||
description: Token required to register new users
|
||||
type: string
|
||||
x-go-name: SignupToken
|
||||
updateAt:
|
||||
description: Updated time
|
||||
format: int64
|
||||
type: integer
|
||||
x-go-name: UpdateAt
|
||||
required:
|
||||
- id
|
||||
- signupToken
|
||||
- modifiedBy
|
||||
- updateAt
|
||||
type: object
|
||||
x-go-package: github.com/mattermost/focalboard/server/model
|
||||
host: localhost
|
||||
info:
|
||||
contact:
|
||||
email: api@focalboard.com
|
||||
name: Focalboard
|
||||
url: https://www.focalboard.com
|
||||
description: Server for Focalboard
|
||||
license:
|
||||
name: Custom
|
||||
url: https://github.com/mattermost/focalboard/blob/main/LICENSE.txt
|
||||
title: Focalboard Server
|
||||
version: 0.5.0
|
||||
paths:
|
||||
/api/v1/blocks:
|
||||
get:
|
||||
description: Returns blocks
|
||||
operationId: getBlocks
|
||||
parameters:
|
||||
- description: ID of parent block, omit to specify all blocks
|
||||
in: query
|
||||
name: parent_id
|
||||
type: string
|
||||
- description: Type of blocks to return, omit to specify all types
|
||||
in: query
|
||||
name: type
|
||||
type: string
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: success
|
||||
schema:
|
||||
items:
|
||||
$ref: '#/definitions/Block'
|
||||
type: array
|
||||
default:
|
||||
description: internal error
|
||||
schema:
|
||||
$ref: '#/definitions/ErrorResponse'
|
||||
security:
|
||||
- BearerAuth: []
|
||||
post:
|
||||
description: Insert or update blocks
|
||||
operationId: updateBlocks
|
||||
parameters:
|
||||
- description: array of blocks to insert or update
|
||||
in: body
|
||||
name: Body
|
||||
required: true
|
||||
schema:
|
||||
items:
|
||||
$ref: '#/definitions/Block'
|
||||
type: array
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: success
|
||||
default:
|
||||
description: internal error
|
||||
schema:
|
||||
$ref: '#/definitions/ErrorResponse'
|
||||
security:
|
||||
- BearerAuth: []
|
||||
/api/v1/blocks/{blockID}:
|
||||
delete:
|
||||
description: Deletes a block
|
||||
operationId: deleteBlock
|
||||
parameters:
|
||||
- description: ID of block to delete
|
||||
in: path
|
||||
name: blockID
|
||||
required: true
|
||||
type: string
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: success
|
||||
default:
|
||||
description: internal error
|
||||
schema:
|
||||
$ref: '#/definitions/ErrorResponse'
|
||||
security:
|
||||
- BearerAuth: []
|
||||
/api/v1/blocks/{blockID}/subtree:
|
||||
get:
|
||||
description: Returns the blocks of a subtree
|
||||
operationId: getSubTree
|
||||
parameters:
|
||||
- description: The ID of the root block of the subtree
|
||||
in: path
|
||||
name: blockID
|
||||
required: true
|
||||
type: string
|
||||
- description: The number of levels to return. 2 or 3. Defaults to 2.
|
||||
in: query
|
||||
maximum: 3
|
||||
minimum: 2
|
||||
name: l
|
||||
type: integer
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: success
|
||||
schema:
|
||||
items:
|
||||
$ref: '#/definitions/Block'
|
||||
type: array
|
||||
default:
|
||||
description: internal error
|
||||
schema:
|
||||
$ref: '#/definitions/ErrorResponse'
|
||||
security:
|
||||
- BearerAuth: []
|
||||
/api/v1/blocks/export:
|
||||
get:
|
||||
description: Returns all blocks
|
||||
operationId: exportBlocks
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: success
|
||||
schema:
|
||||
items:
|
||||
$ref: '#/definitions/Block'
|
||||
type: array
|
||||
default:
|
||||
description: internal error
|
||||
schema:
|
||||
$ref: '#/definitions/ErrorResponse'
|
||||
security:
|
||||
- BearerAuth: []
|
||||
/api/v1/blocks/import:
|
||||
post:
|
||||
description: Import blocks
|
||||
operationId: importBlocks
|
||||
parameters:
|
||||
- description: array of blocks to import
|
||||
in: body
|
||||
name: Body
|
||||
required: true
|
||||
schema:
|
||||
items:
|
||||
$ref: '#/definitions/Block'
|
||||
type: array
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: success
|
||||
default:
|
||||
description: internal error
|
||||
schema:
|
||||
$ref: '#/definitions/ErrorResponse'
|
||||
security:
|
||||
- BearerAuth: []
|
||||
/api/v1/files:
|
||||
post:
|
||||
consumes:
|
||||
- multipart/form-data
|
||||
description: Upload a binary file
|
||||
operationId: uploadFile
|
||||
parameters:
|
||||
- description: The file to upload
|
||||
in: formData
|
||||
name: uploaded file
|
||||
type: file
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: success
|
||||
schema:
|
||||
$ref: '#/definitions/FileUploadResponse'
|
||||
default:
|
||||
description: internal error
|
||||
schema:
|
||||
$ref: '#/definitions/ErrorResponse'
|
||||
security:
|
||||
- BearerAuth: []
|
||||
/api/v1/login:
|
||||
post:
|
||||
description: Login user
|
||||
operationId: login
|
||||
parameters:
|
||||
- description: Login request
|
||||
in: body
|
||||
name: body
|
||||
required: true
|
||||
schema:
|
||||
$ref: '#/definitions/LoginRequest'
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: success
|
||||
schema:
|
||||
$ref: '#/definitions/LoginResponse'
|
||||
"401":
|
||||
description: invalid login
|
||||
schema:
|
||||
$ref: '#/definitions/ErrorResponse'
|
||||
"500":
|
||||
description: internal error
|
||||
schema:
|
||||
$ref: '#/definitions/ErrorResponse'
|
||||
/api/v1/register:
|
||||
post:
|
||||
description: Register new user
|
||||
operationId: register
|
||||
parameters:
|
||||
- description: Register request
|
||||
in: body
|
||||
name: body
|
||||
required: true
|
||||
schema:
|
||||
$ref: '#/definitions/RegisterRequest'
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: success
|
||||
"401":
|
||||
description: invalid registration token
|
||||
"500":
|
||||
description: internal error
|
||||
schema:
|
||||
$ref: '#/definitions/ErrorResponse'
|
||||
/api/v1/sharing/{rootID}:
|
||||
get:
|
||||
description: Returns sharing information for a root block
|
||||
operationId: getSharing
|
||||
parameters:
|
||||
- description: ID of the root block
|
||||
in: path
|
||||
name: rootID
|
||||
required: true
|
||||
type: string
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: success
|
||||
schema:
|
||||
$ref: '#/definitions/Sharing'
|
||||
default:
|
||||
description: internal error
|
||||
schema:
|
||||
$ref: '#/definitions/ErrorResponse'
|
||||
security:
|
||||
- BearerAuth: []
|
||||
post:
|
||||
description: Sets sharing information for a root block
|
||||
operationId: postSharing
|
||||
parameters:
|
||||
- description: ID of the root block
|
||||
in: path
|
||||
name: rootID
|
||||
required: true
|
||||
type: string
|
||||
- description: sharing information for a root block
|
||||
in: body
|
||||
name: Body
|
||||
required: true
|
||||
schema:
|
||||
$ref: '#/definitions/Sharing'
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: success
|
||||
default:
|
||||
description: internal error
|
||||
schema:
|
||||
$ref: '#/definitions/ErrorResponse'
|
||||
security:
|
||||
- BearerAuth: []
|
||||
/api/v1/users/{userID}:
|
||||
get:
|
||||
description: Returns a user
|
||||
operationId: getUser
|
||||
parameters:
|
||||
- description: User ID
|
||||
in: path
|
||||
name: userID
|
||||
required: true
|
||||
type: string
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: success
|
||||
schema:
|
||||
$ref: '#/definitions/User'
|
||||
default:
|
||||
description: internal error
|
||||
schema:
|
||||
$ref: '#/definitions/ErrorResponse'
|
||||
security:
|
||||
- BearerAuth: []
|
||||
/api/v1/users/{userID}/changepassword:
|
||||
post:
|
||||
description: Change a user's password
|
||||
operationId: changePassword
|
||||
parameters:
|
||||
- description: User ID
|
||||
in: path
|
||||
name: userID
|
||||
required: true
|
||||
type: string
|
||||
- description: Change password request
|
||||
in: body
|
||||
name: body
|
||||
required: true
|
||||
schema:
|
||||
$ref: '#/definitions/ChangePasswordRequest'
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: success
|
||||
"400":
|
||||
description: invalid request
|
||||
schema:
|
||||
$ref: '#/definitions/ErrorResponse'
|
||||
"500":
|
||||
description: internal error
|
||||
schema:
|
||||
$ref: '#/definitions/ErrorResponse'
|
||||
security:
|
||||
- BearerAuth: []
|
||||
/api/v1/users/me:
|
||||
get:
|
||||
description: Returns the currently logged-in user
|
||||
operationId: getMe
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: success
|
||||
schema:
|
||||
$ref: '#/definitions/User'
|
||||
default:
|
||||
description: internal error
|
||||
schema:
|
||||
$ref: '#/definitions/ErrorResponse'
|
||||
security:
|
||||
- BearerAuth: []
|
||||
/api/v1/workspace:
|
||||
get:
|
||||
description: Returns information of the root workspace
|
||||
operationId: getWorkspace
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: success
|
||||
schema:
|
||||
$ref: '#/definitions/Workspace'
|
||||
default:
|
||||
description: internal error
|
||||
schema:
|
||||
$ref: '#/definitions/ErrorResponse'
|
||||
security:
|
||||
- BearerAuth: []
|
||||
/api/v1/workspace/regenerate_signup_token:
|
||||
post:
|
||||
description: Regenerates the signup token for the root workspace
|
||||
operationId: regenerateSignupToken
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: success
|
||||
default:
|
||||
description: internal error
|
||||
schema:
|
||||
$ref: '#/definitions/ErrorResponse'
|
||||
security:
|
||||
- BearerAuth: []
|
||||
/files/{fileID}:
|
||||
get:
|
||||
description: Returns the contents of an uploaded file
|
||||
operationId: getFile
|
||||
parameters:
|
||||
- description: ID of the file
|
||||
in: path
|
||||
name: fileID
|
||||
required: true
|
||||
type: string
|
||||
produces:
|
||||
- application/json
|
||||
- image/jpg
|
||||
- image/png
|
||||
responses:
|
||||
"200":
|
||||
description: success
|
||||
default:
|
||||
description: internal error
|
||||
schema:
|
||||
$ref: '#/definitions/ErrorResponse'
|
||||
security:
|
||||
- BearerAuth: []
|
||||
produces:
|
||||
- application/json
|
||||
schemes:
|
||||
- http
|
||||
- https
|
||||
securityDefinitions:
|
||||
BearerAuth:
|
||||
description: 'Pass session token using Bearer authentication, e.g. set header "Authorization: Bearer <session token>"'
|
||||
in: header
|
||||
name: Authorization
|
||||
type: apiKey
|
||||
swagger: "2.0"
|
Loading…
Reference in New Issue
Block a user