You've already forked focalboard
							
							
				mirror of
				https://github.com/mattermost/focalboard.git
				synced 2025-10-31 00:17:42 +02:00 
			
		
		
		
	[GH-3410] Healthcheck Endpoint with Server Metadata (#4151)
* add ping endpoint and tests * remove unnecessary newlines * fix: invalid Swagger YAML comment blocks * refactor and add 'suite' SKU * generate swagger docs Co-authored-by: Mattermod <mattermod@users.noreply.github.com> Co-authored-by: Paul Esch-Laurent <paul.esch-laurent@mattermost.com>
This commit is contained in:
		| @@ -52,7 +52,7 @@ func (a *API) handleCreateCard(w http.ResponseWriter, r *http.Request) { | ||||
| 	//   description: Disables notifications (for bulk data inserting) | ||||
| 	//   required: false | ||||
| 	//   type: bool | ||||
| 	//  security: | ||||
| 	// security: | ||||
| 	// - BearerAuth: [] | ||||
| 	// responses: | ||||
| 	//   '200': | ||||
| @@ -128,7 +128,7 @@ func (a *API) handleCreateCard(w http.ResponseWriter, r *http.Request) { | ||||
| } | ||||
|  | ||||
| func (a *API) handleGetCards(w http.ResponseWriter, r *http.Request) { | ||||
| 	// swagger:operation GET /boards/{boardID}/cards | ||||
| 	// swagger:operation GET /boards/{boardID}/cards getCards | ||||
| 	// | ||||
| 	// Fetches cards for the specified board. | ||||
| 	// | ||||
| @@ -151,7 +151,7 @@ func (a *API) handleGetCards(w http.ResponseWriter, r *http.Request) { | ||||
| 	//   description: Number of cards to return per page(default=100) | ||||
| 	//   required: false | ||||
| 	//   type: integer | ||||
| 	//  security: | ||||
| 	// security: | ||||
| 	// - BearerAuth: [] | ||||
| 	// responses: | ||||
| 	//   '200': | ||||
| @@ -252,7 +252,7 @@ func (a *API) handlePatchCard(w http.ResponseWriter, r *http.Request) { | ||||
| 	//   description: Disables notifications (for bulk data patching) | ||||
| 	//   required: false | ||||
| 	//   type: bool | ||||
| 	//  security: | ||||
| 	// security: | ||||
| 	// - BearerAuth: [] | ||||
| 	// responses: | ||||
| 	//   '200': | ||||
| @@ -325,7 +325,7 @@ func (a *API) handlePatchCard(w http.ResponseWriter, r *http.Request) { | ||||
| } | ||||
|  | ||||
| func (a *API) handleGetCard(w http.ResponseWriter, r *http.Request) { | ||||
| 	// swagger:operation GET /cards/{cardID} | ||||
| 	// swagger:operation GET /cards/{cardID} getCard | ||||
| 	// | ||||
| 	// Fetches the specified card. | ||||
| 	// | ||||
| @@ -338,7 +338,7 @@ func (a *API) handleGetCard(w http.ResponseWriter, r *http.Request) { | ||||
| 	//   description: Card ID | ||||
| 	//   required: true | ||||
| 	//   type: string | ||||
| 	//  security: | ||||
| 	// security: | ||||
| 	// - BearerAuth: [] | ||||
| 	// responses: | ||||
| 	//   '200': | ||||
|   | ||||
| @@ -1,6 +1,7 @@ | ||||
| package api | ||||
|  | ||||
| import ( | ||||
| 	"encoding/json" | ||||
| 	"net/http" | ||||
|  | ||||
| 	"github.com/gorilla/mux" | ||||
| @@ -9,6 +10,7 @@ import ( | ||||
| func (a *API) registerSystemRoutes(r *mux.Router) { | ||||
| 	// System APIs | ||||
| 	r.HandleFunc("/hello", a.handleHello).Methods("GET") | ||||
| 	r.HandleFunc("/ping", a.handlePing).Methods("GET") | ||||
| } | ||||
|  | ||||
| func (a *API) handleHello(w http.ResponseWriter, r *http.Request) { | ||||
| @@ -24,3 +26,32 @@ func (a *API) handleHello(w http.ResponseWriter, r *http.Request) { | ||||
| 	//     description: success | ||||
| 	stringResponse(w, "Hello") | ||||
| } | ||||
|  | ||||
| func (a *API) handlePing(w http.ResponseWriter, r *http.Request) { | ||||
| 	// swagger:operation GET /ping ping | ||||
| 	// | ||||
| 	// Responds with server metadata if the web service is running. | ||||
| 	// | ||||
| 	// --- | ||||
| 	// produces: | ||||
| 	// - application/json | ||||
| 	// responses: | ||||
| 	//   '200': | ||||
| 	//     description: success | ||||
| 	serverMetadata := a.app.GetServerMetadata() | ||||
|  | ||||
| 	if a.singleUserToken != "" { | ||||
| 		serverMetadata.SKU = "personal_desktop" | ||||
| 	} | ||||
|  | ||||
| 	if serverMetadata.Edition == "plugin" { | ||||
| 		serverMetadata.SKU = "suite" | ||||
| 	} | ||||
|  | ||||
| 	bytes, err := json.Marshal(serverMetadata) | ||||
| 	if err != nil { | ||||
| 		a.errorResponse(w, r, err) | ||||
| 	} | ||||
|  | ||||
| 	jsonStringResponse(w, 200, string(bytes)) | ||||
| } | ||||
|   | ||||
							
								
								
									
										143
									
								
								server/api/system_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										143
									
								
								server/api/system_test.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,143 @@ | ||||
| package api | ||||
|  | ||||
| import ( | ||||
| 	"encoding/json" | ||||
| 	"net/http" | ||||
| 	"net/http/httptest" | ||||
| 	"runtime" | ||||
| 	"testing" | ||||
|  | ||||
| 	"github.com/mattermost/focalboard/server/app" | ||||
| 	"github.com/mattermost/focalboard/server/model" | ||||
| 	"github.com/mattermost/mattermost-server/v6/shared/mlog" | ||||
| ) | ||||
|  | ||||
| func TestHello(t *testing.T) { | ||||
| 	testAPI := API{logger: mlog.CreateConsoleTestLogger(false, mlog.LvlDebug)} | ||||
|  | ||||
| 	t.Run("Returns 'Hello' on success", func(t *testing.T) { | ||||
| 		request, _ := http.NewRequest(http.MethodGet, "/hello", nil) | ||||
| 		response := httptest.NewRecorder() | ||||
|  | ||||
| 		testAPI.handleHello(response, request) | ||||
|  | ||||
| 		got := response.Body.String() | ||||
| 		want := "Hello" | ||||
|  | ||||
| 		if got != want { | ||||
| 			t.Errorf("got %q want %q", got, want) | ||||
| 		} | ||||
|  | ||||
| 		if response.Code != http.StatusOK { | ||||
| 			t.Errorf("got HTTP %d want %d", response.Code, http.StatusOK) | ||||
| 		} | ||||
| 	}) | ||||
| } | ||||
|  | ||||
| func TestPing(t *testing.T) { | ||||
| 	testAPI := API{logger: mlog.CreateConsoleTestLogger(false, mlog.LvlDebug)} | ||||
|  | ||||
| 	t.Run("Returns metadata on success", func(t *testing.T) { | ||||
| 		request, _ := http.NewRequest(http.MethodGet, "/ping", nil) | ||||
| 		response := httptest.NewRecorder() | ||||
|  | ||||
| 		testAPI.handlePing(response, request) | ||||
|  | ||||
| 		var got app.ServerMetadata | ||||
| 		err := json.NewDecoder(response.Body).Decode(&got) | ||||
| 		if err != nil { | ||||
| 			t.Fatalf("Unable to JSON decode response body %q", response.Body) | ||||
| 		} | ||||
|  | ||||
| 		want := app.ServerMetadata{ | ||||
| 			Version:     model.CurrentVersion, | ||||
| 			BuildNumber: model.BuildNumber, | ||||
| 			BuildDate:   model.BuildDate, | ||||
| 			Commit:      model.BuildHash, | ||||
| 			Edition:     model.Edition, | ||||
| 			DBType:      "", | ||||
| 			DBVersion:   "", | ||||
| 			OSType:      runtime.GOOS, | ||||
| 			OSArch:      runtime.GOARCH, | ||||
| 			SKU:         "personal_server", | ||||
| 		} | ||||
|  | ||||
| 		if got != want { | ||||
| 			t.Errorf("got %q want %q", got, want) | ||||
| 		} | ||||
|  | ||||
| 		if response.Code != http.StatusOK { | ||||
| 			t.Errorf("got HTTP %d want %d", response.Code, http.StatusOK) | ||||
| 		} | ||||
| 	}) | ||||
|  | ||||
| 	t.Run("Sets SKU to 'personal_desktop' when in single-user mode", func(t *testing.T) { | ||||
| 		testAPI.singleUserToken = "abc-123-xyz-456" | ||||
| 		request, _ := http.NewRequest(http.MethodGet, "/ping", nil) | ||||
| 		response := httptest.NewRecorder() | ||||
|  | ||||
| 		testAPI.handlePing(response, request) | ||||
|  | ||||
| 		var got app.ServerMetadata | ||||
| 		err := json.NewDecoder(response.Body).Decode(&got) | ||||
| 		if err != nil { | ||||
| 			t.Fatalf("Unable to JSON decode response body %q", response.Body) | ||||
| 		} | ||||
|  | ||||
| 		want := app.ServerMetadata{ | ||||
| 			Version:     model.CurrentVersion, | ||||
| 			BuildNumber: model.BuildNumber, | ||||
| 			BuildDate:   model.BuildDate, | ||||
| 			Commit:      model.BuildHash, | ||||
| 			Edition:     model.Edition, | ||||
| 			DBType:      "", | ||||
| 			DBVersion:   "", | ||||
| 			OSType:      runtime.GOOS, | ||||
| 			OSArch:      runtime.GOARCH, | ||||
| 			SKU:         "personal_desktop", | ||||
| 		} | ||||
|  | ||||
| 		if got != want { | ||||
| 			t.Errorf("got %q want %q", got, want) | ||||
| 		} | ||||
|  | ||||
| 		if response.Code != http.StatusOK { | ||||
| 			t.Errorf("got HTTP %d want %d", response.Code, http.StatusOK) | ||||
| 		} | ||||
| 	}) | ||||
|  | ||||
| 	t.Run("Sets SKU to 'suite' when in plugin mode", func(t *testing.T) { | ||||
| 		model.Edition = "plugin" | ||||
| 		request, _ := http.NewRequest(http.MethodGet, "/ping", nil) | ||||
| 		response := httptest.NewRecorder() | ||||
|  | ||||
| 		testAPI.handlePing(response, request) | ||||
|  | ||||
| 		var got app.ServerMetadata | ||||
| 		err := json.NewDecoder(response.Body).Decode(&got) | ||||
| 		if err != nil { | ||||
| 			t.Fatalf("Unable to JSON decode response body %q", response.Body) | ||||
| 		} | ||||
|  | ||||
| 		want := app.ServerMetadata{ | ||||
| 			Version:     model.CurrentVersion, | ||||
| 			BuildNumber: model.BuildNumber, | ||||
| 			BuildDate:   model.BuildDate, | ||||
| 			Commit:      model.BuildHash, | ||||
| 			Edition:     "plugin", | ||||
| 			DBType:      "", | ||||
| 			DBVersion:   "", | ||||
| 			OSType:      runtime.GOOS, | ||||
| 			OSArch:      runtime.GOARCH, | ||||
| 			SKU:         "suite", | ||||
| 		} | ||||
|  | ||||
| 		if got != want { | ||||
| 			t.Errorf("got %q want %q", got, want) | ||||
| 		} | ||||
|  | ||||
| 		if response.Code != http.StatusOK { | ||||
| 			t.Errorf("got HTTP %d want %d", response.Code, http.StatusOK) | ||||
| 		} | ||||
| 	}) | ||||
| } | ||||
| @@ -283,7 +283,7 @@ func (a *API) handleUpdateUserConfig(w http.ResponseWriter, r *http.Request) { | ||||
| 	//   description: User config patch to apply | ||||
| 	//   required: true | ||||
| 	//   schema: | ||||
| 	//     "$ref": "#/definitions/UserPropPatch" | ||||
| 	//     "$ref": "#/definitions/UserPreferencesPatch" | ||||
| 	// security: | ||||
| 	// - BearerAuth: [] | ||||
| 	// responses: | ||||
|   | ||||
							
								
								
									
										42
									
								
								server/app/server_metadata.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										42
									
								
								server/app/server_metadata.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,42 @@ | ||||
| package app | ||||
|  | ||||
| import ( | ||||
| 	"runtime" | ||||
|  | ||||
| 	"github.com/mattermost/focalboard/server/model" | ||||
| ) | ||||
|  | ||||
| type ServerMetadata struct { | ||||
| 	Version     string `json:"version"` | ||||
| 	BuildNumber string `json:"build_number"` | ||||
| 	BuildDate   string `json:"build_date"` | ||||
| 	Commit      string `json:"commit"` | ||||
| 	Edition     string `json:"edition"` | ||||
| 	DBType      string `json:"db_type"` | ||||
| 	DBVersion   string `json:"db_version"` | ||||
| 	OSType      string `json:"os_type"` | ||||
| 	OSArch      string `json:"os_arch"` | ||||
| 	SKU         string `json:"sku"` | ||||
| } | ||||
|  | ||||
| func (a *App) GetServerMetadata() *ServerMetadata { | ||||
| 	var dbType string | ||||
| 	var dbVersion string | ||||
| 	if a != nil && a.store != nil { | ||||
| 		dbType = a.store.DBType() | ||||
| 		dbVersion = a.store.DBVersion() | ||||
| 	} | ||||
|  | ||||
| 	return &ServerMetadata{ | ||||
| 		Version:     model.CurrentVersion, | ||||
| 		BuildNumber: model.BuildNumber, | ||||
| 		BuildDate:   model.BuildDate, | ||||
| 		Commit:      model.BuildHash, | ||||
| 		Edition:     model.Edition, | ||||
| 		DBType:      dbType, | ||||
| 		DBVersion:   dbVersion, | ||||
| 		OSType:      runtime.GOOS, | ||||
| 		OSArch:      runtime.GOARCH, | ||||
| 		SKU:         "personal_server", | ||||
| 	} | ||||
| } | ||||
							
								
								
									
										37
									
								
								server/app/server_metadata_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										37
									
								
								server/app/server_metadata_test.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,37 @@ | ||||
| package app | ||||
|  | ||||
| import ( | ||||
| 	"reflect" | ||||
| 	"runtime" | ||||
| 	"testing" | ||||
|  | ||||
| 	"github.com/mattermost/focalboard/server/model" | ||||
| ) | ||||
|  | ||||
| func TestGetServerMetadata(t *testing.T) { | ||||
| 	th, tearDown := SetupTestHelper(t) | ||||
| 	defer tearDown() | ||||
|  | ||||
| 	th.Store.EXPECT().DBType().Return("TEST_DB_TYPE") | ||||
| 	th.Store.EXPECT().DBVersion().Return("TEST_DB_VERSION") | ||||
|  | ||||
| 	t.Run("Get Server Metadata", func(t *testing.T) { | ||||
| 		got := th.App.GetServerMetadata() | ||||
| 		want := &ServerMetadata{ | ||||
| 			Version:     model.CurrentVersion, | ||||
| 			BuildNumber: model.BuildNumber, | ||||
| 			BuildDate:   model.BuildDate, | ||||
| 			Commit:      model.BuildHash, | ||||
| 			Edition:     model.Edition, | ||||
| 			DBType:      "TEST_DB_TYPE", | ||||
| 			DBVersion:   "TEST_DB_VERSION", | ||||
| 			OSType:      runtime.GOOS, | ||||
| 			OSArch:      runtime.GOARCH, | ||||
| 			SKU:         "personal_server", | ||||
| 		} | ||||
|  | ||||
| 		if !reflect.DeepEqual(got, want) { | ||||
| 			t.Errorf("got: %q, want: %q", got, want) | ||||
| 		} | ||||
| 	}) | ||||
| } | ||||
| @@ -182,6 +182,20 @@ func (mr *MockStoreMockRecorder) DBType() *gomock.Call { | ||||
| 	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DBType", reflect.TypeOf((*MockStore)(nil).DBType)) | ||||
| } | ||||
|  | ||||
| // DBVersion mocks base method. | ||||
| func (m *MockStore) DBVersion() string { | ||||
| 	m.ctrl.T.Helper() | ||||
| 	ret := m.ctrl.Call(m, "DBVersion") | ||||
| 	ret0, _ := ret[0].(string) | ||||
| 	return ret0 | ||||
| } | ||||
|  | ||||
| // DBVersion indicates an expected call of DBVersion. | ||||
| func (mr *MockStoreMockRecorder) DBVersion() *gomock.Call { | ||||
| 	mr.mock.ctrl.T.Helper() | ||||
| 	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DBVersion", reflect.TypeOf((*MockStore)(nil).DBVersion)) | ||||
| } | ||||
|  | ||||
| // DeleteBlock mocks base method. | ||||
| func (m *MockStore) DeleteBlock(arg0, arg1 string) error { | ||||
| 	m.ctrl.T.Helper() | ||||
|   | ||||
| @@ -124,6 +124,11 @@ func (s *SQLStore) CreateUser(user *model.User) (*model.User, error) { | ||||
|  | ||||
| } | ||||
|  | ||||
| func (s *SQLStore) DBVersion() string { | ||||
| 	return s.dBVersion(s.db) | ||||
|  | ||||
| } | ||||
|  | ||||
| func (s *SQLStore) DeleteBlock(blockID string, modifiedBy string) error { | ||||
| 	if s.dbType == model.SqliteDBType { | ||||
| 		return s.deleteBlock(s.db, blockID, modifiedBy) | ||||
|   | ||||
| @@ -175,3 +175,26 @@ func (s *SQLStore) searchUserChannels(db sq.BaseRunner, teamID, userID, query st | ||||
| func (s *SQLStore) getChannel(db sq.BaseRunner, teamID, channel string) (*mmModel.Channel, error) { | ||||
| 	return nil, store.NewNotSupportedError("get channel not supported on standalone mode") | ||||
| } | ||||
|  | ||||
| func (s *SQLStore) dBVersion(db sq.BaseRunner) string { | ||||
| 	var version string | ||||
| 	var row *sql.Row | ||||
|  | ||||
| 	switch s.dbType { | ||||
| 	case model.MysqlDBType: | ||||
| 		row = s.db.QueryRow("SELECT VERSION()") | ||||
| 	case model.PostgresDBType: | ||||
| 		row = s.db.QueryRow("SHOW server_version") | ||||
| 	case model.SqliteDBType: | ||||
| 		row = s.db.QueryRow("SELECT sqlite_version()") | ||||
| 	default: | ||||
| 		return "" | ||||
| 	} | ||||
|  | ||||
| 	if err := row.Scan(&version); err != nil { | ||||
| 		s.logger.Error("error checking database version", mlog.Err(err)) | ||||
| 		return "" | ||||
| 	} | ||||
|  | ||||
| 	return version | ||||
| } | ||||
|   | ||||
| @@ -153,6 +153,7 @@ type Store interface { | ||||
| 	UpdateCardLimitTimestamp(cardLimit int) (int64, error) | ||||
|  | ||||
| 	DBType() string | ||||
| 	DBVersion() string | ||||
|  | ||||
| 	GetLicense() *mmModel.License | ||||
| 	GetCloudLimits() (*mmModel.ProductLimits, error) | ||||
|   | ||||
| @@ -1 +1 @@ | ||||
| 6.0.1 | ||||
| 6.2.1 | ||||
							
								
								
									
										4080
									
								
								server/swagger/docs/html/index.html
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										4080
									
								
								server/swagger/docs/html/index.html
									
									
									
										generated
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										162
									
								
								server/swagger/swagger.yml
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										162
									
								
								server/swagger/swagger.yml
									
									
									
										generated
									
									
									
								
							| @@ -39,6 +39,15 @@ definitions: | ||||
|             BoardsCloudLimits is the representation of the limits for the | ||||
|             Boards server | ||||
|         x-go-package: github.com/mattermost/focalboard/server/model | ||||
|     BoardsStatistics: | ||||
|         description: BoardsStatistics is the representation of the statistics for the Boards server | ||||
|         x-go-package: github.com/mattermost/focalboard/server/model | ||||
|     Card: | ||||
|         title: Card represents a group of content blocks and properties. | ||||
|         x-go-package: github.com/mattermost/focalboard/server/model | ||||
|     CardPatch: | ||||
|         description: CardPatch is a patch for modifying cards | ||||
|         x-go-package: github.com/mattermost/focalboard/server/model | ||||
|     Category: | ||||
|         description: Category is a board category | ||||
|         x-go-package: github.com/mattermost/focalboard/server/model | ||||
| @@ -96,8 +105,8 @@ definitions: | ||||
|     User: | ||||
|         description: User is a user | ||||
|         x-go-package: github.com/mattermost/focalboard/server/model | ||||
|     UserPropPatch: | ||||
|         description: UserPropPatch is a user property patch | ||||
|     UserPreferencesPatch: | ||||
|         description: UserPreferencesPatch is a user property patch | ||||
|         x-go-package: github.com/mattermost/focalboard/server/model | ||||
| host: localhost | ||||
| info: | ||||
| @@ -559,6 +568,71 @@ paths: | ||||
|                         $ref: '#/definitions/ErrorResponse' | ||||
|             security: | ||||
|                 - BearerAuth: [] | ||||
|     /boards/{boardID}/cards: | ||||
|         get: | ||||
|             operationId: getCards | ||||
|             parameters: | ||||
|                 - description: Board ID | ||||
|                   in: path | ||||
|                   name: boardID | ||||
|                   required: true | ||||
|                   type: string | ||||
|                 - description: The page to select (default=0) | ||||
|                   in: query | ||||
|                   name: page | ||||
|                   type: integer | ||||
|                 - description: Number of cards to return per page(default=100) | ||||
|                   in: query | ||||
|                   name: per_page | ||||
|                   type: integer | ||||
|             produces: | ||||
|                 - application/json | ||||
|             responses: | ||||
|                 "200": | ||||
|                     description: success | ||||
|                     schema: | ||||
|                         items: | ||||
|                             $ref: '#/definitions/Card' | ||||
|                         type: array | ||||
|                 default: | ||||
|                     description: internal error | ||||
|                     schema: | ||||
|                         $ref: '#/definitions/ErrorResponse' | ||||
|             security: | ||||
|                 - BearerAuth: [] | ||||
|             summary: Fetches cards for the specified board. | ||||
|         post: | ||||
|             operationId: createCard | ||||
|             parameters: | ||||
|                 - description: Board ID | ||||
|                   in: path | ||||
|                   name: boardID | ||||
|                   required: true | ||||
|                   type: string | ||||
|                 - description: the card to create | ||||
|                   in: body | ||||
|                   name: Body | ||||
|                   required: true | ||||
|                   schema: | ||||
|                     $ref: '#/definitions/Card' | ||||
|                 - description: Disables notifications (for bulk data inserting) | ||||
|                   in: query | ||||
|                   name: disable_notify | ||||
|                   type: bool | ||||
|             produces: | ||||
|                 - application/json | ||||
|             responses: | ||||
|                 "200": | ||||
|                     description: success | ||||
|                     schema: | ||||
|                         $ref: '#/definitions/Card' | ||||
|                 default: | ||||
|                     description: internal error | ||||
|                     schema: | ||||
|                         $ref: '#/definitions/ErrorResponse' | ||||
|             security: | ||||
|                 - BearerAuth: [] | ||||
|             summary: Creates a new card for the specified board. | ||||
|     /boards/{boardID}/duplicate: | ||||
|         post: | ||||
|             description: Returns the new created board and all the blocks | ||||
| @@ -876,6 +950,62 @@ paths: | ||||
|                         $ref: '#/definitions/ErrorResponse' | ||||
|             security: | ||||
|                 - BearerAuth: [] | ||||
|     /cards/{cardID}: | ||||
|         get: | ||||
|             operationId: getCard | ||||
|             parameters: | ||||
|                 - description: Card ID | ||||
|                   in: path | ||||
|                   name: cardID | ||||
|                   required: true | ||||
|                   type: string | ||||
|             produces: | ||||
|                 - application/json | ||||
|             responses: | ||||
|                 "200": | ||||
|                     description: success | ||||
|                     schema: | ||||
|                         $ref: '#/definitions/Card' | ||||
|                 default: | ||||
|                     description: internal error | ||||
|                     schema: | ||||
|                         $ref: '#/definitions/ErrorResponse' | ||||
|             security: | ||||
|                 - BearerAuth: [] | ||||
|             summary: Fetches the specified card. | ||||
|     /cards/{cardID}/cards: | ||||
|         patch: | ||||
|             operationId: patchCard | ||||
|             parameters: | ||||
|                 - description: Card ID | ||||
|                   in: path | ||||
|                   name: cardID | ||||
|                   required: true | ||||
|                   type: string | ||||
|                 - description: the card patch | ||||
|                   in: body | ||||
|                   name: Body | ||||
|                   required: true | ||||
|                   schema: | ||||
|                     $ref: '#/definitions/CardPatch' | ||||
|                 - description: Disables notifications (for bulk data patching) | ||||
|                   in: query | ||||
|                   name: disable_notify | ||||
|                   type: bool | ||||
|             produces: | ||||
|                 - application/json | ||||
|             responses: | ||||
|                 "200": | ||||
|                     description: success | ||||
|                     schema: | ||||
|                         $ref: '#/definitions/Card' | ||||
|                 default: | ||||
|                     description: internal error | ||||
|                     schema: | ||||
|                         $ref: '#/definitions/ErrorResponse' | ||||
|             security: | ||||
|                 - BearerAuth: [] | ||||
|             summary: Patches the specified card. | ||||
|     /clientConfig: | ||||
|         get: | ||||
|             description: Returns the client configuration | ||||
| @@ -994,6 +1124,15 @@ paths: | ||||
|                         $ref: '#/definitions/ErrorResponse' | ||||
|             security: | ||||
|                 - BearerAuth: [] | ||||
|     /ping: | ||||
|         get: | ||||
|             operationId: ping | ||||
|             produces: | ||||
|                 - application/json | ||||
|             responses: | ||||
|                 "200": | ||||
|                     description: success | ||||
|             summary: Responds with server metadata if the web service is running. | ||||
|     /register: | ||||
|         post: | ||||
|             description: Register new user | ||||
| @@ -1016,6 +1155,23 @@ paths: | ||||
|                     description: internal error | ||||
|                     schema: | ||||
|                         $ref: '#/definitions/ErrorResponse' | ||||
|     /statistics: | ||||
|         get: | ||||
|             operationId: handleStatistics | ||||
|             produces: | ||||
|                 - application/json | ||||
|             responses: | ||||
|                 "200": | ||||
|                     description: success | ||||
|                     schema: | ||||
|                         $ref: '#/definitions/BoardStatistics' | ||||
|                 default: | ||||
|                     description: internal error | ||||
|                     schema: | ||||
|                         $ref: '#/definitions/ErrorResponse' | ||||
|             security: | ||||
|                 - BearerAuth: [] | ||||
|             summary: Fetches the statistic  of the server. | ||||
|     /subscriptions: | ||||
|         post: | ||||
|             operationId: createSubscription | ||||
| @@ -1748,7 +1904,7 @@ paths: | ||||
|                   name: Body | ||||
|                   required: true | ||||
|                   schema: | ||||
|                     $ref: '#/definitions/UserPropPatch' | ||||
|                     $ref: '#/definitions/UserPreferencesPatch' | ||||
|             produces: | ||||
|                 - application/json | ||||
|             responses: | ||||
|   | ||||
		Reference in New Issue
	
	Block a user