chore: remove openid field from user

This commit is contained in:
Steven
2023-09-14 22:57:27 +08:00
parent 42bd9b194b
commit 33d9c13b7e
31 changed files with 298 additions and 819 deletions

View File

@ -1,6 +1,7 @@
package v1 package v1
import ( import (
"context"
"encoding/json" "encoding/json"
"fmt" "fmt"
"net/http" "net/http"
@ -13,6 +14,7 @@ import (
"github.com/usememos/memos/common/util" "github.com/usememos/memos/common/util"
"github.com/usememos/memos/plugin/idp" "github.com/usememos/memos/plugin/idp"
"github.com/usememos/memos/plugin/idp/oauth2" "github.com/usememos/memos/plugin/idp/oauth2"
storepb "github.com/usememos/memos/proto/gen/store"
"github.com/usememos/memos/store" "github.com/usememos/memos/store"
"golang.org/x/crypto/bcrypt" "golang.org/x/crypto/bcrypt"
) )
@ -100,6 +102,9 @@ func (s *APIV1Service) SignIn(c echo.Context) error {
if err != nil { if err != nil {
return echo.NewHTTPError(http.StatusInternalServerError, fmt.Sprintf("failed to generate tokens, err: %s", err)).SetInternal(err) return echo.NewHTTPError(http.StatusInternalServerError, fmt.Sprintf("failed to generate tokens, err: %s", err)).SetInternal(err)
} }
if err := s.UpsertAccessTokenToStore(ctx, user, accessToken); err != nil {
return echo.NewHTTPError(http.StatusInternalServerError, fmt.Sprintf("failed to upsert access token, err: %s", err)).SetInternal(err)
}
if err := s.createAuthSignInActivity(c, user); err != nil { if err := s.createAuthSignInActivity(c, user); err != nil {
return echo.NewHTTPError(http.StatusInternalServerError, "Failed to create activity").SetInternal(err) return echo.NewHTTPError(http.StatusInternalServerError, "Failed to create activity").SetInternal(err)
} }
@ -198,7 +203,6 @@ func (s *APIV1Service) SignInSSO(c echo.Context) error {
Role: store.RoleUser, Role: store.RoleUser,
Nickname: userInfo.DisplayName, Nickname: userInfo.DisplayName,
Email: userInfo.Email, Email: userInfo.Email,
OpenID: util.GenUUID(),
} }
password, err := util.RandomString(20) password, err := util.RandomString(20)
if err != nil { if err != nil {
@ -222,6 +226,9 @@ func (s *APIV1Service) SignInSSO(c echo.Context) error {
if err != nil { if err != nil {
return echo.NewHTTPError(http.StatusInternalServerError, fmt.Sprintf("failed to generate tokens, err: %s", err)).SetInternal(err) return echo.NewHTTPError(http.StatusInternalServerError, fmt.Sprintf("failed to generate tokens, err: %s", err)).SetInternal(err)
} }
if err := s.UpsertAccessTokenToStore(ctx, user, accessToken); err != nil {
return echo.NewHTTPError(http.StatusInternalServerError, fmt.Sprintf("failed to upsert access token, err: %s", err)).SetInternal(err)
}
if err := s.createAuthSignInActivity(c, user); err != nil { if err := s.createAuthSignInActivity(c, user); err != nil {
return echo.NewHTTPError(http.StatusInternalServerError, "Failed to create activity").SetInternal(err) return echo.NewHTTPError(http.StatusInternalServerError, "Failed to create activity").SetInternal(err)
} }
@ -277,7 +284,6 @@ func (s *APIV1Service) SignUp(c echo.Context) error {
// The new signup user should be normal user by default. // The new signup user should be normal user by default.
Role: store.RoleUser, Role: store.RoleUser,
Nickname: signup.Username, Nickname: signup.Username,
OpenID: util.GenUUID(),
} }
if len(existedHostUsers) == 0 { if len(existedHostUsers) == 0 {
// Change the default role to host if there is no host user. // Change the default role to host if there is no host user.
@ -316,6 +322,9 @@ func (s *APIV1Service) SignUp(c echo.Context) error {
if err != nil { if err != nil {
return echo.NewHTTPError(http.StatusInternalServerError, fmt.Sprintf("failed to generate tokens, err: %s", err)).SetInternal(err) return echo.NewHTTPError(http.StatusInternalServerError, fmt.Sprintf("failed to generate tokens, err: %s", err)).SetInternal(err)
} }
if err := s.UpsertAccessTokenToStore(ctx, user, accessToken); err != nil {
return echo.NewHTTPError(http.StatusInternalServerError, fmt.Sprintf("failed to upsert access token, err: %s", err)).SetInternal(err)
}
if err := s.createAuthSignUpActivity(c, user); err != nil { if err := s.createAuthSignUpActivity(c, user); err != nil {
return echo.NewHTTPError(http.StatusInternalServerError, "Failed to create activity").SetInternal(err) return echo.NewHTTPError(http.StatusInternalServerError, "Failed to create activity").SetInternal(err)
} }
@ -325,6 +334,30 @@ func (s *APIV1Service) SignUp(c echo.Context) error {
return c.JSON(http.StatusOK, userMessage) return c.JSON(http.StatusOK, userMessage)
} }
func (s *APIV1Service) UpsertAccessTokenToStore(ctx context.Context, user *store.User, accessToken string) error {
userAccessTokens, err := s.Store.GetUserAccessTokens(ctx, user.ID)
if err != nil {
return errors.Wrap(err, "failed to get user access tokens")
}
userAccessToken := storepb.AccessTokensUserSetting_AccessToken{
AccessToken: accessToken,
Description: "Account sign in",
}
userAccessTokens = append(userAccessTokens, &userAccessToken)
if _, err := s.Store.UpsertUserSettingV1(ctx, &storepb.UserSetting{
UserId: user.ID,
Key: storepb.UserSettingKey_USER_SETTING_ACCESS_TOKENS,
Value: &storepb.UserSetting_AccessTokens{
AccessTokens: &storepb.AccessTokensUserSetting{
AccessTokens: userAccessTokens,
},
},
}); err != nil {
return echo.NewHTTPError(http.StatusInternalServerError, fmt.Sprintf("failed to upsert user setting, err: %s", err)).SetInternal(err)
}
return nil
}
func (s *APIV1Service) createAuthSignInActivity(c echo.Context, user *store.User) error { func (s *APIV1Service) createAuthSignInActivity(c echo.Context, user *store.User) error {
ctx := c.Request().Context() ctx := c.Request().Context()
payload := ActivityUserAuthSignInPayload{ payload := ActivityUserAuthSignInPayload{

View File

@ -209,11 +209,6 @@ const docTemplate = `{
} }
}, },
"post": { "post": {
"security": [
{
"ApiKeyAuth": []
}
],
"consumes": [ "consumes": [
"application/json" "application/json"
], ],
@ -256,11 +251,6 @@ const docTemplate = `{
}, },
"/api/v1/idp/{idpId}": { "/api/v1/idp/{idpId}": {
"get": { "get": {
"security": [
{
"ApiKeyAuth": []
}
],
"consumes": [ "consumes": [
"application/json" "application/json"
], ],
@ -302,11 +292,6 @@ const docTemplate = `{
} }
}, },
"delete": { "delete": {
"security": [
{
"ApiKeyAuth": []
}
],
"consumes": [ "consumes": [
"application/json" "application/json"
], ],
@ -345,11 +330,6 @@ const docTemplate = `{
} }
}, },
"patch": { "patch": {
"security": [
{
"ApiKeyAuth": []
}
],
"consumes": [ "consumes": [
"application/json" "application/json"
], ],
@ -399,11 +379,6 @@ const docTemplate = `{
}, },
"/api/v1/memo": { "/api/v1/memo": {
"get": { "get": {
"security": [
{
"ApiKeyAuth": []
}
],
"produces": [ "produces": [
"application/json" "application/json"
], ],
@ -484,11 +459,6 @@ const docTemplate = `{
} }
}, },
"post": { "post": {
"security": [
{
"ApiKeyAuth": []
}
],
"description": "Visibility can be PUBLIC, PROTECTED or PRIVATE\n*You should omit fields to use their default values", "description": "Visibility can be PUBLIC, PROTECTED or PRIVATE\n*You should omit fields to use their default values",
"consumes": [ "consumes": [
"application/json" "application/json"
@ -535,11 +505,6 @@ const docTemplate = `{
}, },
"/api/v1/memo/all": { "/api/v1/memo/all": {
"get": { "get": {
"security": [
{
"ApiKeyAuth": []
}
],
"description": "This should also list protected memos if the user is logged in\nAuthentication is optional", "description": "This should also list protected memos if the user is logged in\nAuthentication is optional",
"produces": [ "produces": [
"application/json" "application/json"
@ -667,11 +632,6 @@ const docTemplate = `{
} }
}, },
"delete": { "delete": {
"security": [
{
"ApiKeyAuth": []
}
],
"produces": [ "produces": [
"application/json" "application/json"
], ],
@ -710,11 +670,6 @@ const docTemplate = `{
} }
}, },
"patch": { "patch": {
"security": [
{
"ApiKeyAuth": []
}
],
"description": "Visibility can be PUBLIC, PROTECTED or PRIVATE\n*You should omit fields to use their default values", "description": "Visibility can be PUBLIC, PROTECTED or PRIVATE\n*You should omit fields to use their default values",
"consumes": [ "consumes": [
"application/json" "application/json"
@ -768,11 +723,6 @@ const docTemplate = `{
}, },
"/api/v1/memo/{memoId}/organizer": { "/api/v1/memo/{memoId}/organizer": {
"post": { "post": {
"security": [
{
"ApiKeyAuth": []
}
],
"consumes": [ "consumes": [
"application/json" "application/json"
], ],
@ -1004,11 +954,6 @@ const docTemplate = `{
} }
}, },
"post": { "post": {
"security": [
{
"ApiKeyAuth": []
}
],
"consumes": [ "consumes": [
"application/json" "application/json"
], ],
@ -1058,11 +1003,6 @@ const docTemplate = `{
}, },
"/api/v1/memo/{memoId}/resource/{resourceId}": { "/api/v1/memo/{memoId}/resource/{resourceId}": {
"delete": { "delete": {
"security": [
{
"ApiKeyAuth": []
}
],
"consumes": [ "consumes": [
"application/json" "application/json"
], ],
@ -1129,11 +1069,6 @@ const docTemplate = `{
}, },
"/api/v1/resource": { "/api/v1/resource": {
"get": { "get": {
"security": [
{
"ApiKeyAuth": []
}
],
"produces": [ "produces": [
"application/json" "application/json"
], ],
@ -1174,11 +1109,6 @@ const docTemplate = `{
} }
}, },
"post": { "post": {
"security": [
{
"ApiKeyAuth": []
}
],
"consumes": [ "consumes": [
"application/json" "application/json"
], ],
@ -1221,11 +1151,6 @@ const docTemplate = `{
}, },
"/api/v1/resource/blob": { "/api/v1/resource/blob": {
"post": { "post": {
"security": [
{
"ApiKeyAuth": []
}
],
"consumes": [ "consumes": [
"multipart/form-data" "multipart/form-data"
], ],
@ -1266,11 +1191,6 @@ const docTemplate = `{
}, },
"/api/v1/resource/{resourceId}": { "/api/v1/resource/{resourceId}": {
"delete": { "delete": {
"security": [
{
"ApiKeyAuth": []
}
],
"produces": [ "produces": [
"application/json" "application/json"
], ],
@ -1309,11 +1229,6 @@ const docTemplate = `{
} }
}, },
"patch": { "patch": {
"security": [
{
"ApiKeyAuth": []
}
],
"produces": [ "produces": [
"application/json" "application/json"
], ],
@ -1388,11 +1303,6 @@ const docTemplate = `{
}, },
"/api/v1/storage": { "/api/v1/storage": {
"get": { "get": {
"security": [
{
"ApiKeyAuth": []
}
],
"produces": [ "produces": [
"application/json" "application/json"
], ],
@ -1419,11 +1329,6 @@ const docTemplate = `{
} }
}, },
"post": { "post": {
"security": [
{
"ApiKeyAuth": []
}
],
"consumes": [ "consumes": [
"application/json" "application/json"
], ],
@ -1466,11 +1371,6 @@ const docTemplate = `{
}, },
"/api/v1/storage/{storageId}": { "/api/v1/storage/{storageId}": {
"delete": { "delete": {
"security": [
{
"ApiKeyAuth": []
}
],
"produces": [ "produces": [
"application/json" "application/json"
], ],
@ -1506,11 +1406,6 @@ const docTemplate = `{
} }
}, },
"patch": { "patch": {
"security": [
{
"ApiKeyAuth": []
}
],
"produces": [ "produces": [
"application/json" "application/json"
], ],
@ -1557,11 +1452,6 @@ const docTemplate = `{
}, },
"/api/v1/system/setting": { "/api/v1/system/setting": {
"get": { "get": {
"security": [
{
"ApiKeyAuth": []
}
],
"produces": [ "produces": [
"application/json" "application/json"
], ],
@ -1588,11 +1478,6 @@ const docTemplate = `{
} }
}, },
"post": { "post": {
"security": [
{
"ApiKeyAuth": []
}
],
"consumes": [ "consumes": [
"application/json" "application/json"
], ],
@ -1638,11 +1523,6 @@ const docTemplate = `{
}, },
"/api/v1/system/vacuum": { "/api/v1/system/vacuum": {
"post": { "post": {
"security": [
{
"ApiKeyAuth": []
}
],
"produces": [ "produces": [
"application/json" "application/json"
], ],
@ -1668,11 +1548,6 @@ const docTemplate = `{
}, },
"/api/v1/tag": { "/api/v1/tag": {
"get": { "get": {
"security": [
{
"ApiKeyAuth": []
}
],
"produces": [ "produces": [
"application/json" "application/json"
], ],
@ -1699,11 +1574,6 @@ const docTemplate = `{
} }
}, },
"post": { "post": {
"security": [
{
"ApiKeyAuth": []
}
],
"consumes": [ "consumes": [
"application/json" "application/json"
], ],
@ -1746,11 +1616,6 @@ const docTemplate = `{
}, },
"/api/v1/tag/delete": { "/api/v1/tag/delete": {
"post": { "post": {
"security": [
{
"ApiKeyAuth": []
}
],
"consumes": [ "consumes": [
"application/json" "application/json"
], ],
@ -1793,11 +1658,6 @@ const docTemplate = `{
}, },
"/api/v1/tag/suggestion": { "/api/v1/tag/suggestion": {
"get": { "get": {
"security": [
{
"ApiKeyAuth": []
}
],
"produces": [ "produces": [
"application/json" "application/json"
], ],
@ -1894,11 +1754,6 @@ const docTemplate = `{
}, },
"/api/v1/user/me": { "/api/v1/user/me": {
"get": { "get": {
"security": [
{
"ApiKeyAuth": []
}
],
"produces": [ "produces": [
"application/json" "application/json"
], ],
@ -1958,11 +1813,6 @@ const docTemplate = `{
}, },
"/api/v1/user/setting": { "/api/v1/user/setting": {
"post": { "post": {
"security": [
{
"ApiKeyAuth": []
}
],
"consumes": [ "consumes": [
"application/json" "application/json"
], ],
@ -1988,7 +1838,7 @@ const docTemplate = `{
"200": { "200": {
"description": "Created user setting", "description": "Created user setting",
"schema": { "schema": {
"$ref": "#/definitions/store.UserSetting" "$ref": "#/definitions/github_com_usememos_memos_store.UserSetting"
} }
}, },
"400": { "400": {
@ -2300,6 +2150,20 @@ const docTemplate = `{
} }
} }
}, },
"github_com_usememos_memos_store.UserSetting": {
"type": "object",
"properties": {
"key": {
"type": "string"
},
"userID": {
"type": "integer"
},
"value": {
"type": "string"
}
}
},
"profile.Profile": { "profile.Profile": {
"type": "object", "type": "object",
"properties": { "properties": {
@ -2582,9 +2446,6 @@ const docTemplate = `{
"nickname": { "nickname": {
"type": "string" "type": "string"
}, },
"openID": {
"type": "string"
},
"passwordHash": { "passwordHash": {
"type": "string" "type": "string"
}, },
@ -2608,20 +2469,6 @@ const docTemplate = `{
} }
} }
}, },
"store.UserSetting": {
"type": "object",
"properties": {
"key": {
"type": "string"
},
"userID": {
"type": "integer"
},
"value": {
"type": "string"
}
}
},
"store.Visibility": { "store.Visibility": {
"type": "string", "type": "string",
"enum": [ "enum": [
@ -3205,9 +3052,6 @@ const docTemplate = `{
"password": { "password": {
"type": "string" "type": "string"
}, },
"resetOpenId": {
"type": "boolean"
},
"rowStatus": { "rowStatus": {
"$ref": "#/definitions/v1.RowStatus" "$ref": "#/definitions/v1.RowStatus"
}, },
@ -3297,9 +3141,6 @@ const docTemplate = `{
"nickname": { "nickname": {
"type": "string" "type": "string"
}, },
"openId": {
"type": "string"
},
"role": { "role": {
"$ref": "#/definitions/v1.Role" "$ref": "#/definitions/v1.Role"
}, },
@ -3369,16 +3210,8 @@ const docTemplate = `{
] ]
} }
}, },
"securityDefinitions": {
"ApiKeyAuth": {
"description": "Insert your Open ID API Key here.",
"type": "apiKey",
"name": "openId",
"in": "query"
}
},
"externalDocs": { "externalDocs": {
"description": "Find out more about Memos", "description": "Find out more about Memos.",
"url": "https://usememos.com/" "url": "https://usememos.com/"
} }
}` }`

View File

@ -124,7 +124,6 @@ func (s *APIV1Service) GetIdentityProviderList(c echo.Context) error {
// @Failure 401 {object} nil "Missing user in session | Unauthorized" // @Failure 401 {object} nil "Missing user in session | Unauthorized"
// @Failure 400 {object} nil "Malformatted post identity provider request" // @Failure 400 {object} nil "Malformatted post identity provider request"
// @Failure 500 {object} nil "Failed to find user | Failed to create identity provider" // @Failure 500 {object} nil "Failed to find user | Failed to create identity provider"
// @Security ApiKeyAuth
// @Router /api/v1/idp [POST] // @Router /api/v1/idp [POST]
func (s *APIV1Service) CreateIdentityProvider(c echo.Context) error { func (s *APIV1Service) CreateIdentityProvider(c echo.Context) error {
ctx := c.Request().Context() ctx := c.Request().Context()
@ -172,7 +171,6 @@ func (s *APIV1Service) CreateIdentityProvider(c echo.Context) error {
// @Failure 401 {object} nil "Missing user in session | Unauthorized" // @Failure 401 {object} nil "Missing user in session | Unauthorized"
// @Failure 404 {object} nil "Identity provider not found" // @Failure 404 {object} nil "Identity provider not found"
// @Failure 500 {object} nil "Failed to find identity provider list | Failed to find user" // @Failure 500 {object} nil "Failed to find identity provider list | Failed to find user"
// @Security ApiKeyAuth
// @Router /api/v1/idp/{idpId} [GET] // @Router /api/v1/idp/{idpId} [GET]
func (s *APIV1Service) GetIdentityProvider(c echo.Context) error { func (s *APIV1Service) GetIdentityProvider(c echo.Context) error {
ctx := c.Request().Context() ctx := c.Request().Context()
@ -219,7 +217,6 @@ func (s *APIV1Service) GetIdentityProvider(c echo.Context) error {
// @Failure 400 {object} nil "ID is not a number: %s | Malformatted patch identity provider request" // @Failure 400 {object} nil "ID is not a number: %s | Malformatted patch identity provider request"
// @Failure 401 {object} nil "Missing user in session | Unauthorized" // @Failure 401 {object} nil "Missing user in session | Unauthorized"
// @Failure 500 {object} nil "Failed to find user | Failed to patch identity provider" // @Failure 500 {object} nil "Failed to find user | Failed to patch identity provider"
// @Security ApiKeyAuth
// @Router /api/v1/idp/{idpId} [DELETE] // @Router /api/v1/idp/{idpId} [DELETE]
func (s *APIV1Service) DeleteIdentityProvider(c echo.Context) error { func (s *APIV1Service) DeleteIdentityProvider(c echo.Context) error {
ctx := c.Request().Context() ctx := c.Request().Context()
@ -261,7 +258,6 @@ func (s *APIV1Service) DeleteIdentityProvider(c echo.Context) error {
// @Failure 400 {object} nil "ID is not a number: %s | Malformatted patch identity provider request" // @Failure 400 {object} nil "ID is not a number: %s | Malformatted patch identity provider request"
// @Failure 401 {object} nil "Missing user in session | Unauthorized // @Failure 401 {object} nil "Missing user in session | Unauthorized
// @Failure 500 {object} nil "Failed to find user | Failed to patch identity provider" // @Failure 500 {object} nil "Failed to find user | Failed to patch identity provider"
// @Security ApiKeyAuth
// @Router /api/v1/idp/{idpId} [PATCH] // @Router /api/v1/idp/{idpId} [PATCH]
func (s *APIV1Service) UpdateIdentityProvider(c echo.Context) error { func (s *APIV1Service) UpdateIdentityProvider(c echo.Context) error {
ctx := c.Request().Context() ctx := c.Request().Context()

View File

@ -128,7 +128,6 @@ func JWTMiddleware(server *APIV1Service, next echo.HandlerFunc, secret string) e
} }
func (s *APIV1Service) defaultAuthSkipper(c echo.Context) bool { func (s *APIV1Service) defaultAuthSkipper(c echo.Context) bool {
ctx := c.Request().Context()
path := c.Path() path := c.Path()
// Skip auth. // Skip auth.
@ -136,21 +135,5 @@ func (s *APIV1Service) defaultAuthSkipper(c echo.Context) bool {
return true return true
} }
// If there is openId in query string and related user is found, then skip auth.
openID := c.QueryParam("openId")
if openID != "" {
user, err := s.Store.GetUser(ctx, &store.FindUser{
OpenID: &openID,
})
if err != nil {
return false
}
if user != nil {
// Stores userID into context.
c.Set(userIDContextKey, user.ID)
return true
}
}
return false return false
} }

View File

@ -139,7 +139,6 @@ func (s *APIV1Service) registerMemoRoutes(g *echo.Group) {
// @Success 200 {object} []store.Memo "Memo list" // @Success 200 {object} []store.Memo "Memo list"
// @Failure 400 {object} nil "Missing user to find memo" // @Failure 400 {object} nil "Missing user to find memo"
// @Failure 500 {object} nil "Failed to get memo display with updated ts setting value | Failed to fetch memo list | Failed to compose memo response" // @Failure 500 {object} nil "Failed to get memo display with updated ts setting value | Failed to fetch memo list | Failed to compose memo response"
// @Security ApiKeyAuth
// @Router /api/v1/memo [GET] // @Router /api/v1/memo [GET]
func (s *APIV1Service) GetMemoList(c echo.Context) error { func (s *APIV1Service) GetMemoList(c echo.Context) error {
ctx := c.Request().Context() ctx := c.Request().Context()
@ -239,7 +238,6 @@ func (s *APIV1Service) GetMemoList(c echo.Context) error {
// @Failure 401 {object} nil "Missing user in session" // @Failure 401 {object} nil "Missing user in session"
// @Failure 404 {object} nil "User not found | Memo not found: %d" // @Failure 404 {object} nil "User not found | Memo not found: %d"
// @Failure 500 {object} nil "Failed to find user setting | Failed to unmarshal user setting value | Failed to find system setting | Failed to unmarshal system setting | Failed to find user | Failed to create memo | Failed to create activity | Failed to upsert memo resource | Failed to upsert memo relation | Failed to compose memo | Failed to compose memo response" // @Failure 500 {object} nil "Failed to find user setting | Failed to unmarshal user setting value | Failed to find system setting | Failed to unmarshal system setting | Failed to find user | Failed to create memo | Failed to create activity | Failed to upsert memo resource | Failed to upsert memo relation | Failed to compose memo | Failed to compose memo response"
// @Security ApiKeyAuth
// @Router /api/v1/memo [POST] // @Router /api/v1/memo [POST]
// //
// NOTES: // NOTES:
@ -398,7 +396,6 @@ func (s *APIV1Service) CreateMemo(c echo.Context) error {
// @Param offset query int false "Offset" // @Param offset query int false "Offset"
// @Success 200 {object} []store.Memo "Memo list" // @Success 200 {object} []store.Memo "Memo list"
// @Failure 500 {object} nil "Failed to get memo display with updated ts setting value | Failed to fetch all memo list | Failed to compose memo response" // @Failure 500 {object} nil "Failed to get memo display with updated ts setting value | Failed to fetch all memo list | Failed to compose memo response"
// @Security ApiKeyAuth
// @Router /api/v1/memo/all [GET] // @Router /api/v1/memo/all [GET]
// //
// NOTES: // NOTES:
@ -575,7 +572,6 @@ func (s *APIV1Service) GetMemo(c echo.Context) error {
// @Failure 401 {object} nil "Missing user in session | Unauthorized" // @Failure 401 {object} nil "Missing user in session | Unauthorized"
// @Failure 404 {object} nil "Memo not found: %d" // @Failure 404 {object} nil "Memo not found: %d"
// @Failure 500 {object} nil "Failed to find memo | Failed to delete memo ID: %v" // @Failure 500 {object} nil "Failed to find memo | Failed to delete memo ID: %v"
// @Security ApiKeyAuth
// @Router /api/v1/memo/{memoId} [DELETE] // @Router /api/v1/memo/{memoId} [DELETE]
func (s *APIV1Service) DeleteMemo(c echo.Context) error { func (s *APIV1Service) DeleteMemo(c echo.Context) error {
ctx := c.Request().Context() ctx := c.Request().Context()
@ -624,7 +620,6 @@ func (s *APIV1Service) DeleteMemo(c echo.Context) error {
// @Failure 401 {object} nil "Missing user in session | Unauthorized" // @Failure 401 {object} nil "Missing user in session | Unauthorized"
// @Failure 404 {object} nil "Memo not found: %d" // @Failure 404 {object} nil "Memo not found: %d"
// @Failure 500 {object} nil "Failed to find memo | Failed to patch memo | Failed to upsert memo resource | Failed to delete memo resource | Failed to compose memo response" // @Failure 500 {object} nil "Failed to find memo | Failed to patch memo | Failed to upsert memo resource | Failed to delete memo resource | Failed to compose memo response"
// @Security ApiKeyAuth
// @Router /api/v1/memo/{memoId} [PATCH] // @Router /api/v1/memo/{memoId} [PATCH]
// //
// NOTES: // NOTES:

View File

@ -37,7 +37,6 @@ func (s *APIV1Service) registerMemoOrganizerRoutes(g *echo.Group) {
// @Failure 401 {object} nil "Missing user in session | Unauthorized" // @Failure 401 {object} nil "Missing user in session | Unauthorized"
// @Failure 404 {object} nil "Memo not found: %v" // @Failure 404 {object} nil "Memo not found: %v"
// @Failure 500 {object} nil "Failed to find memo | Failed to upsert memo organizer | Failed to find memo by ID: %v | Failed to compose memo response" // @Failure 500 {object} nil "Failed to find memo | Failed to upsert memo organizer | Failed to find memo by ID: %v | Failed to compose memo response"
// @Security ApiKeyAuth
// @Router /api/v1/memo/{memoId}/organizer [POST] // @Router /api/v1/memo/{memoId}/organizer [POST]
func (s *APIV1Service) CreateMemoOrganizer(c echo.Context) error { func (s *APIV1Service) CreateMemoOrganizer(c echo.Context) error {
ctx := c.Request().Context() ctx := c.Request().Context()

View File

@ -82,7 +82,6 @@ func (s *APIV1Service) GetMemoResourceList(c echo.Context) error {
// @Failure 400 {object} nil "ID is not a number: %s | Malformatted post memo resource request | Resource not found" // @Failure 400 {object} nil "ID is not a number: %s | Malformatted post memo resource request | Resource not found"
// @Failure 401 {object} nil "Missing user in session | Unauthorized to bind this resource" // @Failure 401 {object} nil "Missing user in session | Unauthorized to bind this resource"
// @Failure 500 {object} nil "Failed to fetch resource | Failed to upsert memo resource" // @Failure 500 {object} nil "Failed to fetch resource | Failed to upsert memo resource"
// @Security ApiKeyAuth
// @Router /api/v1/memo/{memoId}/resource [POST] // @Router /api/v1/memo/{memoId}/resource [POST]
// //
// NOTES: // NOTES:
@ -140,7 +139,6 @@ func (s *APIV1Service) BindMemoResource(c echo.Context) error {
// @Failure 400 {object} nil "Memo ID is not a number: %s | Resource ID is not a number: %s | Memo not found" // @Failure 400 {object} nil "Memo ID is not a number: %s | Resource ID is not a number: %s | Memo not found"
// @Failure 401 {object} nil "Missing user in session | Unauthorized" // @Failure 401 {object} nil "Missing user in session | Unauthorized"
// @Failure 500 {object} nil "Failed to find memo | Failed to fetch resource list" // @Failure 500 {object} nil "Failed to find memo | Failed to fetch resource list"
// @Security ApiKeyAuth
// @Router /api/v1/memo/{memoId}/resource/{resourceId} [DELETE] // @Router /api/v1/memo/{memoId}/resource/{resourceId} [DELETE]
func (s *APIV1Service) UnbindMemoResource(c echo.Context) error { func (s *APIV1Service) UnbindMemoResource(c echo.Context) error {
ctx := c.Request().Context() ctx := c.Request().Context()

View File

@ -100,7 +100,6 @@ func (s *APIV1Service) registerResourcePublicRoutes(g *echo.Group) {
// @Success 200 {object} []store.Resource "Resource list" // @Success 200 {object} []store.Resource "Resource list"
// @Failure 401 {object} nil "Missing user in session" // @Failure 401 {object} nil "Missing user in session"
// @Failure 500 {object} nil "Failed to fetch resource list" // @Failure 500 {object} nil "Failed to fetch resource list"
// @Security ApiKeyAuth
// @Router /api/v1/resource [GET] // @Router /api/v1/resource [GET]
func (s *APIV1Service) GetResourceList(c echo.Context) error { func (s *APIV1Service) GetResourceList(c echo.Context) error {
ctx := c.Request().Context() ctx := c.Request().Context()
@ -140,7 +139,6 @@ func (s *APIV1Service) GetResourceList(c echo.Context) error {
// @Failure 400 {object} nil "Malformatted post resource request | Invalid external link | Invalid external link scheme | Failed to request %s | Failed to read %s | Failed to read mime from %s" // @Failure 400 {object} nil "Malformatted post resource request | Invalid external link | Invalid external link scheme | Failed to request %s | Failed to read %s | Failed to read mime from %s"
// @Failure 401 {object} nil "Missing user in session" // @Failure 401 {object} nil "Missing user in session"
// @Failure 500 {object} nil "Failed to save resource | Failed to create resource | Failed to create activity" // @Failure 500 {object} nil "Failed to save resource | Failed to create resource | Failed to create activity"
// @Security ApiKeyAuth
// @Router /api/v1/resource [POST] // @Router /api/v1/resource [POST]
func (s *APIV1Service) CreateResource(c echo.Context) error { func (s *APIV1Service) CreateResource(c echo.Context) error {
ctx := c.Request().Context() ctx := c.Request().Context()
@ -192,7 +190,6 @@ func (s *APIV1Service) CreateResource(c echo.Context) error {
// @Failure 400 {object} nil "Upload file not found | File size exceeds allowed limit of %d MiB | Failed to parse upload data" // @Failure 400 {object} nil "Upload file not found | File size exceeds allowed limit of %d MiB | Failed to parse upload data"
// @Failure 401 {object} nil "Missing user in session" // @Failure 401 {object} nil "Missing user in session"
// @Failure 500 {object} nil "Failed to get uploading file | Failed to open file | Failed to save resource | Failed to create resource | Failed to create activity" // @Failure 500 {object} nil "Failed to get uploading file | Failed to open file | Failed to save resource | Failed to create resource | Failed to create activity"
// @Security ApiKeyAuth
// @Router /api/v1/resource/blob [POST] // @Router /api/v1/resource/blob [POST]
func (s *APIV1Service) UploadResource(c echo.Context) error { func (s *APIV1Service) UploadResource(c echo.Context) error {
ctx := c.Request().Context() ctx := c.Request().Context()
@ -265,7 +262,6 @@ func (s *APIV1Service) UploadResource(c echo.Context) error {
// @Failure 401 {object} nil "Missing user in session" // @Failure 401 {object} nil "Missing user in session"
// @Failure 404 {object} nil "Resource not found: %d" // @Failure 404 {object} nil "Resource not found: %d"
// @Failure 500 {object} nil "Failed to find resource | Failed to delete resource" // @Failure 500 {object} nil "Failed to find resource | Failed to delete resource"
// @Security ApiKeyAuth
// @Router /api/v1/resource/{resourceId} [DELETE] // @Router /api/v1/resource/{resourceId} [DELETE]
func (s *APIV1Service) DeleteResource(c echo.Context) error { func (s *APIV1Service) DeleteResource(c echo.Context) error {
ctx := c.Request().Context() ctx := c.Request().Context()
@ -322,7 +318,6 @@ func (s *APIV1Service) DeleteResource(c echo.Context) error {
// @Failure 401 {object} nil "Missing user in session | Unauthorized" // @Failure 401 {object} nil "Missing user in session | Unauthorized"
// @Failure 404 {object} nil "Resource not found: %d" // @Failure 404 {object} nil "Resource not found: %d"
// @Failure 500 {object} nil "Failed to find resource | Failed to patch resource" // @Failure 500 {object} nil "Failed to find resource | Failed to patch resource"
// @Security ApiKeyAuth
// @Router /api/v1/resource/{resourceId} [PATCH] // @Router /api/v1/resource/{resourceId} [PATCH]
func (s *APIV1Service) UpdateResource(c echo.Context) error { func (s *APIV1Service) UpdateResource(c echo.Context) error {
ctx := c.Request().Context() ctx := c.Request().Context()

View File

@ -77,7 +77,6 @@ func (s *APIV1Service) registerStorageRoutes(g *echo.Group) {
// @Success 200 {object} []store.Storage "List of storages" // @Success 200 {object} []store.Storage "List of storages"
// @Failure 401 {object} nil "Missing user in session | Unauthorized" // @Failure 401 {object} nil "Missing user in session | Unauthorized"
// @Failure 500 {object} nil "Failed to find user | Failed to convert storage" // @Failure 500 {object} nil "Failed to find user | Failed to convert storage"
// @Security ApiKeyAuth
// @Router /api/v1/storage [GET] // @Router /api/v1/storage [GET]
func (s *APIV1Service) GetStorageList(c echo.Context) error { func (s *APIV1Service) GetStorageList(c echo.Context) error {
ctx := c.Request().Context() ctx := c.Request().Context()
@ -124,7 +123,6 @@ func (s *APIV1Service) GetStorageList(c echo.Context) error {
// @Failure 400 {object} nil "Malformatted post storage request" // @Failure 400 {object} nil "Malformatted post storage request"
// @Failure 401 {object} nil "Missing user in session" // @Failure 401 {object} nil "Missing user in session"
// @Failure 500 {object} nil "Failed to find user | Failed to create storage | Failed to convert storage" // @Failure 500 {object} nil "Failed to find user | Failed to create storage | Failed to convert storage"
// @Security ApiKeyAuth
// @Router /api/v1/storage [POST] // @Router /api/v1/storage [POST]
func (s *APIV1Service) CreateStorage(c echo.Context) error { func (s *APIV1Service) CreateStorage(c echo.Context) error {
ctx := c.Request().Context() ctx := c.Request().Context()
@ -182,7 +180,6 @@ func (s *APIV1Service) CreateStorage(c echo.Context) error {
// @Failure 400 {object} nil "ID is not a number: %s | Storage service %d is using" // @Failure 400 {object} nil "ID is not a number: %s | Storage service %d is using"
// @Failure 401 {object} nil "Missing user in session | Unauthorized" // @Failure 401 {object} nil "Missing user in session | Unauthorized"
// @Failure 500 {object} nil "Failed to find user | Failed to find storage | Failed to unmarshal storage service id | Failed to delete storage" // @Failure 500 {object} nil "Failed to find user | Failed to find storage | Failed to unmarshal storage service id | Failed to delete storage"
// @Security ApiKeyAuth
// @Router /api/v1/storage/{storageId} [DELETE] // @Router /api/v1/storage/{storageId} [DELETE]
// //
// NOTES: // NOTES:
@ -241,7 +238,6 @@ func (s *APIV1Service) DeleteStorage(c echo.Context) error {
// @Failure 400 {object} nil "ID is not a number: %s | Malformatted patch storage request | Malformatted post storage request" // @Failure 400 {object} nil "ID is not a number: %s | Malformatted patch storage request | Malformatted post storage request"
// @Failure 401 {object} nil "Missing user in session | Unauthorized" // @Failure 401 {object} nil "Missing user in session | Unauthorized"
// @Failure 500 {object} nil "Failed to find user | Failed to patch storage | Failed to convert storage" // @Failure 500 {object} nil "Failed to find user | Failed to patch storage | Failed to convert storage"
// @Security ApiKeyAuth
// @Router /api/v1/storage/{storageId} [PATCH] // @Router /api/v1/storage/{storageId} [PATCH]
func (s *APIV1Service) UpdateStorage(c echo.Context) error { func (s *APIV1Service) UpdateStorage(c echo.Context) error {
ctx := c.Request().Context() ctx := c.Request().Context()

View File

@ -9,6 +9,15 @@ definitions:
title: title:
type: string type: string
type: object type: object
github_com_usememos_memos_store.UserSetting:
properties:
key:
type: string
userID:
type: integer
value:
type: string
type: object
profile.Profile: profile.Profile:
properties: properties:
mode: mode:
@ -197,8 +206,6 @@ definitions:
type: integer type: integer
nickname: nickname:
type: string type: string
openID:
type: string
passwordHash: passwordHash:
type: string type: string
role: role:
@ -213,15 +220,6 @@ definitions:
description: Domain specific fields description: Domain specific fields
type: string type: string
type: object type: object
store.UserSetting:
properties:
key:
type: string
userID:
type: integer
value:
type: string
type: object
store.Visibility: store.Visibility:
enum: enum:
- PUBLIC - PUBLIC
@ -624,8 +622,6 @@ definitions:
type: string type: string
password: password:
type: string type: string
resetOpenId:
type: boolean
rowStatus: rowStatus:
$ref: '#/definitions/v1.RowStatus' $ref: '#/definitions/v1.RowStatus'
username: username:
@ -683,8 +679,6 @@ definitions:
type: integer type: integer
nickname: nickname:
type: string type: string
openId:
type: string
role: role:
$ref: '#/definitions/v1.Role' $ref: '#/definitions/v1.Role'
rowStatus: rowStatus:
@ -733,7 +727,7 @@ definitions:
- Protected - Protected
- Private - Private
externalDocs: externalDocs:
description: Find out more about Memos description: Find out more about Memos.
url: https://usememos.com/ url: https://usememos.com/
info: info:
contact: contact:
@ -899,8 +893,6 @@ paths:
description: Missing user in session | Unauthorized description: Missing user in session | Unauthorized
"500": "500":
description: Failed to find user | Failed to create identity provider description: Failed to find user | Failed to create identity provider
security:
- ApiKeyAuth: []
summary: Create Identity Provider summary: Create Identity Provider
tags: tags:
- idp - idp
@ -928,8 +920,6 @@ paths:
description: Missing user in session | Unauthorized description: Missing user in session | Unauthorized
"500": "500":
description: Failed to find user | Failed to patch identity provider description: Failed to find user | Failed to patch identity provider
security:
- ApiKeyAuth: []
summary: Delete an identity provider by ID summary: Delete an identity provider by ID
tags: tags:
- idp - idp
@ -957,8 +947,6 @@ paths:
description: Identity provider not found description: Identity provider not found
"500": "500":
description: Failed to find identity provider list | Failed to find user description: Failed to find identity provider list | Failed to find user
security:
- ApiKeyAuth: []
summary: Get an identity provider by ID summary: Get an identity provider by ID
tags: tags:
- idp - idp
@ -991,8 +979,6 @@ paths:
description: Missing user in session | Unauthorized description: Missing user in session | Unauthorized
"500": "500":
description: Failed to find user | Failed to patch identity provider description: Failed to find user | Failed to patch identity provider
security:
- ApiKeyAuth: []
summary: Update an identity provider by ID summary: Update an identity provider by ID
tags: tags:
- idp - idp
@ -1048,8 +1034,6 @@ paths:
"500": "500":
description: Failed to get memo display with updated ts setting value | description: Failed to get memo display with updated ts setting value |
Failed to fetch memo list | Failed to compose memo response Failed to fetch memo list | Failed to compose memo response
security:
- ApiKeyAuth: []
summary: Get a list of memos matching optional filters summary: Get a list of memos matching optional filters
tags: tags:
- memo - memo
@ -1086,8 +1070,6 @@ paths:
| Failed to find user | Failed to create memo | Failed to create activity | Failed to find user | Failed to create memo | Failed to create activity
| Failed to upsert memo resource | Failed to upsert memo relation | Failed | Failed to upsert memo resource | Failed to upsert memo relation | Failed
to compose memo | Failed to compose memo response to compose memo | Failed to compose memo response
security:
- ApiKeyAuth: []
summary: Create a memo summary: Create a memo
tags: tags:
- memo - memo
@ -1114,8 +1096,6 @@ paths:
description: 'Memo not found: %d' description: 'Memo not found: %d'
"500": "500":
description: 'Failed to find memo | Failed to delete memo ID: %v' description: 'Failed to find memo | Failed to delete memo ID: %v'
security:
- ApiKeyAuth: []
summary: Delete memo by ID summary: Delete memo by ID
tags: tags:
- memo - memo
@ -1185,8 +1165,6 @@ paths:
description: Failed to find memo | Failed to patch memo | Failed to upsert description: Failed to find memo | Failed to patch memo | Failed to upsert
memo resource | Failed to delete memo resource | Failed to compose memo memo resource | Failed to delete memo resource | Failed to compose memo
response response
security:
- ApiKeyAuth: []
summary: Update a memo summary: Update a memo
tags: tags:
- memo - memo
@ -1223,8 +1201,6 @@ paths:
"500": "500":
description: 'Failed to find memo | Failed to upsert memo organizer | Failed description: 'Failed to find memo | Failed to upsert memo organizer | Failed
to find memo by ID: %v | Failed to compose memo response' to find memo by ID: %v | Failed to compose memo response'
security:
- ApiKeyAuth: []
summary: Organize memo (pin/unpin) summary: Organize memo (pin/unpin)
tags: tags:
- memo-organizer - memo-organizer
@ -1378,8 +1354,6 @@ paths:
description: Missing user in session | Unauthorized to bind this resource description: Missing user in session | Unauthorized to bind this resource
"500": "500":
description: Failed to fetch resource | Failed to upsert memo resource description: Failed to fetch resource | Failed to upsert memo resource
security:
- ApiKeyAuth: []
summary: Bind resource to memo summary: Bind resource to memo
tags: tags:
- memo-resource - memo-resource
@ -1413,8 +1387,6 @@ paths:
description: Missing user in session | Unauthorized description: Missing user in session | Unauthorized
"500": "500":
description: Failed to find memo | Failed to fetch resource list description: Failed to find memo | Failed to fetch resource list
security:
- ApiKeyAuth: []
summary: Unbind resource from memo summary: Unbind resource from memo
tags: tags:
- memo-resource - memo-resource
@ -1444,8 +1416,6 @@ paths:
"500": "500":
description: Failed to get memo display with updated ts setting value | description: Failed to get memo display with updated ts setting value |
Failed to fetch all memo list | Failed to compose memo response Failed to fetch all memo list | Failed to compose memo response
security:
- ApiKeyAuth: []
summary: Get a list of public memos matching optional filters summary: Get a list of public memos matching optional filters
tags: tags:
- memo - memo
@ -1514,8 +1484,6 @@ paths:
description: Missing user in session description: Missing user in session
"500": "500":
description: Failed to fetch resource list description: Failed to fetch resource list
security:
- ApiKeyAuth: []
summary: Get a list of resources summary: Get a list of resources
tags: tags:
- resource - resource
@ -1545,8 +1513,6 @@ paths:
"500": "500":
description: Failed to save resource | Failed to create resource | Failed description: Failed to save resource | Failed to create resource | Failed
to create activity to create activity
security:
- ApiKeyAuth: []
summary: Create resource summary: Create resource
tags: tags:
- resource - resource
@ -1573,8 +1539,6 @@ paths:
description: 'Resource not found: %d' description: 'Resource not found: %d'
"500": "500":
description: Failed to find resource | Failed to delete resource description: Failed to find resource | Failed to delete resource
security:
- ApiKeyAuth: []
summary: Delete a resource summary: Delete a resource
tags: tags:
- resource - resource
@ -1606,8 +1570,6 @@ paths:
description: 'Resource not found: %d' description: 'Resource not found: %d'
"500": "500":
description: Failed to find resource | Failed to patch resource description: Failed to find resource | Failed to patch resource
security:
- ApiKeyAuth: []
summary: Update a resource summary: Update a resource
tags: tags:
- resource - resource
@ -1636,8 +1598,6 @@ paths:
"500": "500":
description: Failed to get uploading file | Failed to open file | Failed description: Failed to get uploading file | Failed to open file | Failed
to save resource | Failed to create resource | Failed to create activity to save resource | Failed to create resource | Failed to create activity
security:
- ApiKeyAuth: []
summary: Upload resource summary: Upload resource
tags: tags:
- resource - resource
@ -1673,8 +1633,6 @@ paths:
description: Missing user in session | Unauthorized description: Missing user in session | Unauthorized
"500": "500":
description: Failed to find user | Failed to convert storage description: Failed to find user | Failed to convert storage
security:
- ApiKeyAuth: []
summary: Get a list of storages summary: Get a list of storages
tags: tags:
- storage - storage
@ -1702,8 +1660,6 @@ paths:
"500": "500":
description: Failed to find user | Failed to create storage | Failed to description: Failed to find user | Failed to create storage | Failed to
convert storage convert storage
security:
- ApiKeyAuth: []
summary: Create storage summary: Create storage
tags: tags:
- storage - storage
@ -1729,8 +1685,6 @@ paths:
"500": "500":
description: Failed to find user | Failed to find storage | Failed to unmarshal description: Failed to find user | Failed to find storage | Failed to unmarshal
storage service id | Failed to delete storage storage service id | Failed to delete storage
security:
- ApiKeyAuth: []
summary: Delete a storage summary: Delete a storage
tags: tags:
- storage - storage
@ -1762,8 +1716,6 @@ paths:
"500": "500":
description: Failed to find user | Failed to patch storage | Failed to convert description: Failed to find user | Failed to patch storage | Failed to convert
storage storage
security:
- ApiKeyAuth: []
summary: Update a storage summary: Update a storage
tags: tags:
- storage - storage
@ -1782,8 +1734,6 @@ paths:
description: Missing user in session | Unauthorized description: Missing user in session | Unauthorized
"500": "500":
description: Failed to find user | Failed to find system setting list description: Failed to find user | Failed to find system setting list
security:
- ApiKeyAuth: []
summary: Get a list of system settings summary: Get a list of system settings
tags: tags:
- system-setting - system-setting
@ -1812,8 +1762,6 @@ paths:
description: Cannot disable passwords if no SSO identity provider is configured. description: Cannot disable passwords if no SSO identity provider is configured.
"500": "500":
description: Failed to find user | Failed to upsert system setting description: Failed to find user | Failed to upsert system setting
security:
- ApiKeyAuth: []
summary: Create system setting summary: Create system setting
tags: tags:
- system-setting - system-setting
@ -1830,8 +1778,6 @@ paths:
description: Missing user in session | Unauthorized description: Missing user in session | Unauthorized
"500": "500":
description: Failed to find user | Failed to ExecVacuum database description: Failed to find user | Failed to ExecVacuum database
security:
- ApiKeyAuth: []
summary: Vacuum the database summary: Vacuum the database
tags: tags:
- system - system
@ -1850,8 +1796,6 @@ paths:
description: Missing user id to find tag description: Missing user id to find tag
"500": "500":
description: Failed to find tag list description: Failed to find tag list
security:
- ApiKeyAuth: []
summary: Get a list of tags summary: Get a list of tags
tags: tags:
- tag - tag
@ -1878,8 +1822,6 @@ paths:
description: Missing user in session description: Missing user in session
"500": "500":
description: Failed to upsert tag | Failed to create activity description: Failed to upsert tag | Failed to create activity
security:
- ApiKeyAuth: []
summary: Create a tag summary: Create a tag
tags: tags:
- tag - tag
@ -1907,8 +1849,6 @@ paths:
description: Missing user in session description: Missing user in session
"500": "500":
description: 'Failed to delete tag name: %v' description: 'Failed to delete tag name: %v'
security:
- ApiKeyAuth: []
summary: Delete a tag summary: Delete a tag
tags: tags:
- tag - tag
@ -1927,8 +1867,6 @@ paths:
description: Missing user session description: Missing user session
"500": "500":
description: Failed to find memo list | Failed to find tag list description: Failed to find memo list | Failed to find tag list
security:
- ApiKeyAuth: []
summary: Get a list of tags suggested from other memos contents summary: Get a list of tags suggested from other memos contents
tags: tags:
- tag - tag
@ -2073,8 +2011,6 @@ paths:
description: Missing auth session description: Missing auth session
"500": "500":
description: Failed to find user | Failed to find userSettingList description: Failed to find user | Failed to find userSettingList
security:
- ApiKeyAuth: []
summary: Get current user summary: Get current user
tags: tags:
- user - user
@ -2117,7 +2053,7 @@ paths:
"200": "200":
description: Created user setting description: Created user setting
schema: schema:
$ref: '#/definitions/store.UserSetting' $ref: '#/definitions/github_com_usememos_memos_store.UserSetting'
"400": "400":
description: Malformatted post user setting upsert request | Invalid user description: Malformatted post user setting upsert request | Invalid user
setting format setting format
@ -2125,8 +2061,6 @@ paths:
description: Missing auth session description: Missing auth session
"500": "500":
description: Failed to upsert user setting description: Failed to upsert user setting
security:
- ApiKeyAuth: []
summary: Upsert user setting summary: Upsert user setting
tags: tags:
- user-setting - user-setting
@ -2238,10 +2172,4 @@ paths:
summary: Get RSS for a user summary: Get RSS for a user
tags: tags:
- rss - rss
securityDefinitions:
ApiKeyAuth:
description: Insert your Open ID API Key here.
in: query
name: openId
type: apiKey
swagger: "2.0" swagger: "2.0"

View File

@ -163,7 +163,6 @@ func (s *APIV1Service) GetSystemStatus(c echo.Context) error {
// @Success 200 {boolean} true "Database vacuumed" // @Success 200 {boolean} true "Database vacuumed"
// @Failure 401 {object} nil "Missing user in session | Unauthorized" // @Failure 401 {object} nil "Missing user in session | Unauthorized"
// @Failure 500 {object} nil "Failed to find user | Failed to ExecVacuum database" // @Failure 500 {object} nil "Failed to find user | Failed to ExecVacuum database"
// @Security ApiKeyAuth
// @Router /api/v1/system/vacuum [POST] // @Router /api/v1/system/vacuum [POST]
func (s *APIV1Service) ExecVacuum(c echo.Context) error { func (s *APIV1Service) ExecVacuum(c echo.Context) error {
ctx := c.Request().Context() ctx := c.Request().Context()

View File

@ -90,7 +90,6 @@ func (s *APIV1Service) registerSystemSettingRoutes(g *echo.Group) {
// @Success 200 {object} []SystemSetting "System setting list" // @Success 200 {object} []SystemSetting "System setting list"
// @Failure 401 {object} nil "Missing user in session | Unauthorized" // @Failure 401 {object} nil "Missing user in session | Unauthorized"
// @Failure 500 {object} nil "Failed to find user | Failed to find system setting list" // @Failure 500 {object} nil "Failed to find user | Failed to find system setting list"
// @Security ApiKeyAuth
// @Router /api/v1/system/setting [GET] // @Router /api/v1/system/setting [GET]
func (s *APIV1Service) GetSystemSettingList(c echo.Context) error { func (s *APIV1Service) GetSystemSettingList(c echo.Context) error {
ctx := c.Request().Context() ctx := c.Request().Context()
@ -133,7 +132,6 @@ func (s *APIV1Service) GetSystemSettingList(c echo.Context) error {
// @Failure 401 {object} nil "Missing user in session | Unauthorized" // @Failure 401 {object} nil "Missing user in session | Unauthorized"
// @Failure 403 {object} nil "Cannot disable passwords if no SSO identity provider is configured." // @Failure 403 {object} nil "Cannot disable passwords if no SSO identity provider is configured."
// @Failure 500 {object} nil "Failed to find user | Failed to upsert system setting" // @Failure 500 {object} nil "Failed to find user | Failed to upsert system setting"
// @Security ApiKeyAuth
// @Router /api/v1/system/setting [POST] // @Router /api/v1/system/setting [POST]
func (s *APIV1Service) CreateSystemSetting(c echo.Context) error { func (s *APIV1Service) CreateSystemSetting(c echo.Context) error {
ctx := c.Request().Context() ctx := c.Request().Context()

View File

@ -41,7 +41,6 @@ func (s *APIV1Service) registerTagRoutes(g *echo.Group) {
// @Success 200 {object} []string "Tag list" // @Success 200 {object} []string "Tag list"
// @Failure 400 {object} nil "Missing user id to find tag" // @Failure 400 {object} nil "Missing user id to find tag"
// @Failure 500 {object} nil "Failed to find tag list" // @Failure 500 {object} nil "Failed to find tag list"
// @Security ApiKeyAuth
// @Router /api/v1/tag [GET] // @Router /api/v1/tag [GET]
func (s *APIV1Service) GetTagList(c echo.Context) error { func (s *APIV1Service) GetTagList(c echo.Context) error {
ctx := c.Request().Context() ctx := c.Request().Context()
@ -75,7 +74,6 @@ func (s *APIV1Service) GetTagList(c echo.Context) error {
// @Failure 400 {object} nil "Malformatted post tag request | Tag name shouldn't be empty" // @Failure 400 {object} nil "Malformatted post tag request | Tag name shouldn't be empty"
// @Failure 401 {object} nil "Missing user in session" // @Failure 401 {object} nil "Missing user in session"
// @Failure 500 {object} nil "Failed to upsert tag | Failed to create activity" // @Failure 500 {object} nil "Failed to upsert tag | Failed to create activity"
// @Security ApiKeyAuth
// @Router /api/v1/tag [POST] // @Router /api/v1/tag [POST]
func (s *APIV1Service) CreateTag(c echo.Context) error { func (s *APIV1Service) CreateTag(c echo.Context) error {
ctx := c.Request().Context() ctx := c.Request().Context()
@ -117,7 +115,6 @@ func (s *APIV1Service) CreateTag(c echo.Context) error {
// @Failure 400 {object} nil "Malformatted post tag request | Tag name shouldn't be empty" // @Failure 400 {object} nil "Malformatted post tag request | Tag name shouldn't be empty"
// @Failure 401 {object} nil "Missing user in session" // @Failure 401 {object} nil "Missing user in session"
// @Failure 500 {object} nil "Failed to delete tag name: %v" // @Failure 500 {object} nil "Failed to delete tag name: %v"
// @Security ApiKeyAuth
// @Router /api/v1/tag/delete [POST] // @Router /api/v1/tag/delete [POST]
func (s *APIV1Service) DeleteTag(c echo.Context) error { func (s *APIV1Service) DeleteTag(c echo.Context) error {
ctx := c.Request().Context() ctx := c.Request().Context()
@ -152,7 +149,6 @@ func (s *APIV1Service) DeleteTag(c echo.Context) error {
// @Success 200 {object} []string "Tag list" // @Success 200 {object} []string "Tag list"
// @Failure 400 {object} nil "Missing user session" // @Failure 400 {object} nil "Missing user session"
// @Failure 500 {object} nil "Failed to find memo list | Failed to find tag list" // @Failure 500 {object} nil "Failed to find memo list | Failed to find tag list"
// @Security ApiKeyAuth
// @Router /api/v1/tag/suggestion [GET] // @Router /api/v1/tag/suggestion [GET]
func (s *APIV1Service) GetTagSuggestion(c echo.Context) error { func (s *APIV1Service) GetTagSuggestion(c echo.Context) error {
ctx := c.Request().Context() ctx := c.Request().Context()

View File

@ -43,7 +43,6 @@ type User struct {
Email string `json:"email"` Email string `json:"email"`
Nickname string `json:"nickname"` Nickname string `json:"nickname"`
PasswordHash string `json:"-"` PasswordHash string `json:"-"`
OpenID string `json:"openId"`
AvatarURL string `json:"avatarUrl"` AvatarURL string `json:"avatarUrl"`
UserSettingList []*UserSetting `json:"userSettingList"` UserSettingList []*UserSetting `json:"userSettingList"`
} }
@ -57,13 +56,12 @@ type CreateUserRequest struct {
} }
type UpdateUserRequest struct { type UpdateUserRequest struct {
RowStatus *RowStatus `json:"rowStatus"` RowStatus *RowStatus `json:"rowStatus"`
Username *string `json:"username"` Username *string `json:"username"`
Email *string `json:"email"` Email *string `json:"email"`
Nickname *string `json:"nickname"` Nickname *string `json:"nickname"`
Password *string `json:"password"` Password *string `json:"password"`
ResetOpenID *bool `json:"resetOpenId"` AvatarURL *string `json:"avatarUrl"`
AvatarURL *string `json:"avatarUrl"`
} }
func (s *APIV1Service) registerUserRoutes(g *echo.Group) { func (s *APIV1Service) registerUserRoutes(g *echo.Group) {
@ -96,7 +94,6 @@ func (s *APIV1Service) GetUserList(c echo.Context) error {
for _, user := range list { for _, user := range list {
userMessage := convertUserFromStore(user) userMessage := convertUserFromStore(user)
// data desensitize // data desensitize
userMessage.OpenID = ""
userMessage.Email = "" userMessage.Email = ""
userMessageList = append(userMessageList, userMessage) userMessageList = append(userMessageList, userMessage)
} }
@ -158,7 +155,6 @@ func (s *APIV1Service) CreateUser(c echo.Context) error {
Email: userCreate.Email, Email: userCreate.Email,
Nickname: userCreate.Nickname, Nickname: userCreate.Nickname,
PasswordHash: string(passwordHash), PasswordHash: string(passwordHash),
OpenID: util.GenUUID(),
}) })
if err != nil { if err != nil {
return echo.NewHTTPError(http.StatusInternalServerError, "Failed to create user").SetInternal(err) return echo.NewHTTPError(http.StatusInternalServerError, "Failed to create user").SetInternal(err)
@ -179,7 +175,6 @@ func (s *APIV1Service) CreateUser(c echo.Context) error {
// @Success 200 {object} store.User "Current user" // @Success 200 {object} store.User "Current user"
// @Failure 401 {object} nil "Missing auth session" // @Failure 401 {object} nil "Missing auth session"
// @Failure 500 {object} nil "Failed to find user | Failed to find userSettingList" // @Failure 500 {object} nil "Failed to find user | Failed to find userSettingList"
// @Security ApiKeyAuth
// @Router /api/v1/user/me [GET] // @Router /api/v1/user/me [GET]
func (s *APIV1Service) GetCurrentUser(c echo.Context) error { func (s *APIV1Service) GetCurrentUser(c echo.Context) error {
ctx := c.Request().Context() ctx := c.Request().Context()
@ -234,7 +229,6 @@ func (s *APIV1Service) GetUserByUsername(c echo.Context) error {
userMessage := convertUserFromStore(user) userMessage := convertUserFromStore(user)
// data desensitize // data desensitize
userMessage.OpenID = ""
userMessage.Email = "" userMessage.Email = ""
return c.JSON(http.StatusOK, userMessage) return c.JSON(http.StatusOK, userMessage)
} }
@ -267,7 +261,6 @@ func (s *APIV1Service) GetUserByID(c echo.Context) error {
userMessage := convertUserFromStore(user) userMessage := convertUserFromStore(user)
// data desensitize // data desensitize
userMessage.OpenID = ""
userMessage.Email = "" userMessage.Email = ""
return c.JSON(http.StatusOK, userMessage) return c.JSON(http.StatusOK, userMessage)
} }
@ -385,10 +378,6 @@ func (s *APIV1Service) UpdateUser(c echo.Context) error {
passwordHashStr := string(passwordHash) passwordHashStr := string(passwordHash)
userUpdate.PasswordHash = &passwordHashStr userUpdate.PasswordHash = &passwordHashStr
} }
if request.ResetOpenID != nil && *request.ResetOpenID {
openID := util.GenUUID()
userUpdate.OpenID = &openID
}
if request.AvatarURL != nil { if request.AvatarURL != nil {
userUpdate.AvatarURL = request.AvatarURL userUpdate.AvatarURL = request.AvatarURL
} }
@ -508,7 +497,6 @@ func convertUserFromStore(user *store.User) *User {
Email: user.Email, Email: user.Email,
Nickname: user.Nickname, Nickname: user.Nickname,
PasswordHash: user.PasswordHash, PasswordHash: user.PasswordHash,
OpenID: user.OpenID,
AvatarURL: user.AvatarURL, AvatarURL: user.AvatarURL,
} }
} }

View File

@ -92,7 +92,6 @@ func (s *APIV1Service) registerUserSettingRoutes(g *echo.Group) {
// @Failure 400 {object} nil "Malformatted post user setting upsert request | Invalid user setting format" // @Failure 400 {object} nil "Malformatted post user setting upsert request | Invalid user setting format"
// @Failure 401 {object} nil "Missing auth session" // @Failure 401 {object} nil "Missing auth session"
// @Failure 500 {object} nil "Failed to upsert user setting" // @Failure 500 {object} nil "Failed to upsert user setting"
// @Security ApiKeyAuth
// @Router /api/v1/user/setting [POST] // @Router /api/v1/user/setting [POST]
func (s *APIV1Service) UpsertUserSetting(c echo.Context) error { func (s *APIV1Service) UpsertUserSetting(c echo.Context) error {
ctx := c.Request().Context() ctx := c.Request().Context()

View File

@ -27,12 +27,7 @@ type APIV1Service struct {
// @BasePath / // @BasePath /
// //
// @externalDocs.url https://usememos.com/ // @externalDocs.url https://usememos.com/
// @externalDocs.description Find out more about Memos // @externalDocs.description Find out more about Memos.
//
// @securitydefinitions.apikey ApiKeyAuth
// @in query
// @name openId
// @description Insert your Open ID API Key here.
func NewAPIV1Service(secret string, profile *profile.Profile, store *store.Store, telegramBot *telegram.Bot) *APIV1Service { func NewAPIV1Service(secret string, profile *profile.Profile, store *store.Store, telegramBot *telegram.Bot) *APIV1Service {
return &APIV1Service{ return &APIV1Service{
Secret: secret, Secret: secret,

View File

@ -9,7 +9,6 @@ import (
"github.com/labstack/echo/v4" "github.com/labstack/echo/v4"
"github.com/pkg/errors" "github.com/pkg/errors"
"github.com/usememos/memos/api/auth" "github.com/usememos/memos/api/auth"
"github.com/usememos/memos/common/util"
apiv2pb "github.com/usememos/memos/proto/gen/api/v2" apiv2pb "github.com/usememos/memos/proto/gen/api/v2"
storepb "github.com/usememos/memos/proto/gen/store" storepb "github.com/usememos/memos/proto/gen/store"
"github.com/usememos/memos/store" "github.com/usememos/memos/store"
@ -47,12 +46,6 @@ func (s *UserService) GetUser(ctx context.Context, request *apiv2pb.GetUserReque
} }
userMessage := convertUserFromStore(user) userMessage := convertUserFromStore(user)
currentUser, _ := getCurrentUser(ctx, s.Store)
if currentUser == nil || currentUser.ID != user.ID {
// Data desensitization.
userMessage.OpenId = ""
}
response := &apiv2pb.GetUserResponse{ response := &apiv2pb.GetUserResponse{
User: userMessage, User: userMessage,
} }
@ -88,9 +81,6 @@ func (s *UserService) UpdateUser(ctx context.Context, request *apiv2pb.UpdateUse
} else if path == "role" { } else if path == "role" {
role := convertUserRoleToStore(request.User.Role) role := convertUserRoleToStore(request.User.Role)
update.Role = &role update.Role = &role
} else if path == "reset_open_id" {
openID := util.GenUUID()
update.OpenID = &openID
} else if path == "password" { } else if path == "password" {
passwordHash, err := bcrypt.GenerateFromPassword([]byte(request.User.Password), bcrypt.DefaultCost) passwordHash, err := bcrypt.GenerateFromPassword([]byte(request.User.Password), bcrypt.DefaultCost)
if err != nil { if err != nil {
@ -283,7 +273,6 @@ func convertUserFromStore(user *store.User) *apiv2pb.User {
Role: convertUserRoleFromStore(user.Role), Role: convertUserRoleFromStore(user.Role),
Email: user.Email, Email: user.Email,
Nickname: user.Nickname, Nickname: user.Nickname,
OpenId: user.OpenID,
AvatarUrl: user.AvatarURL, AvatarUrl: user.AvatarURL,
} }
} }

View File

@ -101,7 +101,6 @@ func (s setupService) createUser(ctx context.Context, hostUsername, hostPassword
// The new signup user should be normal user by default. // The new signup user should be normal user by default.
Role: store.RoleHost, Role: store.RoleHost,
Nickname: hostUsername, Nickname: hostUsername,
OpenID: util.GenUUID(),
} }
if len(userCreate.Username) < 3 { if len(userCreate.Username) < 3 {

View File

@ -9,16 +9,7 @@ API Support
**License:** [MIT License](https://github.com/usememos/memos/blob/main/LICENSE) **License:** [MIT License](https://github.com/usememos/memos/blob/main/LICENSE)
[Find out more about Memos](https://usememos.com/) [Find out more about Memos.](https://usememos.com/)
### Security
**ApiKeyAuth**
| apiKey | *API Key* |
| ------ | --------- |
| Description | Insert your Open ID API Key here. |
| In | query |
| Name | openId |
--- ---
### /api/v1/auth/signin ### /api/v1/auth/signin
@ -144,12 +135,6 @@ Create Identity Provider
| 401 | Missing user in session \| Unauthorized | | | 401 | Missing user in session \| Unauthorized | |
| 500 | Failed to find user \| Failed to create identity provider | | | 500 | Failed to find user \| Failed to create identity provider | |
##### Security
| Security Schema | Scopes |
| --------------- | ------ |
| ApiKeyAuth | |
### /api/v1/idp/{idpId} ### /api/v1/idp/{idpId}
#### DELETE #### DELETE
@ -172,12 +157,6 @@ Delete an identity provider by ID
| 401 | Missing user in session \| Unauthorized | | | 401 | Missing user in session \| Unauthorized | |
| 500 | Failed to find user \| Failed to patch identity provider | | | 500 | Failed to find user \| Failed to patch identity provider | |
##### Security
| Security Schema | Scopes |
| --------------- | ------ |
| ApiKeyAuth | |
#### GET #### GET
##### Summary ##### Summary
@ -199,12 +178,6 @@ Get an identity provider by ID
| 404 | Identity provider not found | | | 404 | Identity provider not found | |
| 500 | Failed to find identity provider list \| Failed to find user | | | 500 | Failed to find identity provider list \| Failed to find user | |
##### Security
| Security Schema | Scopes |
| --------------- | ------ |
| ApiKeyAuth | |
#### PATCH #### PATCH
##### Summary ##### Summary
@ -226,12 +199,6 @@ Update an identity provider by ID
| 401 | Missing user in session \| Unauthorized | | | 401 | Missing user in session \| Unauthorized | |
| 500 | Failed to find user \| Failed to patch identity provider | | | 500 | Failed to find user \| Failed to patch identity provider | |
##### Security
| Security Schema | Scopes |
| --------------- | ------ |
| ApiKeyAuth | |
--- ---
### /api/v1/memo ### /api/v1/memo
@ -261,12 +228,6 @@ Get a list of memos matching optional filters
| 400 | Missing user to find memo | | | 400 | Missing user to find memo | |
| 500 | Failed to get memo display with updated ts setting value \| Failed to fetch memo list \| Failed to compose memo response | | | 500 | Failed to get memo display with updated ts setting value \| Failed to fetch memo list \| Failed to compose memo response | |
##### Security
| Security Schema | Scopes |
| --------------- | ------ |
| ApiKeyAuth | |
#### POST #### POST
##### Summary ##### Summary
@ -293,12 +254,6 @@ Visibility can be PUBLIC, PROTECTED or PRIVATE
| 404 | User not found \| Memo not found: %d | | | 404 | User not found \| Memo not found: %d | |
| 500 | Failed to find user setting \| Failed to unmarshal user setting value \| Failed to find system setting \| Failed to unmarshal system setting \| Failed to find user \| Failed to create memo \| Failed to create activity \| Failed to upsert memo resource \| Failed to upsert memo relation \| Failed to compose memo \| Failed to compose memo response | | | 500 | Failed to find user setting \| Failed to unmarshal user setting value \| Failed to find system setting \| Failed to unmarshal system setting \| Failed to find user \| Failed to create memo \| Failed to create activity \| Failed to upsert memo resource \| Failed to upsert memo relation \| Failed to compose memo \| Failed to compose memo response | |
##### Security
| Security Schema | Scopes |
| --------------- | ------ |
| ApiKeyAuth | |
### /api/v1/memo/{memoId} ### /api/v1/memo/{memoId}
#### DELETE #### DELETE
@ -322,12 +277,6 @@ Delete memo by ID
| 404 | Memo not found: %d | | | 404 | Memo not found: %d | |
| 500 | Failed to find memo \| Failed to delete memo ID: %v | | | 500 | Failed to find memo \| Failed to delete memo ID: %v | |
##### Security
| Security Schema | Scopes |
| --------------- | ------ |
| ApiKeyAuth | |
#### GET #### GET
##### Summary ##### Summary
@ -377,12 +326,6 @@ Visibility can be PUBLIC, PROTECTED or PRIVATE
| 404 | Memo not found: %d | | | 404 | Memo not found: %d | |
| 500 | Failed to find memo \| Failed to patch memo \| Failed to upsert memo resource \| Failed to delete memo resource \| Failed to compose memo response | | | 500 | Failed to find memo \| Failed to patch memo \| Failed to upsert memo resource \| Failed to delete memo resource \| Failed to compose memo response | |
##### Security
| Security Schema | Scopes |
| --------------- | ------ |
| ApiKeyAuth | |
### /api/v1/memo/all ### /api/v1/memo/all
#### GET #### GET
@ -409,12 +352,6 @@ Authentication is optional
| 200 | Memo list | [ [store.Memo](#storememo) ] | | 200 | Memo list | [ [store.Memo](#storememo) ] |
| 500 | Failed to get memo display with updated ts setting value \| Failed to fetch all memo list \| Failed to compose memo response | | | 500 | Failed to get memo display with updated ts setting value \| Failed to fetch all memo list \| Failed to compose memo response | |
##### Security
| Security Schema | Scopes |
| --------------- | ------ |
| ApiKeyAuth | |
### /api/v1/memo/stats ### /api/v1/memo/stats
#### GET #### GET
@ -466,12 +403,6 @@ Organize memo (pin/unpin)
| 404 | Memo not found: %v | | | 404 | Memo not found: %v | |
| 500 | Failed to find memo \| Failed to upsert memo organizer \| Failed to find memo by ID: %v \| Failed to compose memo response | | | 500 | Failed to find memo \| Failed to upsert memo organizer \| Failed to find memo by ID: %v \| Failed to compose memo response | |
##### Security
| Security Schema | Scopes |
| --------------- | ------ |
| ApiKeyAuth | |
--- ---
### /api/v1/memo/{memoId}/relation ### /api/v1/memo/{memoId}/relation
@ -588,12 +519,6 @@ Bind resource to memo
| 401 | Missing user in session \| Unauthorized to bind this resource | | | 401 | Missing user in session \| Unauthorized to bind this resource | |
| 500 | Failed to fetch resource \| Failed to upsert memo resource | | | 500 | Failed to fetch resource \| Failed to upsert memo resource | |
##### Security
| Security Schema | Scopes |
| --------------- | ------ |
| ApiKeyAuth | |
### /api/v1/memo/{memoId}/resource/{resourceId} ### /api/v1/memo/{memoId}/resource/{resourceId}
#### DELETE #### DELETE
@ -617,12 +542,6 @@ Unbind resource from memo
| 401 | Missing user in session \| Unauthorized | | | 401 | Missing user in session \| Unauthorized | |
| 500 | Failed to find memo \| Failed to fetch resource list | | | 500 | Failed to find memo \| Failed to fetch resource list | |
##### Security
| Security Schema | Scopes |
| --------------- | ------ |
| ApiKeyAuth | |
--- ---
### /api/v1/ping ### /api/v1/ping
@ -635,20 +554,20 @@ Ping the system
| Code | Description | Schema | | Code | Description | Schema |
| ---- | ----------- | ------ | | ---- | ----------- | ------ |
| 200 | System profile | [profile.Profile](#profileprofile) | | 200 | If succeed to ping the system | boolean |
### /api/v1/status ### /api/v1/status
#### GET #### GET
##### Summary ##### Summary
Get system status Get system GetSystemStatus
##### Responses ##### Responses
| Code | Description | Schema | | Code | Description | Schema |
| ---- | ----------- | ------ | | ---- | ----------- | ------ |
| 200 | System status | [v1.SystemStatus](#v1systemstatus) | | 200 | System GetSystemStatus | [v1.SystemStatus](#v1systemstatus) |
| 401 | Missing user in session \| Unauthorized | | | 401 | Missing user in session \| Unauthorized | |
| 500 | Failed to find host user \| Failed to find system setting list \| Failed to unmarshal system setting customized profile value | | | 500 | Failed to find host user \| Failed to find system setting list \| Failed to unmarshal system setting customized profile value | |
@ -665,13 +584,7 @@ Vacuum the database
| ---- | ----------- | ------ | | ---- | ----------- | ------ |
| 200 | Database vacuumed | boolean | | 200 | Database vacuumed | boolean |
| 401 | Missing user in session \| Unauthorized | | | 401 | Missing user in session \| Unauthorized | |
| 500 | Failed to find user \| Failed to vacuum database | | | 500 | Failed to find user \| Failed to ExecVacuum database | |
##### Security
| Security Schema | Scopes |
| --------------- | ------ |
| ApiKeyAuth | |
--- ---
### /api/v1/resource ### /api/v1/resource
@ -696,12 +609,6 @@ Get a list of resources
| 401 | Missing user in session | | | 401 | Missing user in session | |
| 500 | Failed to fetch resource list | | | 500 | Failed to fetch resource list | |
##### Security
| Security Schema | Scopes |
| --------------- | ------ |
| ApiKeyAuth | |
#### POST #### POST
##### Summary ##### Summary
@ -722,12 +629,6 @@ Create resource
| 401 | Missing user in session | | | 401 | Missing user in session | |
| 500 | Failed to save resource \| Failed to create resource \| Failed to create activity | | | 500 | Failed to save resource \| Failed to create resource \| Failed to create activity | |
##### Security
| Security Schema | Scopes |
| --------------- | ------ |
| ApiKeyAuth | |
### /api/v1/resource/{resourceId} ### /api/v1/resource/{resourceId}
#### DELETE #### DELETE
@ -751,12 +652,6 @@ Delete a resource
| 404 | Resource not found: %d | | | 404 | Resource not found: %d | |
| 500 | Failed to find resource \| Failed to delete resource | | | 500 | Failed to find resource \| Failed to delete resource | |
##### Security
| Security Schema | Scopes |
| --------------- | ------ |
| ApiKeyAuth | |
#### PATCH #### PATCH
##### Summary ##### Summary
@ -779,12 +674,6 @@ Update a resource
| 404 | Resource not found: %d | | | 404 | Resource not found: %d | |
| 500 | Failed to find resource \| Failed to patch resource | | | 500 | Failed to find resource \| Failed to patch resource | |
##### Security
| Security Schema | Scopes |
| --------------- | ------ |
| ApiKeyAuth | |
### /api/v1/resource/blob ### /api/v1/resource/blob
#### POST #### POST
@ -807,12 +696,6 @@ Upload resource
| 401 | Missing user in session | | | 401 | Missing user in session | |
| 500 | Failed to get uploading file \| Failed to open file \| Failed to save resource \| Failed to create resource \| Failed to create activity | | | 500 | Failed to get uploading file \| Failed to open file \| Failed to save resource \| Failed to create resource \| Failed to create activity | |
##### Security
| Security Schema | Scopes |
| --------------- | ------ |
| ApiKeyAuth | |
### /o/r/{resourceId} ### /o/r/{resourceId}
#### GET #### GET
@ -857,12 +740,6 @@ Get a list of storages
| 401 | Missing user in session \| Unauthorized | | | 401 | Missing user in session \| Unauthorized | |
| 500 | Failed to find user \| Failed to convert storage | | | 500 | Failed to find user \| Failed to convert storage | |
##### Security
| Security Schema | Scopes |
| --------------- | ------ |
| ApiKeyAuth | |
#### POST #### POST
##### Summary ##### Summary
@ -883,12 +760,6 @@ Create storage
| 401 | Missing user in session | | | 401 | Missing user in session | |
| 500 | Failed to find user \| Failed to create storage \| Failed to convert storage | | | 500 | Failed to find user \| Failed to create storage \| Failed to convert storage | |
##### Security
| Security Schema | Scopes |
| --------------- | ------ |
| ApiKeyAuth | |
### /api/v1/storage/{storageId} ### /api/v1/storage/{storageId}
#### DELETE #### DELETE
@ -911,12 +782,6 @@ Delete a storage
| 401 | Missing user in session \| Unauthorized | | | 401 | Missing user in session \| Unauthorized | |
| 500 | Failed to find user \| Failed to find storage \| Failed to unmarshal storage service id \| Failed to delete storage | | | 500 | Failed to find user \| Failed to find storage \| Failed to unmarshal storage service id \| Failed to delete storage | |
##### Security
| Security Schema | Scopes |
| --------------- | ------ |
| ApiKeyAuth | |
#### PATCH #### PATCH
##### Summary ##### Summary
@ -938,12 +803,6 @@ Update a storage
| 401 | Missing user in session \| Unauthorized | | | 401 | Missing user in session \| Unauthorized | |
| 500 | Failed to find user \| Failed to patch storage \| Failed to convert storage | | | 500 | Failed to find user \| Failed to patch storage \| Failed to convert storage | |
##### Security
| Security Schema | Scopes |
| --------------- | ------ |
| ApiKeyAuth | |
--- ---
### /api/v1/system/setting ### /api/v1/system/setting
@ -960,12 +819,6 @@ Get a list of system settings
| 401 | Missing user in session \| Unauthorized | | | 401 | Missing user in session \| Unauthorized | |
| 500 | Failed to find user \| Failed to find system setting list | | | 500 | Failed to find user \| Failed to find system setting list | |
##### Security
| Security Schema | Scopes |
| --------------- | ------ |
| ApiKeyAuth | |
#### POST #### POST
##### Summary ##### Summary
@ -987,12 +840,6 @@ Create system setting
| 403 | Cannot disable passwords if no SSO identity provider is configured. | | | 403 | Cannot disable passwords if no SSO identity provider is configured. | |
| 500 | Failed to find user \| Failed to upsert system setting | | | 500 | Failed to find user \| Failed to upsert system setting | |
##### Security
| Security Schema | Scopes |
| --------------- | ------ |
| ApiKeyAuth | |
--- ---
### /api/v1/tag ### /api/v1/tag
@ -1009,12 +856,6 @@ Get a list of tags
| 400 | Missing user id to find tag | | | 400 | Missing user id to find tag | |
| 500 | Failed to find tag list | | | 500 | Failed to find tag list | |
##### Security
| Security Schema | Scopes |
| --------------- | ------ |
| ApiKeyAuth | |
#### POST #### POST
##### Summary ##### Summary
@ -1035,12 +876,6 @@ Create a tag
| 401 | Missing user in session | | | 401 | Missing user in session | |
| 500 | Failed to upsert tag \| Failed to create activity | | | 500 | Failed to upsert tag \| Failed to create activity | |
##### Security
| Security Schema | Scopes |
| --------------- | ------ |
| ApiKeyAuth | |
### /api/v1/tag/delete ### /api/v1/tag/delete
#### POST #### POST
@ -1063,12 +898,6 @@ Delete a tag
| 401 | Missing user in session | | | 401 | Missing user in session | |
| 500 | Failed to delete tag name: %v | | | 500 | Failed to delete tag name: %v | |
##### Security
| Security Schema | Scopes |
| --------------- | ------ |
| ApiKeyAuth | |
### /api/v1/tag/suggestion ### /api/v1/tag/suggestion
#### GET #### GET
@ -1084,12 +913,6 @@ Get a list of tags suggested from other memos contents
| 400 | Missing user session | | | 400 | Missing user session | |
| 500 | Failed to find memo list \| Failed to find tag list | | | 500 | Failed to find memo list \| Failed to find tag list | |
##### Security
| Security Schema | Scopes |
| --------------- | ------ |
| ApiKeyAuth | |
--- ---
### /api/v1/user ### /api/v1/user
@ -1206,12 +1029,6 @@ Get current user
| 401 | Missing auth session | | | 401 | Missing auth session | |
| 500 | Failed to find user \| Failed to find userSettingList | | | 500 | Failed to find user \| Failed to find userSettingList | |
##### Security
| Security Schema | Scopes |
| --------------- | ------ |
| ApiKeyAuth | |
### /api/v1/user/name/{username} ### /api/v1/user/name/{username}
#### GET #### GET
@ -1239,7 +1056,7 @@ Get user by username
#### POST #### POST
##### Summary ##### Summary
Create user setting Upsert user setting
##### Parameters ##### Parameters
@ -1251,17 +1068,11 @@ Create user setting
| Code | Description | Schema | | Code | Description | Schema |
| ---- | ----------- | ------ | | ---- | ----------- | ------ |
| 200 | Created user setting | [store.UserSetting](#storeusersetting) | | 200 | Created user setting | [github_com_usememos_memos_store.UserSetting](#github_com_usememos_memos_storeusersetting) |
| 400 | Malformatted post user setting upsert request \| Invalid user setting format | | | 400 | Malformatted post user setting upsert request \| Invalid user setting format | |
| 401 | Missing auth session | | | 401 | Missing auth session | |
| 500 | Failed to upsert user setting | | | 500 | Failed to upsert user setting | |
##### Security
| Security Schema | Scopes |
| --------------- | ------ |
| ApiKeyAuth | |
--- ---
### /explore/rss.xml ### /explore/rss.xml
@ -1299,7 +1110,28 @@ Get RSS for a user
| 500 | Failed to get system customized profile \| Failed to find memo list \| Failed to generate rss | | 500 | Failed to get system customized profile \| Failed to find memo list \| Failed to generate rss |
--- ---
### /o/get/httpmeta ### /o/get/GetImage
#### GET
##### Summary
Get GetImage from URL
##### Parameters
| Name | Located in | Description | Required | Schema |
| ---- | ---------- | ----------- | -------- | ------ |
| url | query | Image url | Yes | string |
##### Responses
| Code | Description |
| ---- | ----------- |
| 200 | Image |
| 400 | Missing GetImage url \| Wrong url \| Failed to get GetImage url: %s |
| 500 | Failed to write GetImage blob |
### /o/get/GetWebsiteMetadata
#### GET #### GET
##### Summary ##### Summary
@ -1320,27 +1152,6 @@ Get website metadata
| 400 | Missing website url \| Wrong url | | | 400 | Missing website url \| Wrong url | |
| 406 | Failed to get website meta with url: %s | | | 406 | Failed to get website meta with url: %s | |
### /o/get/image
#### GET
##### Summary
Get image from URL
##### Parameters
| Name | Located in | Description | Required | Schema |
| ---- | ---------- | ----------- | -------- | ------ |
| url | query | Image url | Yes | string |
##### Responses
| Code | Description |
| ---- | ----------- |
| 200 | Image |
| 400 | Missing image url \| Wrong url \| Failed to get image url: %s |
| 500 | Failed to write image blob |
--- ---
### Models ### Models
@ -1352,6 +1163,14 @@ Get image from URL
| image | string | | No | | image | string | | No |
| title | string | | No | | title | string | | No |
#### github_com_usememos_memos_store.UserSetting
| Name | Type | Description | Required |
| ---- | ---- | ----------- | -------- |
| key | string | | No |
| userID | integer | | No |
| value | string | | No |
#### profile.Profile #### profile.Profile
| Name | Type | Description | Required | | Name | Type | Description | Required |
@ -1484,21 +1303,12 @@ Get image from URL
| email | string | | No | | email | string | | No |
| id | integer | | No | | id | integer | | No |
| nickname | string | | No | | nickname | string | | No |
| openID | string | | No |
| passwordHash | string | | No | | passwordHash | string | | No |
| role | [store.Role](#storerole) | | No | | role | [store.Role](#storerole) | | No |
| rowStatus | [store.RowStatus](#storerowstatus) | Standard fields | No | | rowStatus | [store.RowStatus](#storerowstatus) | Standard fields | No |
| updatedTs | integer | | No | | updatedTs | integer | | No |
| username | string | Domain specific fields | No | | username | string | Domain specific fields | No |
#### store.UserSetting
| Name | Type | Description | Required |
| ---- | ---- | ----------- | -------- |
| key | string | | No |
| userID | integer | | No |
| value | string | | No |
#### store.Visibility #### store.Visibility
| Name | Type | Description | Required | | Name | Type | Description | Required |
@ -1528,7 +1338,6 @@ Get image from URL
| Name | Type | Description | Required | | Name | Type | Description | Required |
| ---- | ---- | ----------- | -------- | | ---- | ---- | ----------- | -------- |
| downloadToLocal | boolean | | No |
| externalLink | string | | No | | externalLink | string | | No |
| filename | string | | No | | filename | string | | No |
| internalPath | string | | No | | internalPath | string | | No |
@ -1766,7 +1575,6 @@ Get image from URL
| email | string | | No | | email | string | | No |
| nickname | string | | No | | nickname | string | | No |
| password | string | | No | | password | string | | No |
| resetOpenId | boolean | | No |
| rowStatus | [v1.RowStatus](#v1rowstatus) | | No | | rowStatus | [v1.RowStatus](#v1rowstatus) | | No |
| username | string | | No | | username | string | | No |
@ -1820,7 +1628,6 @@ Get image from URL
| email | string | | No | | email | string | | No |
| id | integer | | No | | id | integer | | No |
| nickname | string | | No | | nickname | string | | No |
| openId | string | | No |
| role | [v1.Role](#v1role) | | No | | role | [v1.Role](#v1role) | | No |
| rowStatus | [v1.RowStatus](#v1rowstatus) | Standard fields | No | | rowStatus | [v1.RowStatus](#v1rowstatus) | Standard fields | No |
| updatedTs | integer | | No | | updatedTs | integer | | No |

View File

@ -59,17 +59,15 @@ message User {
string nickname = 5; string nickname = 5;
string open_id = 6; string avatar_url = 6;
string avatar_url = 7; string password = 7 [(google.api.field_behavior) = INPUT_ONLY];
string password = 8 [(google.api.field_behavior) = INPUT_ONLY]; RowStatus row_status = 8;
RowStatus row_status = 9; google.protobuf.Timestamp create_time = 9;
google.protobuf.Timestamp create_time = 10; google.protobuf.Timestamp update_time = 10;
google.protobuf.Timestamp update_time = 11;
} }
message GetUserRequest { message GetUserRequest {

View File

@ -554,7 +554,6 @@
| role | [User.Role](#memos-api-v2-User-Role) | | | | role | [User.Role](#memos-api-v2-User-Role) | | |
| email | [string](#string) | | | | email | [string](#string) | | |
| nickname | [string](#string) | | | | nickname | [string](#string) | | |
| open_id | [string](#string) | | |
| avatar_url | [string](#string) | | | | avatar_url | [string](#string) | | |
| password | [string](#string) | | | | password | [string](#string) | | |
| row_status | [RowStatus](#memos-api-v2-RowStatus) | | | | row_status | [RowStatus](#memos-api-v2-RowStatus) | | |

View File

@ -84,12 +84,11 @@ type User struct {
Role User_Role `protobuf:"varint,3,opt,name=role,proto3,enum=memos.api.v2.User_Role" json:"role,omitempty"` Role User_Role `protobuf:"varint,3,opt,name=role,proto3,enum=memos.api.v2.User_Role" json:"role,omitempty"`
Email string `protobuf:"bytes,4,opt,name=email,proto3" json:"email,omitempty"` Email string `protobuf:"bytes,4,opt,name=email,proto3" json:"email,omitempty"`
Nickname string `protobuf:"bytes,5,opt,name=nickname,proto3" json:"nickname,omitempty"` Nickname string `protobuf:"bytes,5,opt,name=nickname,proto3" json:"nickname,omitempty"`
OpenId string `protobuf:"bytes,6,opt,name=open_id,json=openId,proto3" json:"open_id,omitempty"` AvatarUrl string `protobuf:"bytes,6,opt,name=avatar_url,json=avatarUrl,proto3" json:"avatar_url,omitempty"`
AvatarUrl string `protobuf:"bytes,7,opt,name=avatar_url,json=avatarUrl,proto3" json:"avatar_url,omitempty"` Password string `protobuf:"bytes,7,opt,name=password,proto3" json:"password,omitempty"`
Password string `protobuf:"bytes,8,opt,name=password,proto3" json:"password,omitempty"` RowStatus RowStatus `protobuf:"varint,8,opt,name=row_status,json=rowStatus,proto3,enum=memos.api.v2.RowStatus" json:"row_status,omitempty"`
RowStatus RowStatus `protobuf:"varint,9,opt,name=row_status,json=rowStatus,proto3,enum=memos.api.v2.RowStatus" json:"row_status,omitempty"` CreateTime *timestamppb.Timestamp `protobuf:"bytes,9,opt,name=create_time,json=createTime,proto3" json:"create_time,omitempty"`
CreateTime *timestamppb.Timestamp `protobuf:"bytes,10,opt,name=create_time,json=createTime,proto3" json:"create_time,omitempty"` UpdateTime *timestamppb.Timestamp `protobuf:"bytes,10,opt,name=update_time,json=updateTime,proto3" json:"update_time,omitempty"`
UpdateTime *timestamppb.Timestamp `protobuf:"bytes,11,opt,name=update_time,json=updateTime,proto3" json:"update_time,omitempty"`
} }
func (x *User) Reset() { func (x *User) Reset() {
@ -159,13 +158,6 @@ func (x *User) GetNickname() string {
return "" return ""
} }
func (x *User) GetOpenId() string {
if x != nil {
return x.OpenId
}
return ""
}
func (x *User) GetAvatarUrl() string { func (x *User) GetAvatarUrl() string {
if x != nil { if x != nil {
return x.AvatarUrl return x.AvatarUrl
@ -781,7 +773,7 @@ var file_api_v2_user_service_proto_rawDesc = []byte{
0x69, 0x2f, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x5f, 0x62, 0x65, 0x68, 0x61, 0x76, 0x69, 0x6f, 0x72, 0x69, 0x2f, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x5f, 0x62, 0x65, 0x68, 0x61, 0x76, 0x69, 0x6f, 0x72,
0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1f, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1f, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70,
0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d,
0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xd9, 0x03, 0x0a, 0x04, 0x55, 0x73, 0x65, 0x72, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xc0, 0x03, 0x0a, 0x04, 0x55, 0x73, 0x65, 0x72,
0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x02, 0x69, 0x64, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x02, 0x69, 0x64,
0x12, 0x1a, 0x0a, 0x08, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x12, 0x1a, 0x0a, 0x08, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01,
0x28, 0x09, 0x52, 0x08, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x2b, 0x0a, 0x04, 0x28, 0x09, 0x52, 0x08, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x2b, 0x0a, 0x04,
@ -790,154 +782,153 @@ var file_api_v2_user_service_proto_rawDesc = []byte{
0x6f, 0x6c, 0x65, 0x52, 0x04, 0x72, 0x6f, 0x6c, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x6d, 0x61, 0x6f, 0x6c, 0x65, 0x52, 0x04, 0x72, 0x6f, 0x6c, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x6d, 0x61,
0x69, 0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x65, 0x6d, 0x61, 0x69, 0x6c, 0x12, 0x69, 0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x65, 0x6d, 0x61, 0x69, 0x6c, 0x12,
0x1a, 0x0a, 0x08, 0x6e, 0x69, 0x63, 0x6b, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x1a, 0x0a, 0x08, 0x6e, 0x69, 0x63, 0x6b, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28,
0x09, 0x52, 0x08, 0x6e, 0x69, 0x63, 0x6b, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x17, 0x0a, 0x07, 0x6f, 0x09, 0x52, 0x08, 0x6e, 0x69, 0x63, 0x6b, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x61,
0x70, 0x65, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x6f, 0x70, 0x76, 0x61, 0x74, 0x61, 0x72, 0x5f, 0x75, 0x72, 0x6c, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52,
0x65, 0x6e, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x61, 0x76, 0x61, 0x74, 0x61, 0x72, 0x5f, 0x75, 0x09, 0x61, 0x76, 0x61, 0x74, 0x61, 0x72, 0x55, 0x72, 0x6c, 0x12, 0x1f, 0x0a, 0x08, 0x70, 0x61,
0x72, 0x6c, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x61, 0x76, 0x61, 0x74, 0x61, 0x72, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x42, 0x03, 0xe0, 0x41,
0x55, 0x72, 0x6c, 0x12, 0x1f, 0x0a, 0x08, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x18, 0x04, 0x52, 0x08, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x12, 0x36, 0x0a, 0x0a, 0x72,
0x08, 0x20, 0x01, 0x28, 0x09, 0x42, 0x03, 0xe0, 0x41, 0x04, 0x52, 0x08, 0x70, 0x61, 0x73, 0x73, 0x6f, 0x77, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0e, 0x32,
0x77, 0x6f, 0x72, 0x64, 0x12, 0x36, 0x0a, 0x0a, 0x72, 0x6f, 0x77, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x17, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x32, 0x2e, 0x52,
0x75, 0x73, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x17, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x6f, 0x77, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x09, 0x72, 0x6f, 0x77, 0x53, 0x74, 0x61,
0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x32, 0x2e, 0x52, 0x6f, 0x77, 0x53, 0x74, 0x61, 0x74, 0x75, 0x74, 0x75, 0x73, 0x12, 0x3b, 0x0a, 0x0b, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x5f, 0x74, 0x69,
0x73, 0x52, 0x09, 0x72, 0x6f, 0x77, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x3b, 0x0a, 0x0b, 0x6d, 0x65, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c,
0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73,
0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x0a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x54, 0x69, 0x6d, 0x65,
0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x0a, 0x63, 0x12, 0x3b, 0x0a, 0x0b, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18,
0x72, 0x65, 0x61, 0x74, 0x65, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x3b, 0x0a, 0x0b, 0x75, 0x70, 0x64, 0x0a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70,
0x61, 0x74, 0x65, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d,
0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x70, 0x52, 0x0a, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x54, 0x69, 0x6d, 0x65, 0x22, 0x3b, 0x0a,
0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x0a, 0x75, 0x70, 0x64, 0x61, 0x04, 0x52, 0x6f, 0x6c, 0x65, 0x12, 0x14, 0x0a, 0x10, 0x52, 0x4f, 0x4c, 0x45, 0x5f, 0x55, 0x4e,
0x74, 0x65, 0x54, 0x69, 0x6d, 0x65, 0x22, 0x3b, 0x0a, 0x04, 0x52, 0x6f, 0x6c, 0x65, 0x12, 0x14, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x08, 0x0a, 0x04, 0x48,
0x0a, 0x10, 0x52, 0x4f, 0x4c, 0x45, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x4f, 0x53, 0x54, 0x10, 0x01, 0x12, 0x09, 0x0a, 0x05, 0x41, 0x44, 0x4d, 0x49, 0x4e, 0x10, 0x02,
0x45, 0x44, 0x10, 0x00, 0x12, 0x08, 0x0a, 0x04, 0x48, 0x4f, 0x53, 0x54, 0x10, 0x01, 0x12, 0x09, 0x12, 0x08, 0x0a, 0x04, 0x55, 0x53, 0x45, 0x52, 0x10, 0x03, 0x22, 0x2c, 0x0a, 0x0e, 0x47, 0x65,
0x0a, 0x05, 0x41, 0x44, 0x4d, 0x49, 0x4e, 0x10, 0x02, 0x12, 0x08, 0x0a, 0x04, 0x55, 0x53, 0x45, 0x74, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1a, 0x0a, 0x08,
0x52, 0x10, 0x03, 0x22, 0x2c, 0x0a, 0x0e, 0x47, 0x65, 0x74, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08,
0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0x39, 0x0a, 0x0f, 0x47, 0x65, 0x74, 0x55,
0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x73, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x26, 0x0a, 0x04, 0x75,
0x65, 0x22, 0x39, 0x0a, 0x0f, 0x47, 0x65, 0x74, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x73, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x6d, 0x65, 0x6d, 0x6f,
0x6f, 0x6e, 0x73, 0x65, 0x12, 0x26, 0x0a, 0x04, 0x75, 0x73, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x32, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x52, 0x04, 0x75,
0x73, 0x65, 0x72, 0x22, 0x78, 0x0a, 0x11, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x55, 0x73, 0x65,
0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x75, 0x73, 0x65, 0x72,
0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x75, 0x73, 0x65, 0x72,
0x6e, 0x61, 0x6d, 0x65, 0x12, 0x26, 0x0a, 0x04, 0x75, 0x73, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01,
0x28, 0x0b, 0x32, 0x12, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76,
0x32, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x52, 0x04, 0x75, 0x73, 0x65, 0x72, 0x22, 0x78, 0x0a, 0x11, 0x32, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x52, 0x04, 0x75, 0x73, 0x65, 0x72, 0x12, 0x1f, 0x0a, 0x0b,
0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x5f, 0x6d, 0x61, 0x73, 0x6b, 0x18, 0x03, 0x20, 0x03, 0x28,
0x74, 0x12, 0x1a, 0x0a, 0x08, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x09, 0x52, 0x0a, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4d, 0x61, 0x73, 0x6b, 0x22, 0x3c, 0x0a,
0x01, 0x28, 0x09, 0x52, 0x08, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x26, 0x0a, 0x12, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f,
0x04, 0x75, 0x73, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x6d, 0x65, 0x6e, 0x73, 0x65, 0x12, 0x26, 0x0a, 0x04, 0x75, 0x73, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28,
0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x32, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x52, 0x0b, 0x32, 0x12, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x32,
0x04, 0x75, 0x73, 0x65, 0x72, 0x12, 0x1f, 0x0a, 0x0b, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x5f, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x52, 0x04, 0x75, 0x73, 0x65, 0x72, 0x22, 0x39, 0x0a, 0x1b, 0x4c,
0x6d, 0x61, 0x73, 0x6b, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0a, 0x75, 0x70, 0x64, 0x61, 0x69, 0x73, 0x74, 0x55, 0x73, 0x65, 0x72, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x54, 0x6f, 0x6b,
0x74, 0x65, 0x4d, 0x61, 0x73, 0x6b, 0x22, 0x3c, 0x0a, 0x12, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x65, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x75, 0x73,
0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x26, 0x0a, 0x04, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x75, 0x73,
0x75, 0x73, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x6d, 0x65, 0x6d, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0x62, 0x0a, 0x1c, 0x4c, 0x69, 0x73, 0x74, 0x55, 0x73,
0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x32, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x52, 0x04, 0x65, 0x72, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x73, 0x52, 0x65,
0x75, 0x73, 0x65, 0x72, 0x22, 0x39, 0x0a, 0x1b, 0x4c, 0x69, 0x73, 0x74, 0x55, 0x73, 0x65, 0x72, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x42, 0x0a, 0x0d, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73,
0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1d, 0x2e,
0x65, 0x73, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x32, 0x2e, 0x55, 0x73, 0x65,
0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0x72, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x52, 0x0c, 0x61, 0x63,
0x62, 0x0a, 0x1c, 0x4c, 0x69, 0x73, 0x74, 0x55, 0x73, 0x65, 0x72, 0x41, 0x63, 0x63, 0x65, 0x73, 0x63, 0x65, 0x73, 0x73, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x73, 0x22, 0x85, 0x01, 0x0a, 0x1c, 0x43,
0x73, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12,
0x42, 0x0a, 0x0d, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x73,
0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61,
0x70, 0x69, 0x2e, 0x76, 0x32, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73,
0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x52, 0x0c, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x54, 0x6f, 0x6b,
0x65, 0x6e, 0x73, 0x22, 0x85, 0x01, 0x0a, 0x1c, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x55, 0x73,
0x65, 0x72, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x52, 0x65, 0x71,
0x75, 0x65, 0x73, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65,
0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65,
0x12, 0x49, 0x0a, 0x11, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x5f,
0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x6d, 0x65,
0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x32, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x41,
0x63, 0x63, 0x65, 0x73, 0x73, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x52, 0x0f, 0x75, 0x73, 0x65, 0x72,
0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x22, 0x61, 0x0a, 0x1d, 0x43,
0x72, 0x65, 0x61, 0x74, 0x65, 0x55, 0x73, 0x65, 0x72, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x54, 0x72, 0x65, 0x61, 0x74, 0x65, 0x55, 0x73, 0x65, 0x72, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x54,
0x6f, 0x6b, 0x65, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x40, 0x0a, 0x0c, 0x6f, 0x6b, 0x65, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x75,
0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x75,
0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x49, 0x0a, 0x11, 0x75, 0x73, 0x65, 0x72, 0x5f,
0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x02, 0x20, 0x01,
0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76,
0x32, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x54, 0x6f, 0x6b, 0x65, 0x32, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x54, 0x6f, 0x6b, 0x65,
0x6e, 0x52, 0x0b, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x22, 0x5d, 0x6e, 0x52, 0x0f, 0x75, 0x73, 0x65, 0x72, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x54, 0x6f, 0x6b,
0x0a, 0x1c, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x55, 0x73, 0x65, 0x72, 0x41, 0x63, 0x63, 0x65, 0x65, 0x6e, 0x22, 0x61, 0x0a, 0x1d, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x55, 0x73, 0x65, 0x72,
0x73, 0x73, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1a, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f,
0x0a, 0x08, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x6e, 0x73, 0x65, 0x12, 0x40, 0x0a, 0x0c, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x74, 0x6f,
0x52, 0x08, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x21, 0x0a, 0x0c, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x6d, 0x65, 0x6d, 0x6f,
0x63, 0x65, 0x73, 0x73, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x32, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x41, 0x63, 0x63,
0x52, 0x0b, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x22, 0x1f, 0x0a, 0x65, 0x73, 0x73, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x52, 0x0b, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73,
0x1d, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x55, 0x73, 0x65, 0x72, 0x41, 0x63, 0x63, 0x65, 0x73, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x22, 0x5d, 0x0a, 0x1c, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x55,
0x73, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0xca, 0x73, 0x65, 0x72, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x52, 0x65,
0x01, 0x0a, 0x0f, 0x55, 0x73, 0x65, 0x72, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x54, 0x6f, 0x6b, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d,
0x65, 0x6e, 0x12, 0x21, 0x0a, 0x0c, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d,
0x65, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x65, 0x12, 0x21, 0x0a, 0x0c, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x74, 0x6f, 0x6b, 0x65,
0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x54,
0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x6f, 0x6b, 0x65, 0x6e, 0x22, 0x1f, 0x0a, 0x1d, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x55, 0x73,
0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x37, 0x0a, 0x09, 0x69, 0x73, 0x73, 0x75, 0x65, 0x65, 0x72, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x52, 0x65, 0x73,
0x64, 0x5f, 0x61, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0xca, 0x01, 0x0a, 0x0f, 0x55, 0x73, 0x65, 0x72, 0x41, 0x63,
0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x63, 0x65, 0x73, 0x73, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x21, 0x0a, 0x0c, 0x61, 0x63, 0x63,
0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x08, 0x69, 0x73, 0x73, 0x75, 0x65, 0x64, 0x41, 0x74, 0x65, 0x73, 0x73, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52,
0x12, 0x39, 0x0a, 0x0a, 0x65, 0x78, 0x70, 0x69, 0x72, 0x65, 0x73, 0x5f, 0x61, 0x74, 0x18, 0x04, 0x0b, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x20, 0x0a, 0x0b,
0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28,
0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x09, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x37,
0x52, 0x09, 0x65, 0x78, 0x70, 0x69, 0x72, 0x65, 0x73, 0x41, 0x74, 0x32, 0xb9, 0x06, 0x0a, 0x0b, 0x0a, 0x09, 0x69, 0x73, 0x73, 0x75, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28,
0x55, 0x73, 0x65, 0x72, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x73, 0x0a, 0x07, 0x47, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
0x65, 0x74, 0x55, 0x73, 0x65, 0x72, 0x12, 0x1c, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x08, 0x69,
0x70, 0x69, 0x2e, 0x76, 0x32, 0x2e, 0x47, 0x65, 0x74, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x71, 0x73, 0x73, 0x75, 0x65, 0x64, 0x41, 0x74, 0x12, 0x39, 0x0a, 0x0a, 0x65, 0x78, 0x70, 0x69, 0x72,
0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x65, 0x73, 0x5f, 0x61, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f,
0x2e, 0x76, 0x32, 0x2e, 0x47, 0x65, 0x74, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69,
0x6e, 0x73, 0x65, 0x22, 0x2b, 0xda, 0x41, 0x08, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x09, 0x65, 0x78, 0x70, 0x69, 0x72, 0x65, 0x73,
0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1a, 0x12, 0x18, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x32, 0x2f, 0x41, 0x74, 0x32, 0xb9, 0x06, 0x0a, 0x0b, 0x55, 0x73, 0x65, 0x72, 0x53, 0x65, 0x72, 0x76, 0x69,
0x75, 0x73, 0x65, 0x72, 0x73, 0x2f, 0x7b, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x7d, 0x63, 0x65, 0x12, 0x73, 0x0a, 0x07, 0x47, 0x65, 0x74, 0x55, 0x73, 0x65, 0x72, 0x12, 0x1c, 0x2e,
0x12, 0x7f, 0x0a, 0x0a, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x55, 0x73, 0x65, 0x72, 0x12, 0x1f, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x32, 0x2e, 0x47, 0x65, 0x74,
0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x32, 0x2e, 0x55, 0x70, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x6d, 0x65,
0x64, 0x61, 0x74, 0x65, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x32, 0x2e, 0x47, 0x65, 0x74, 0x55, 0x73,
0x20, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x32, 0x2e, 0x55, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x2b, 0xda, 0x41, 0x08, 0x75,
0x70, 0x64, 0x61, 0x74, 0x65, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1a, 0x12, 0x18, 0x2f,
0x65, 0x22, 0x2e, 0xda, 0x41, 0x08, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x82, 0xd3, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x32, 0x2f, 0x75, 0x73, 0x65, 0x72, 0x73, 0x2f, 0x7b, 0x75, 0x73,
0xe4, 0x93, 0x02, 0x1d, 0x3a, 0x01, 0x2a, 0x22, 0x18, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x32, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x7d, 0x12, 0x7f, 0x0a, 0x0a, 0x55, 0x70, 0x64, 0x61, 0x74,
0x65, 0x55, 0x73, 0x65, 0x72, 0x12, 0x1f, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70,
0x69, 0x2e, 0x76, 0x32, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x55, 0x73, 0x65, 0x72, 0x52,
0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61,
0x70, 0x69, 0x2e, 0x76, 0x32, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x55, 0x73, 0x65, 0x72,
0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x2e, 0xda, 0x41, 0x08, 0x75, 0x73, 0x65,
0x72, 0x6e, 0x61, 0x6d, 0x65, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1d, 0x3a, 0x01, 0x2a, 0x22, 0x18,
0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x32, 0x2f, 0x75, 0x73, 0x65, 0x72, 0x73, 0x2f, 0x7b, 0x75,
0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x7d, 0x12, 0xa8, 0x01, 0x0a, 0x14, 0x4c, 0x69, 0x73,
0x74, 0x55, 0x73, 0x65, 0x72, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x54, 0x6f, 0x6b, 0x65, 0x6e,
0x73, 0x12, 0x29, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x32,
0x2e, 0x4c, 0x69, 0x73, 0x74, 0x55, 0x73, 0x65, 0x72, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x54,
0x6f, 0x6b, 0x65, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2a, 0x2e, 0x6d,
0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x32, 0x2e, 0x4c, 0x69, 0x73, 0x74,
0x55, 0x73, 0x65, 0x72, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x73,
0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x39, 0xda, 0x41, 0x08, 0x75, 0x73, 0x65,
0x72, 0x6e, 0x61, 0x6d, 0x65, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x28, 0x12, 0x26, 0x2f, 0x61, 0x70,
0x69, 0x2f, 0x76, 0x32, 0x2f, 0x75, 0x73, 0x65, 0x72, 0x73, 0x2f, 0x7b, 0x75, 0x73, 0x65, 0x72,
0x6e, 0x61, 0x6d, 0x65, 0x7d, 0x2f, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x74, 0x6f, 0x6b,
0x65, 0x6e, 0x73, 0x12, 0xbe, 0x01, 0x0a, 0x15, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x55, 0x73,
0x65, 0x72, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x2a, 0x2e,
0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x32, 0x2e, 0x43, 0x72, 0x65,
0x61, 0x74, 0x65, 0x55, 0x73, 0x65, 0x72, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x54, 0x6f, 0x6b,
0x65, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2b, 0x2e, 0x6d, 0x65, 0x6d, 0x6f,
0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x32, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x55,
0x73, 0x65, 0x72, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x52, 0x65,
0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x4c, 0xda, 0x41, 0x08, 0x75, 0x73, 0x65, 0x72, 0x6e,
0x61, 0x6d, 0x65, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x3b, 0x3a, 0x11, 0x75, 0x73, 0x65, 0x72, 0x5f,
0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x22, 0x26, 0x2f, 0x61,
0x70, 0x69, 0x2f, 0x76, 0x32, 0x2f, 0x75, 0x73, 0x65, 0x72, 0x73, 0x2f, 0x7b, 0x75, 0x73, 0x65,
0x72, 0x6e, 0x61, 0x6d, 0x65, 0x7d, 0x2f, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x74, 0x6f,
0x6b, 0x65, 0x6e, 0x73, 0x12, 0xc7, 0x01, 0x0a, 0x15, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x55,
0x73, 0x65, 0x72, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x2a,
0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x32, 0x2e, 0x44, 0x65,
0x6c, 0x65, 0x74, 0x65, 0x55, 0x73, 0x65, 0x72, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x54, 0x6f,
0x6b, 0x65, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2b, 0x2e, 0x6d, 0x65, 0x6d,
0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x32, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65,
0x55, 0x73, 0x65, 0x72, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x52,
0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x55, 0xda, 0x41, 0x15, 0x75, 0x73, 0x65, 0x72,
0x6e, 0x61, 0x6d, 0x65, 0x2c, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x74, 0x6f, 0x6b, 0x65,
0x6e, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x37, 0x2a, 0x35, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x32,
0x2f, 0x75, 0x73, 0x65, 0x72, 0x73, 0x2f, 0x7b, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x2f, 0x75, 0x73, 0x65, 0x72, 0x73, 0x2f, 0x7b, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65,
0x7d, 0x12, 0xa8, 0x01, 0x0a, 0x14, 0x4c, 0x69, 0x73, 0x74, 0x55, 0x73, 0x65, 0x72, 0x41, 0x63, 0x7d, 0x2f, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x73, 0x2f,
0x63, 0x65, 0x73, 0x73, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x73, 0x12, 0x29, 0x2e, 0x6d, 0x65, 0x6d, 0x7b, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x7d, 0x42, 0xa8,
0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x32, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x55, 0x73, 0x01, 0x0a, 0x10, 0x63, 0x6f, 0x6d, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69,
0x65, 0x72, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x73, 0x52, 0x65, 0x2e, 0x76, 0x32, 0x42, 0x10, 0x55, 0x73, 0x65, 0x72, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65,
0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2a, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x30, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e,
0x69, 0x2e, 0x76, 0x32, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x55, 0x73, 0x65, 0x72, 0x41, 0x63, 0x63, 0x63, 0x6f, 0x6d, 0x2f, 0x75, 0x73, 0x65, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2f, 0x6d, 0x65, 0x6d,
0x65, 0x73, 0x73, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x6f, 0x73, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x67, 0x65, 0x6e, 0x2f, 0x61, 0x70, 0x69,
0x65, 0x22, 0x39, 0xda, 0x41, 0x08, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x82, 0xd3, 0x2f, 0x76, 0x32, 0x3b, 0x61, 0x70, 0x69, 0x76, 0x32, 0xa2, 0x02, 0x03, 0x4d, 0x41, 0x58, 0xaa,
0xe4, 0x93, 0x02, 0x28, 0x12, 0x26, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x32, 0x2f, 0x75, 0x73, 0x02, 0x0c, 0x4d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x41, 0x70, 0x69, 0x2e, 0x56, 0x32, 0xca, 0x02,
0x65, 0x72, 0x73, 0x2f, 0x7b, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x7d, 0x2f, 0x61, 0x0c, 0x4d, 0x65, 0x6d, 0x6f, 0x73, 0x5c, 0x41, 0x70, 0x69, 0x5c, 0x56, 0x32, 0xe2, 0x02, 0x18,
0x63, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x73, 0x12, 0xbe, 0x01, 0x0a, 0x4d, 0x65, 0x6d, 0x6f, 0x73, 0x5c, 0x41, 0x70, 0x69, 0x5c, 0x56, 0x32, 0x5c, 0x47, 0x50, 0x42,
0x15, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x55, 0x73, 0x65, 0x72, 0x41, 0x63, 0x63, 0x65, 0x73, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x0e, 0x4d, 0x65, 0x6d, 0x6f, 0x73,
0x73, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x2a, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x3a, 0x3a, 0x41, 0x70, 0x69, 0x3a, 0x3a, 0x56, 0x32, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f,
0x70, 0x69, 0x2e, 0x76, 0x32, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x55, 0x73, 0x65, 0x72, 0x33,
0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65,
0x73, 0x74, 0x1a, 0x2b, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76,
0x32, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x55, 0x73, 0x65, 0x72, 0x41, 0x63, 0x63, 0x65,
0x73, 0x73, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22,
0x4c, 0xda, 0x41, 0x08, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x82, 0xd3, 0xe4, 0x93,
0x02, 0x3b, 0x3a, 0x11, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x5f,
0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x22, 0x26, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x32, 0x2f, 0x75,
0x73, 0x65, 0x72, 0x73, 0x2f, 0x7b, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x7d, 0x2f,
0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x73, 0x12, 0xc7, 0x01,
0x0a, 0x15, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x55, 0x73, 0x65, 0x72, 0x41, 0x63, 0x63, 0x65,
0x73, 0x73, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x2a, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e,
0x61, 0x70, 0x69, 0x2e, 0x76, 0x32, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x55, 0x73, 0x65,
0x72, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x52, 0x65, 0x71, 0x75,
0x65, 0x73, 0x74, 0x1a, 0x2b, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e,
0x76, 0x32, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x55, 0x73, 0x65, 0x72, 0x41, 0x63, 0x63,
0x65, 0x73, 0x73, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65,
0x22, 0x55, 0xda, 0x41, 0x15, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x2c, 0x61, 0x63,
0x63, 0x65, 0x73, 0x73, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x37,
0x2a, 0x35, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x32, 0x2f, 0x75, 0x73, 0x65, 0x72, 0x73, 0x2f,
0x7b, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x7d, 0x2f, 0x61, 0x63, 0x63, 0x65, 0x73,
0x73, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x73, 0x2f, 0x7b, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73,
0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x7d, 0x42, 0xa8, 0x01, 0x0a, 0x10, 0x63, 0x6f, 0x6d, 0x2e,
0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x32, 0x42, 0x10, 0x55, 0x73,
0x65, 0x72, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01,
0x5a, 0x30, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x75, 0x73, 0x65,
0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2f, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2f, 0x70, 0x72, 0x6f, 0x74,
0x6f, 0x2f, 0x67, 0x65, 0x6e, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x32, 0x3b, 0x61, 0x70, 0x69,
0x76, 0x32, 0xa2, 0x02, 0x03, 0x4d, 0x41, 0x58, 0xaa, 0x02, 0x0c, 0x4d, 0x65, 0x6d, 0x6f, 0x73,
0x2e, 0x41, 0x70, 0x69, 0x2e, 0x56, 0x32, 0xca, 0x02, 0x0c, 0x4d, 0x65, 0x6d, 0x6f, 0x73, 0x5c,
0x41, 0x70, 0x69, 0x5c, 0x56, 0x32, 0xe2, 0x02, 0x18, 0x4d, 0x65, 0x6d, 0x6f, 0x73, 0x5c, 0x41,
0x70, 0x69, 0x5c, 0x56, 0x32, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74,
0x61, 0xea, 0x02, 0x0e, 0x4d, 0x65, 0x6d, 0x6f, 0x73, 0x3a, 0x3a, 0x41, 0x70, 0x69, 0x3a, 0x3a,
0x56, 0x32, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
} }
var ( var (

View File

@ -23,7 +23,6 @@ CREATE TABLE user (
email TEXT NOT NULL DEFAULT '', email TEXT NOT NULL DEFAULT '',
nickname TEXT NOT NULL DEFAULT '', nickname TEXT NOT NULL DEFAULT '',
password_hash TEXT NOT NULL, password_hash TEXT NOT NULL,
open_id TEXT NOT NULL UNIQUE,
avatar_url TEXT NOT NULL DEFAULT '' avatar_url TEXT NOT NULL DEFAULT ''
); );

View File

@ -0,0 +1,25 @@
DROP TABLE IF EXISTS user_temp;
CREATE TABLE user_temp (
id INTEGER PRIMARY KEY AUTOINCREMENT,
created_ts BIGINT NOT NULL DEFAULT (strftime('%s', 'now')),
updated_ts BIGINT NOT NULL DEFAULT (strftime('%s', 'now')),
row_status TEXT NOT NULL CHECK (row_status IN ('NORMAL', 'ARCHIVED')) DEFAULT 'NORMAL',
username TEXT NOT NULL UNIQUE,
role TEXT NOT NULL CHECK (role IN ('HOST', 'ADMIN', 'USER')) DEFAULT 'USER',
email TEXT NOT NULL DEFAULT '',
nickname TEXT NOT NULL DEFAULT '',
password_hash TEXT NOT NULL,
avatar_url TEXT NOT NULL DEFAULT ''
);
INSERT INTO
user_temp (id, created_ts, updated_ts, row_status, username, role, email, nickname, password_hash, avatar_url)
SELECT
id, created_ts, updated_ts, row_status, username, role, email, nickname, password_hash, avatar_url
FROM
user;
DROP TABLE user;
ALTER TABLE user_temp_temp RENAME TO user_temp;

View File

@ -23,7 +23,6 @@ CREATE TABLE user (
email TEXT NOT NULL DEFAULT '', email TEXT NOT NULL DEFAULT '',
nickname TEXT NOT NULL DEFAULT '', nickname TEXT NOT NULL DEFAULT '',
password_hash TEXT NOT NULL, password_hash TEXT NOT NULL,
open_id TEXT NOT NULL UNIQUE,
avatar_url TEXT NOT NULL DEFAULT '' avatar_url TEXT NOT NULL DEFAULT ''
); );

View File

@ -43,7 +43,6 @@ type User struct {
Email string Email string
Nickname string Nickname string
PasswordHash string PasswordHash string
OpenID string
AvatarURL string AvatarURL string
} }
@ -59,7 +58,6 @@ type UpdateUser struct {
Password *string Password *string
AvatarURL *string AvatarURL *string
PasswordHash *string PasswordHash *string
OpenID *string
} }
type FindUser struct { type FindUser struct {
@ -69,7 +67,6 @@ type FindUser struct {
Role *Role Role *Role
Email *string Email *string
Nickname *string Nickname *string
OpenID *string
} }
type DeleteUser struct { type DeleteUser struct {
@ -83,10 +80,9 @@ func (s *Store) CreateUser(ctx context.Context, create *User) (*User, error) {
role, role,
email, email,
nickname, nickname,
password_hash, password_hash
open_id
) )
VALUES (?, ?, ?, ?, ?, ?) VALUES (?, ?, ?, ?, ?)
RETURNING id, avatar_url, created_ts, updated_ts, row_status RETURNING id, avatar_url, created_ts, updated_ts, row_status
` `
if err := s.db.QueryRowContext( if err := s.db.QueryRowContext(
@ -97,7 +93,6 @@ func (s *Store) CreateUser(ctx context.Context, create *User) (*User, error) {
create.Email, create.Email,
create.Nickname, create.Nickname,
create.PasswordHash, create.PasswordHash,
create.OpenID,
).Scan( ).Scan(
&create.ID, &create.ID,
&create.AvatarURL, &create.AvatarURL,
@ -136,16 +131,13 @@ func (s *Store) UpdateUser(ctx context.Context, update *UpdateUser) (*User, erro
if v := update.PasswordHash; v != nil { if v := update.PasswordHash; v != nil {
set, args = append(set, "password_hash = ?"), append(args, *v) set, args = append(set, "password_hash = ?"), append(args, *v)
} }
if v := update.OpenID; v != nil {
set, args = append(set, "open_id = ?"), append(args, *v)
}
args = append(args, update.ID) args = append(args, update.ID)
query := ` query := `
UPDATE user UPDATE user
SET ` + strings.Join(set, ", ") + ` SET ` + strings.Join(set, ", ") + `
WHERE id = ? WHERE id = ?
RETURNING id, username, role, email, nickname, password_hash, open_id, avatar_url, created_ts, updated_ts, row_status RETURNING id, username, role, email, nickname, password_hash, avatar_url, created_ts, updated_ts, row_status
` `
user := &User{} user := &User{}
if err := s.db.QueryRowContext(ctx, query, args...).Scan( if err := s.db.QueryRowContext(ctx, query, args...).Scan(
@ -155,7 +147,6 @@ func (s *Store) UpdateUser(ctx context.Context, update *UpdateUser) (*User, erro
&user.Email, &user.Email,
&user.Nickname, &user.Nickname,
&user.PasswordHash, &user.PasswordHash,
&user.OpenID,
&user.AvatarURL, &user.AvatarURL,
&user.CreatedTs, &user.CreatedTs,
&user.UpdatedTs, &user.UpdatedTs,
@ -186,9 +177,6 @@ func (s *Store) ListUsers(ctx context.Context, find *FindUser) ([]*User, error)
if v := find.Nickname; v != nil { if v := find.Nickname; v != nil {
where, args = append(where, "nickname = ?"), append(args, *v) where, args = append(where, "nickname = ?"), append(args, *v)
} }
if v := find.OpenID; v != nil {
where, args = append(where, "open_id = ?"), append(args, *v)
}
query := ` query := `
SELECT SELECT
@ -198,7 +186,6 @@ func (s *Store) ListUsers(ctx context.Context, find *FindUser) ([]*User, error)
email, email,
nickname, nickname,
password_hash, password_hash,
open_id,
avatar_url, avatar_url,
created_ts, created_ts,
updated_ts, updated_ts,
@ -223,7 +210,6 @@ func (s *Store) ListUsers(ctx context.Context, find *FindUser) ([]*User, error)
&user.Email, &user.Email,
&user.Nickname, &user.Nickname,
&user.PasswordHash, &user.PasswordHash,
&user.OpenID,
&user.AvatarURL, &user.AvatarURL,
&user.CreatedTs, &user.CreatedTs,
&user.UpdatedTs, &user.UpdatedTs,

View File

@ -42,7 +42,6 @@ func createTestingHostUser(ctx context.Context, ts *store.Store) (*store.User, e
Role: store.RoleHost, Role: store.RoleHost,
Email: "test@test.com", Email: "test@test.com",
Nickname: "test_nickname", Nickname: "test_nickname",
OpenID: "test_open_id",
} }
passwordHash, err := bcrypt.GenerateFromPassword([]byte("test_password"), bcrypt.DefaultCost) passwordHash, err := bcrypt.GenerateFromPassword([]byte("test_password"), bcrypt.DefaultCost)
if err != nil { if err != nil {

View File

@ -1,37 +1,13 @@
import { Button, Input, Textarea } from "@mui/joy"; import { Button } from "@mui/joy";
import useCurrentUser from "@/hooks/useCurrentUser"; import useCurrentUser from "@/hooks/useCurrentUser";
import { useUserV1Store } from "@/store/v1";
import { useTranslate } from "@/utils/i18n"; import { useTranslate } from "@/utils/i18n";
import showChangePasswordDialog from "../ChangePasswordDialog"; import showChangePasswordDialog from "../ChangePasswordDialog";
import { showCommonDialog } from "../Dialog/CommonDialog";
import Icon from "../Icon";
import showUpdateAccountDialog from "../UpdateAccountDialog"; import showUpdateAccountDialog from "../UpdateAccountDialog";
import UserAvatar from "../UserAvatar"; import UserAvatar from "../UserAvatar";
const MyAccountSection = () => { const MyAccountSection = () => {
const t = useTranslate(); const t = useTranslate();
const userV1Store = useUserV1Store();
const user = useCurrentUser(); const user = useCurrentUser();
const openAPIRoute = `${window.location.origin}/api/v1/memo?openId=${user.openId}`;
const handleResetOpenIdBtnClick = async () => {
showCommonDialog({
title: t("setting.account-section.openapi-reset"),
content: t("setting.account-section.openapi-reset-warning"),
style: "warning",
dialogName: "reset-openid-dialog",
onConfirm: async () => {
await userV1Store.updateUser(
{
username: user.username,
},
["reset_open_id"]
);
},
});
};
const exampleWithCurl = `curl '${openAPIRoute}' -H 'Content-Type: application/json' --data-raw '{"content":"Hello world!"}'`;
return ( return (
<> <>
@ -52,17 +28,6 @@ const MyAccountSection = () => {
</Button> </Button>
</div> </div>
</div> </div>
<div className="section-container openapi-section-container mt-6">
<p className="title-text">Open ID</p>
<div className="w-full flex flex-row justify-start items-center">
<Input className="grow mr-2" value={user.openId} readOnly />
<Button className="shrink-0" color="neutral" variant="outlined" onClick={handleResetOpenIdBtnClick}>
<Icon.RefreshCw className="h-4 w-4" />
</Button>
</div>
<p className="title-text">Open API Example with cURL</p>
<Textarea className="w-full !font-mono !text-sm whitespace-pre" value={exampleWithCurl} readOnly />
</div>
</> </>
); );
}; };

View File

@ -12,7 +12,6 @@ interface User {
role: UserRole; role: UserRole;
email: string; email: string;
nickname: string; nickname: string;
openId: string;
avatarUrl: string; avatarUrl: string;
userSettingList: UserSetting[]; userSettingList: UserSetting[];
@ -34,7 +33,6 @@ interface UserPatch {
nickname?: string; nickname?: string;
avatarUrl?: string; avatarUrl?: string;
password?: string; password?: string;
resetOpenId?: boolean;
} }
interface UserDelete { interface UserDelete {

View File

@ -37,32 +37,27 @@ export declare class User extends Message<User> {
nickname: string; nickname: string;
/** /**
* @generated from field: string open_id = 6; * @generated from field: string avatar_url = 6;
*/
openId: string;
/**
* @generated from field: string avatar_url = 7;
*/ */
avatarUrl: string; avatarUrl: string;
/** /**
* @generated from field: string password = 8; * @generated from field: string password = 7;
*/ */
password: string; password: string;
/** /**
* @generated from field: memos.api.v2.RowStatus row_status = 9; * @generated from field: memos.api.v2.RowStatus row_status = 8;
*/ */
rowStatus: RowStatus; rowStatus: RowStatus;
/** /**
* @generated from field: google.protobuf.Timestamp create_time = 10; * @generated from field: google.protobuf.Timestamp create_time = 9;
*/ */
createTime?: Timestamp; createTime?: Timestamp;
/** /**
* @generated from field: google.protobuf.Timestamp update_time = 11; * @generated from field: google.protobuf.Timestamp update_time = 10;
*/ */
updateTime?: Timestamp; updateTime?: Timestamp;

View File

@ -17,12 +17,11 @@ export const User = proto3.makeMessageType(
{ no: 3, name: "role", kind: "enum", T: proto3.getEnumType(User_Role) }, { no: 3, name: "role", kind: "enum", T: proto3.getEnumType(User_Role) },
{ no: 4, name: "email", kind: "scalar", T: 9 /* ScalarType.STRING */ }, { no: 4, name: "email", kind: "scalar", T: 9 /* ScalarType.STRING */ },
{ no: 5, name: "nickname", kind: "scalar", T: 9 /* ScalarType.STRING */ }, { no: 5, name: "nickname", kind: "scalar", T: 9 /* ScalarType.STRING */ },
{ no: 6, name: "open_id", kind: "scalar", T: 9 /* ScalarType.STRING */ }, { no: 6, name: "avatar_url", kind: "scalar", T: 9 /* ScalarType.STRING */ },
{ no: 7, name: "avatar_url", kind: "scalar", T: 9 /* ScalarType.STRING */ }, { no: 7, name: "password", kind: "scalar", T: 9 /* ScalarType.STRING */ },
{ no: 8, name: "password", kind: "scalar", T: 9 /* ScalarType.STRING */ }, { no: 8, name: "row_status", kind: "enum", T: proto3.getEnumType(RowStatus) },
{ no: 9, name: "row_status", kind: "enum", T: proto3.getEnumType(RowStatus) }, { no: 9, name: "create_time", kind: "message", T: Timestamp },
{ no: 10, name: "create_time", kind: "message", T: Timestamp }, { no: 10, name: "update_time", kind: "message", T: Timestamp },
{ no: 11, name: "update_time", kind: "message", T: Timestamp },
], ],
); );