feat: page, sort and search stored media and delete several at once in the admin API
This commit is contained in:
1 parent
c39331aa75
commit
fb751ca57f
23 files changed
+1161
-213
No files matched your search
@@ -16,6 +16,7 @@ var (
|
||||
patternLoginRequestUsername = regexp.MustCompile(`^[a-z0-9_-]{3,32}$`)
|
||||
patternRedeemPairingCodeRequestCode = regexp.MustCompile(`^[2-9A-HJ-NP-Z]{8}$`)
|
||||
patternRegisterRequestUsername = regexp.MustCompile(`^[a-z0-9_-]{3,32}$`)
|
||||
patternStoredMediaRefKey = regexp.MustCompile(`^[0-9a-f]{64}$`)
|
||||
patternTrackIDWhenBilibili = regexp.MustCompile(`^BV[1-9A-HJ-NP-Za-km-z]{10}(?:/([2-9]|[1-9][0-9]{1,3}))?$`)
|
||||
)
|
||||
|
||||
@@ -182,6 +183,14 @@ func DecodeAdminSetGithubCredentialRequest(body []byte) (AdminSetGithubCredentia
|
||||
return decodeAdminSetGithubCredentialRequest(body, "")
|
||||
}
|
||||
|
||||
func DecodeAdminListMediaRequest(body []byte) (AdminListMediaRequest, error) {
|
||||
return decodeAdminListMediaRequest(body, "")
|
||||
}
|
||||
|
||||
func DecodeAdminRemoveMediaRequest(body []byte) (AdminRemoveMediaRequest, error) {
|
||||
return decodeAdminRemoveMediaRequest(body, "")
|
||||
}
|
||||
|
||||
func DecodeAdminUpdateSiteRequest(body []byte) (AdminUpdateSiteRequest, error) {
|
||||
return decodeAdminUpdateSiteRequest(body, "")
|
||||
}
|
||||
@@ -346,12 +355,66 @@ func decodeAdminCreateRoomRequest(raw json.RawMessage, path string) (AdminCreate
|
||||
return v, nil
|
||||
}
|
||||
|
||||
func decodeAdminListMediaRequest(raw json.RawMessage, path string) (AdminListMediaRequest, error) {
|
||||
var v AdminListMediaRequest
|
||||
m, err := decodeObject(raw, path, "page", "q", "sort")
|
||||
if err != nil {
|
||||
return v, err
|
||||
}
|
||||
if r, ok := m["page"]; ok {
|
||||
x, err := decodeInteger(r, field(path, "page"))
|
||||
if err != nil {
|
||||
return v, err
|
||||
}
|
||||
if err = checkMinimum(x, field(path, "page"), 1); err != nil {
|
||||
return v, err
|
||||
}
|
||||
v.Page = &x
|
||||
}
|
||||
if r, ok := m["q"]; ok {
|
||||
x, err := decodeString(r, field(path, "q"))
|
||||
if err != nil {
|
||||
return v, err
|
||||
}
|
||||
if err = checkMaxLength(x, field(path, "q"), 100); err != nil {
|
||||
return v, err
|
||||
}
|
||||
v.Q = &x
|
||||
}
|
||||
if r, ok := m["sort"]; ok {
|
||||
x, err := decodeMediaSort(r, field(path, "sort"))
|
||||
if err != nil {
|
||||
return v, err
|
||||
}
|
||||
v.Sort = &x
|
||||
}
|
||||
return v, nil
|
||||
}
|
||||
|
||||
func decodeAdminOpenRegistrationRequest(raw json.RawMessage, path string) (AdminOpenRegistrationRequest, error) {
|
||||
var v AdminOpenRegistrationRequest
|
||||
_, err := decodeObject(raw, path)
|
||||
return v, err
|
||||
}
|
||||
|
||||
func decodeAdminRemoveMediaRequest(raw json.RawMessage, path string) (AdminRemoveMediaRequest, error) {
|
||||
var v AdminRemoveMediaRequest
|
||||
m, err := decodeObject(raw, path, "media")
|
||||
if err != nil {
|
||||
return v, err
|
||||
}
|
||||
if err = requireFields(m, path, "media"); err != nil {
|
||||
return v, err
|
||||
}
|
||||
if v.Media, err = decodeArray(decodeStoredMediaRef, 50)(m["media"], field(path, "media")); err != nil {
|
||||
return v, err
|
||||
}
|
||||
if err = checkMinItems(v.Media, field(path, "media"), 1); err != nil {
|
||||
return v, err
|
||||
}
|
||||
return v, nil
|
||||
}
|
||||
|
||||
func decodeAdminResetAccountPasswordRequest(raw json.RawMessage, path string) (AdminResetAccountPasswordRequest, error) {
|
||||
var v AdminResetAccountPasswordRequest
|
||||
_, err := decodeObject(raw, path)
|
||||
@@ -912,6 +975,18 @@ func decodeLoginRequest(raw json.RawMessage, path string) (LoginRequest, error)
|
||||
return v, nil
|
||||
}
|
||||
|
||||
func decodeMediaSort(raw json.RawMessage, path string) (MediaSort, error) {
|
||||
s, err := decodeString(raw, path)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
switch v := MediaSort(s); v {
|
||||
case MediaSortStored, MediaSortIdle, MediaSortSize:
|
||||
return v, nil
|
||||
}
|
||||
return "", invalid(path, "取值应为 stored、idle、size 之一")
|
||||
}
|
||||
|
||||
func decodeMoveMyPlaylistItemsRequest(raw json.RawMessage, path string) (MoveMyPlaylistItemsRequest, error) {
|
||||
var v MoveMyPlaylistItemsRequest
|
||||
m, err := decodeObject(raw, path, "before", "tracks")
|
||||
@@ -1366,6 +1441,24 @@ func decodeStartGithubLoginRequest(raw json.RawMessage, path string) (StartGithu
|
||||
return v, nil
|
||||
}
|
||||
|
||||
func decodeStoredMediaRef(raw json.RawMessage, path string) (StoredMediaRef, error) {
|
||||
var v StoredMediaRef
|
||||
m, err := decodeObject(raw, path, "key")
|
||||
if err != nil {
|
||||
return v, err
|
||||
}
|
||||
if err = requireFields(m, path, "key"); err != nil {
|
||||
return v, err
|
||||
}
|
||||
if v.Key, err = decodeString(m["key"], field(path, "key")); err != nil {
|
||||
return v, err
|
||||
}
|
||||
if err = checkPattern(v.Key, field(path, "key"), patternStoredMediaRefKey); err != nil {
|
||||
return v, err
|
||||
}
|
||||
return v, nil
|
||||
}
|
||||
|
||||
func decodeTrack(raw json.RawMessage, path string) (Track, error) {
|
||||
var v Track
|
||||
m, err := decodeObject(raw, path, "id", "source")
|
||||
|
||||
+55
-11
@@ -309,11 +309,26 @@
|
||||
"source": {"$ref": "#/$defs/Source"},
|
||||
"link": {"type": "string", "description": "这首歌的页面:链接曲目是链接本身,B 站的歌是视频页面"},
|
||||
"title": {"type": "string"},
|
||||
"artist": {"type": "string", "description": "不知道时为空字符串"},
|
||||
"coverUrl": {"type": "string", "description": "可以直接打开的封面地址,没有封面时为空字符串"},
|
||||
"size": {"type": "integer", "description": "音频文件的字节数"},
|
||||
"storedAtMs": {"type": "integer"},
|
||||
"lastPlayedAtMs": {"anyOf": [{"type": "integer"}, {"type": "null"}], "description": "没有播放过时为 null"}
|
||||
},
|
||||
"required": ["key", "source", "link", "title", "size", "storedAtMs", "lastPlayedAtMs"]
|
||||
"required": ["key", "source", "link", "title", "artist", "coverUrl", "size", "storedAtMs", "lastPlayedAtMs"]
|
||||
},
|
||||
"MediaSort": {
|
||||
"type": "string",
|
||||
"description": "stored:存储时间从新到旧;idle:最近播放从早到晚,从没播放过的排最前;size:占用从大到小。三种排序都以曲目 ID 作为最后的排序键,翻页时不重复也不遗漏",
|
||||
"enum": ["stored", "idle", "size"]
|
||||
},
|
||||
"StoredMediaRef": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"key": {"type": "string", "description": "StoredMedia 的 key:64 个小写十六进制字符", "pattern": "^[0-9a-f]{64}$"}
|
||||
},
|
||||
"required": ["key"]
|
||||
},
|
||||
"SourceAccount": {
|
||||
"type": "object",
|
||||
@@ -1544,26 +1559,55 @@
|
||||
},
|
||||
{
|
||||
"name": "adminListMedia",
|
||||
"description": "已存储的链接曲目和 B 站的歌",
|
||||
"method": "GET",
|
||||
"path": "/api/admin/media",
|
||||
"description": "已存储的链接曲目和 B 站的歌,每页 50 首;页码超出最后一页时 items 为空,其余字段照常",
|
||||
"method": "POST",
|
||||
"path": "/api/admin/media/queries",
|
||||
"auth": "admin",
|
||||
"request": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"page": {"$ref": "#/$defs/Page", "description": "页码,从 1 开始,缺省为 1"},
|
||||
"sort": {"$ref": "#/$defs/MediaSort", "description": "缺省为 stored"},
|
||||
"q": {"type": "string", "description": "按标题搜索:标题包含它就算匹配,不区分大小写,% 和 _ 按字面匹配;缺省或为空时不搜索", "maxLength": 100}
|
||||
}
|
||||
},
|
||||
"response": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"items": {"type": "array", "items": {"$ref": "#/$defs/StoredMedia"}}
|
||||
"items": {"type": "array", "items": {"$ref": "#/$defs/StoredMedia"}},
|
||||
"total": {"type": "integer", "description": "匹配的歌曲数,不只是这一页"},
|
||||
"totalBytes": {"type": "integer", "description": "匹配的歌曲的音频字节数之和"},
|
||||
"page": {"type": "integer"},
|
||||
"pageSize": {"type": "integer", "description": "每页的条数,固定为 50"}
|
||||
},
|
||||
"required": ["items"]
|
||||
"required": ["items", "total", "totalBytes", "page", "pageSize"]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "adminDeleteMedia",
|
||||
"description": "删除一首已存储的歌的音频和封面,并清除它的准备结果",
|
||||
"method": "DELETE",
|
||||
"path": "/api/admin/media/{key}",
|
||||
"name": "adminRemoveMedia",
|
||||
"description": "删除若干首已存储的歌的音频和封面,并清除它们的准备结果,一次 1 到 50 首:正在房间里使用的不会删除,放进 inUse;不存在的忽略。逐首删除,中途出错时返回错误,出错之前已经删掉的不会恢复,用同样的请求重试即可",
|
||||
"method": "POST",
|
||||
"path": "/api/admin/media/removals",
|
||||
"auth": "admin",
|
||||
"status": 204
|
||||
"request": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"media": {"type": "array", "items": {"$ref": "#/$defs/StoredMediaRef"}, "minItems": 1, "maxItems": 50}
|
||||
},
|
||||
"required": ["media"]
|
||||
},
|
||||
"response": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"deleted": {"type": "array", "items": {"type": "string"}, "description": "删掉的歌的 key"},
|
||||
"inUse": {"type": "array", "items": {"type": "string"}, "description": "正在房间里使用、没有删除的歌的 key"}
|
||||
},
|
||||
"required": ["deleted", "inUse"]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "adminUpdateSite",
|
||||
|
||||
+149
-19
@@ -307,6 +307,26 @@
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"AdminListMediaRequest": {
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"page": {
|
||||
"description": "页码,从 1 开始,缺省为 1",
|
||||
"minimum": 1,
|
||||
"type": "integer"
|
||||
},
|
||||
"q": {
|
||||
"description": "按标题搜索:标题包含它就算匹配,不区分大小写,% 和 _ 按字面匹配;缺省或为空时不搜索",
|
||||
"maxLength": 100,
|
||||
"type": "string"
|
||||
},
|
||||
"sort": {
|
||||
"$ref": "#/components/schemas/MediaSort",
|
||||
"description": "缺省为 stored"
|
||||
}
|
||||
},
|
||||
"type": "object"
|
||||
},
|
||||
"AdminListMediaResponse": {
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
@@ -315,10 +335,29 @@
|
||||
"$ref": "#/components/schemas/StoredMedia"
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
"page": {
|
||||
"type": "integer"
|
||||
},
|
||||
"pageSize": {
|
||||
"description": "每页的条数,固定为 50",
|
||||
"type": "integer"
|
||||
},
|
||||
"total": {
|
||||
"description": "匹配的歌曲数,不只是这一页",
|
||||
"type": "integer"
|
||||
},
|
||||
"totalBytes": {
|
||||
"description": "匹配的歌曲的音频字节数之和",
|
||||
"type": "integer"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"items"
|
||||
"items",
|
||||
"total",
|
||||
"totalBytes",
|
||||
"page",
|
||||
"pageSize"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
@@ -341,6 +380,47 @@
|
||||
"additionalProperties": false,
|
||||
"type": "object"
|
||||
},
|
||||
"AdminRemoveMediaRequest": {
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"media": {
|
||||
"items": {
|
||||
"$ref": "#/components/schemas/StoredMediaRef"
|
||||
},
|
||||
"maxItems": 50,
|
||||
"minItems": 1,
|
||||
"type": "array"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"media"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"AdminRemoveMediaResponse": {
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"deleted": {
|
||||
"description": "删掉的歌的 key",
|
||||
"items": {
|
||||
"type": "string"
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
"inUse": {
|
||||
"description": "正在房间里使用、没有删除的歌的 key",
|
||||
"items": {
|
||||
"type": "string"
|
||||
},
|
||||
"type": "array"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"deleted",
|
||||
"inUse"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"AdminResetAccountPasswordRequest": {
|
||||
"additionalProperties": false,
|
||||
"type": "object"
|
||||
@@ -1134,6 +1214,15 @@
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"MediaSort": {
|
||||
"description": "stored:存储时间从新到旧;idle:最近播放从早到晚,从没播放过的排最前;size:占用从大到小。三种排序都以曲目 ID 作为最后的排序键,翻页时不重复也不遗漏",
|
||||
"enum": [
|
||||
"stored",
|
||||
"idle",
|
||||
"size"
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
"Member": {
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
@@ -2048,6 +2137,14 @@
|
||||
"StoredMedia": {
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"artist": {
|
||||
"description": "不知道时为空字符串",
|
||||
"type": "string"
|
||||
},
|
||||
"coverUrl": {
|
||||
"description": "可以直接打开的封面地址,没有封面时为空字符串",
|
||||
"type": "string"
|
||||
},
|
||||
"key": {
|
||||
"description": "曲目 ID 的 SHA-256(十六进制),用于删除;链接曲目的 ID 是规范化之后的链接",
|
||||
"type": "string"
|
||||
@@ -2086,12 +2183,28 @@
|
||||
"source",
|
||||
"link",
|
||||
"title",
|
||||
"artist",
|
||||
"coverUrl",
|
||||
"size",
|
||||
"storedAtMs",
|
||||
"lastPlayedAtMs"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"StoredMediaRef": {
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"key": {
|
||||
"description": "StoredMedia 的 key:64 个小写十六进制字符",
|
||||
"pattern": "^[0-9a-f]{64}$",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"key"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"Track": {
|
||||
"additionalProperties": false,
|
||||
"allOf": [
|
||||
@@ -2265,7 +2378,7 @@
|
||||
},
|
||||
"info": {
|
||||
"title": "Alisten",
|
||||
"version": "6bee23791ffa52ad"
|
||||
"version": "ce462456c63356c6"
|
||||
},
|
||||
"openapi": "3.1.0",
|
||||
"paths": {
|
||||
@@ -3062,9 +3175,19 @@
|
||||
"summary": "写入或覆盖 YouTube cookies,不返回 cookies"
|
||||
}
|
||||
},
|
||||
"/api/admin/media": {
|
||||
"get": {
|
||||
"/api/admin/media/queries": {
|
||||
"post": {
|
||||
"operationId": "adminListMedia",
|
||||
"requestBody": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/AdminListMediaRequest"
|
||||
}
|
||||
}
|
||||
},
|
||||
"required": true
|
||||
},
|
||||
"responses": {
|
||||
"200": {
|
||||
"content": {
|
||||
@@ -3092,24 +3215,31 @@
|
||||
"adminToken": []
|
||||
}
|
||||
],
|
||||
"summary": "已存储的链接曲目和 B 站的歌"
|
||||
"summary": "已存储的链接曲目和 B 站的歌,每页 50 首;页码超出最后一页时 items 为空,其余字段照常"
|
||||
}
|
||||
},
|
||||
"/api/admin/media/{key}": {
|
||||
"delete": {
|
||||
"operationId": "adminDeleteMedia",
|
||||
"parameters": [
|
||||
{
|
||||
"in": "path",
|
||||
"name": "key",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"type": "string"
|
||||
"/api/admin/media/removals": {
|
||||
"post": {
|
||||
"operationId": "adminRemoveMedia",
|
||||
"requestBody": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/AdminRemoveMediaRequest"
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
},
|
||||
"required": true
|
||||
},
|
||||
"responses": {
|
||||
"204": {
|
||||
"200": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/AdminRemoveMediaResponse"
|
||||
}
|
||||
}
|
||||
},
|
||||
"description": "成功"
|
||||
},
|
||||
"default": {
|
||||
@@ -3128,7 +3258,7 @@
|
||||
"adminToken": []
|
||||
}
|
||||
],
|
||||
"summary": "删除一首已存储的歌的音频和封面,并清除它的准备结果"
|
||||
"summary": "删除若干首已存储的歌的音频和封面,并清除它们的准备结果,一次 1 到 50 首:正在房间里使用的不会删除,放进 inUse;不存在的忽略。逐首删除,中途出错时返回错误,出错之前已经删掉的不会恢复,用同样的请求重试即可"
|
||||
}
|
||||
},
|
||||
"/api/admin/registration": {
|
||||
|
||||
+56
-4
@@ -4,7 +4,7 @@ package protocol
|
||||
|
||||
import "encoding/json"
|
||||
|
||||
const Version = "6bee23791ffa52ad"
|
||||
const Version = "ce462456c63356c6"
|
||||
|
||||
type APIKey struct {
|
||||
Key string `json:"key"`
|
||||
@@ -95,8 +95,18 @@ type AdminGetYoutubeCredentialResponse struct {
|
||||
UpdatedAtMs int64 `json:"updatedAtMs"`
|
||||
}
|
||||
|
||||
type AdminListMediaRequest struct {
|
||||
Page *int64 `json:"page,omitempty"`
|
||||
Q *string `json:"q,omitempty"`
|
||||
Sort *MediaSort `json:"sort,omitempty"`
|
||||
}
|
||||
|
||||
type AdminListMediaResponse struct {
|
||||
Items []StoredMedia `json:"items"`
|
||||
Items []StoredMedia `json:"items"`
|
||||
Page int64 `json:"page"`
|
||||
PageSize int64 `json:"pageSize"`
|
||||
Total int64 `json:"total"`
|
||||
TotalBytes int64 `json:"totalBytes"`
|
||||
}
|
||||
|
||||
func (v AdminListMediaResponse) MarshalJSON() ([]byte, error) {
|
||||
@@ -121,6 +131,34 @@ func (v AdminListRoomsResponse) MarshalJSON() ([]byte, error) {
|
||||
|
||||
type AdminOpenRegistrationRequest struct{}
|
||||
|
||||
type AdminRemoveMediaRequest struct {
|
||||
Media []StoredMediaRef `json:"media"`
|
||||
}
|
||||
|
||||
func (v AdminRemoveMediaRequest) MarshalJSON() ([]byte, error) {
|
||||
type plain AdminRemoveMediaRequest
|
||||
if v.Media == nil {
|
||||
v.Media = []StoredMediaRef{}
|
||||
}
|
||||
return json.Marshal(plain(v))
|
||||
}
|
||||
|
||||
type AdminRemoveMediaResponse struct {
|
||||
Deleted []string `json:"deleted"`
|
||||
InUse []string `json:"inUse"`
|
||||
}
|
||||
|
||||
func (v AdminRemoveMediaResponse) MarshalJSON() ([]byte, error) {
|
||||
type plain AdminRemoveMediaResponse
|
||||
if v.Deleted == nil {
|
||||
v.Deleted = []string{}
|
||||
}
|
||||
if v.InUse == nil {
|
||||
v.InUse = []string{}
|
||||
}
|
||||
return json.Marshal(plain(v))
|
||||
}
|
||||
|
||||
type AdminResetAccountPasswordRequest struct{}
|
||||
|
||||
type AdminResetAccountPasswordResponse struct {
|
||||
@@ -444,6 +482,14 @@ type LoginResponse struct {
|
||||
MemberToken string `json:"memberToken"`
|
||||
}
|
||||
|
||||
type MediaSort string
|
||||
|
||||
const (
|
||||
MediaSortStored MediaSort = "stored"
|
||||
MediaSortIdle MediaSort = "idle"
|
||||
MediaSortSize MediaSort = "size"
|
||||
)
|
||||
|
||||
type Member struct {
|
||||
AvatarHash string `json:"avatarHash"`
|
||||
ID string `json:"id"`
|
||||
@@ -854,6 +900,8 @@ type StartGithubLoginResponse struct {
|
||||
}
|
||||
|
||||
type StoredMedia struct {
|
||||
Artist string `json:"artist"`
|
||||
CoverURL string `json:"coverUrl"`
|
||||
Key string `json:"key"`
|
||||
LastPlayedAtMs *int64 `json:"lastPlayedAtMs"`
|
||||
Link string `json:"link"`
|
||||
@@ -863,6 +911,10 @@ type StoredMedia struct {
|
||||
Title string `json:"title"`
|
||||
}
|
||||
|
||||
type StoredMediaRef struct {
|
||||
Key string `json:"key"`
|
||||
}
|
||||
|
||||
type Track struct {
|
||||
ID string `json:"id"`
|
||||
Source Source `json:"source"`
|
||||
@@ -985,8 +1037,8 @@ var (
|
||||
RouteAdminGetGithubCredential = Route{Pattern: "GET /api/admin/credentials/github", Auth: AuthAdmin, Status: 200}
|
||||
RouteAdminSetGithubCredential = Route{Pattern: "PUT /api/admin/credentials/github", Auth: AuthAdmin, Status: 204}
|
||||
RouteAdminDeleteGithubCredential = Route{Pattern: "DELETE /api/admin/credentials/github", Auth: AuthAdmin, Status: 204}
|
||||
RouteAdminListMedia = Route{Pattern: "GET /api/admin/media", Auth: AuthAdmin, Status: 200}
|
||||
RouteAdminDeleteMedia = Route{Pattern: "DELETE /api/admin/media/{key}", Auth: AuthAdmin, Status: 204}
|
||||
RouteAdminListMedia = Route{Pattern: "POST /api/admin/media/queries", Auth: AuthAdmin, Status: 200}
|
||||
RouteAdminRemoveMedia = Route{Pattern: "POST /api/admin/media/removals", Auth: AuthAdmin, Status: 200}
|
||||
RouteAdminUpdateSite = Route{Pattern: "PATCH /api/admin/site", Auth: AuthAdmin, Status: 200}
|
||||
RouteAdminOpenRegistration = Route{Pattern: "PUT /api/admin/registration", Auth: AuthAdmin, Status: 204}
|
||||
RouteAdminCloseRegistration = Route{Pattern: "DELETE /api/admin/registration", Auth: AuthAdmin, Status: 204}
|
||||
|
||||
Reference in new issue
Block a user