mirror of
https://github.com/usememos/memos.git
synced 2025-03-26 23:50:15 +01:00
chore: update signup api (#1067)
This commit is contained in:
parent
3590d3f8b6
commit
aad97c4c54
@ -8,5 +8,4 @@ type SignIn struct {
|
|||||||
type SignUp struct {
|
type SignUp struct {
|
||||||
Username string `json:"username"`
|
Username string `json:"username"`
|
||||||
Password string `json:"password"`
|
Password string `json:"password"`
|
||||||
Role Role `json:"role"`
|
|
||||||
}
|
}
|
||||||
|
14
api/user.go
14
api/user.go
@ -60,15 +60,12 @@ type UserCreate struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (create UserCreate) Validate() error {
|
func (create UserCreate) Validate() error {
|
||||||
if len(create.Username) < 4 {
|
if len(create.Username) < 3 {
|
||||||
return fmt.Errorf("username is too short, minimum length is 4")
|
return fmt.Errorf("username is too short, minimum length is 3")
|
||||||
}
|
}
|
||||||
if len(create.Username) > 32 {
|
if len(create.Username) > 32 {
|
||||||
return fmt.Errorf("username is too long, maximum length is 32")
|
return fmt.Errorf("username is too long, maximum length is 32")
|
||||||
}
|
}
|
||||||
if len(create.Password) < 4 {
|
|
||||||
return fmt.Errorf("password is too short, minimum length is 4")
|
|
||||||
}
|
|
||||||
if len(create.Nickname) > 64 {
|
if len(create.Nickname) > 64 {
|
||||||
return fmt.Errorf("nickname is too long, maximum length is 64")
|
return fmt.Errorf("nickname is too long, maximum length is 64")
|
||||||
}
|
}
|
||||||
@ -102,15 +99,12 @@ type UserPatch struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (patch UserPatch) Validate() error {
|
func (patch UserPatch) Validate() error {
|
||||||
if patch.Username != nil && len(*patch.Username) < 4 {
|
if patch.Username != nil && len(*patch.Username) < 3 {
|
||||||
return fmt.Errorf("username is too short, minimum length is 4")
|
return fmt.Errorf("username is too short, minimum length is 3")
|
||||||
}
|
}
|
||||||
if patch.Username != nil && len(*patch.Username) > 32 {
|
if patch.Username != nil && len(*patch.Username) > 32 {
|
||||||
return fmt.Errorf("username is too long, maximum length is 32")
|
return fmt.Errorf("username is too long, maximum length is 32")
|
||||||
}
|
}
|
||||||
if patch.Password != nil && len(*patch.Password) < 4 {
|
|
||||||
return fmt.Errorf("password is too short, minimum length is 4")
|
|
||||||
}
|
|
||||||
if patch.Nickname != nil && len(*patch.Nickname) > 64 {
|
if patch.Nickname != nil && len(*patch.Nickname) > 64 {
|
||||||
return fmt.Errorf("nickname is too long, maximum length is 64")
|
return fmt.Errorf("nickname is too long, maximum length is 64")
|
||||||
}
|
}
|
||||||
|
@ -15,4 +15,3 @@ services:
|
|||||||
|
|
||||||
volumes:
|
volumes:
|
||||||
memos_volume:
|
memos_volume:
|
||||||
|
|
||||||
|
@ -62,44 +62,45 @@ func (s *Server) registerAuthRoutes(g *echo.Group) {
|
|||||||
return echo.NewHTTPError(http.StatusBadRequest, "Malformatted signup request").SetInternal(err)
|
return echo.NewHTTPError(http.StatusBadRequest, "Malformatted signup request").SetInternal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
hostUserType := api.Host
|
|
||||||
hostUserFind := api.UserFind{
|
|
||||||
Role: &hostUserType,
|
|
||||||
}
|
|
||||||
hostUser, err := s.Store.FindUser(ctx, &hostUserFind)
|
|
||||||
if err != nil && common.ErrorCode(err) != common.NotFound {
|
|
||||||
return echo.NewHTTPError(http.StatusInternalServerError, "Failed to find host user").SetInternal(err)
|
|
||||||
}
|
|
||||||
if signup.Role == api.Host && hostUser != nil {
|
|
||||||
return echo.NewHTTPError(http.StatusUnauthorized, "Site Host existed, please contact the site host to signin account firstly").SetInternal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
systemSettingAllowSignUpName := api.SystemSettingAllowSignUpName
|
|
||||||
allowSignUpSetting, err := s.Store.FindSystemSetting(ctx, &api.SystemSettingFind{
|
|
||||||
Name: &systemSettingAllowSignUpName,
|
|
||||||
})
|
|
||||||
if err != nil && common.ErrorCode(err) != common.NotFound {
|
|
||||||
return echo.NewHTTPError(http.StatusInternalServerError, "Failed to find system setting").SetInternal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
allowSignUpSettingValue := false
|
|
||||||
if allowSignUpSetting != nil {
|
|
||||||
err = json.Unmarshal([]byte(allowSignUpSetting.Value), &allowSignUpSettingValue)
|
|
||||||
if err != nil {
|
|
||||||
return echo.NewHTTPError(http.StatusInternalServerError, "Failed to unmarshal system setting allow signup").SetInternal(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if !allowSignUpSettingValue && hostUser != nil {
|
|
||||||
return echo.NewHTTPError(http.StatusUnauthorized, "Site Host existed, please contact the site host to signin account firstly").SetInternal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
userCreate := &api.UserCreate{
|
userCreate := &api.UserCreate{
|
||||||
Username: signup.Username,
|
Username: signup.Username,
|
||||||
Role: api.Role(signup.Role),
|
// The new signup user should be normal user by default.
|
||||||
|
Role: api.NormalUser,
|
||||||
Nickname: signup.Username,
|
Nickname: signup.Username,
|
||||||
Password: signup.Password,
|
Password: signup.Password,
|
||||||
OpenID: common.GenUUID(),
|
OpenID: common.GenUUID(),
|
||||||
}
|
}
|
||||||
|
hostUserType := api.Host
|
||||||
|
existedHostUsers, err := s.Store.FindUserList(ctx, &api.UserFind{
|
||||||
|
Role: &hostUserType,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return echo.NewHTTPError(http.StatusBadRequest, "Failed to find users").SetInternal(err)
|
||||||
|
}
|
||||||
|
if len(existedHostUsers) == 0 {
|
||||||
|
// Change the default role to host if there is no host user.
|
||||||
|
userCreate.Role = api.Host
|
||||||
|
} else {
|
||||||
|
systemSettingAllowSignUpName := api.SystemSettingAllowSignUpName
|
||||||
|
allowSignUpSetting, err := s.Store.FindSystemSetting(ctx, &api.SystemSettingFind{
|
||||||
|
Name: &systemSettingAllowSignUpName,
|
||||||
|
})
|
||||||
|
if err != nil && common.ErrorCode(err) != common.NotFound {
|
||||||
|
return echo.NewHTTPError(http.StatusInternalServerError, "Failed to find system setting").SetInternal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
allowSignUpSettingValue := false
|
||||||
|
if allowSignUpSetting != nil {
|
||||||
|
err = json.Unmarshal([]byte(allowSignUpSetting.Value), &allowSignUpSettingValue)
|
||||||
|
if err != nil {
|
||||||
|
return echo.NewHTTPError(http.StatusInternalServerError, "Failed to unmarshal system setting allow signup").SetInternal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !allowSignUpSettingValue {
|
||||||
|
return echo.NewHTTPError(http.StatusUnauthorized, "signup is disabled").SetInternal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if err := userCreate.Validate(); err != nil {
|
if err := userCreate.Validate(); err != nil {
|
||||||
return echo.NewHTTPError(http.StatusBadRequest, "Invalid user create format").SetInternal(err)
|
return echo.NewHTTPError(http.StatusBadRequest, "Invalid user create format").SetInternal(err)
|
||||||
}
|
}
|
||||||
@ -110,7 +111,6 @@ func (s *Server) registerAuthRoutes(g *echo.Group) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
userCreate.PasswordHash = string(passwordHash)
|
userCreate.PasswordHash = string(passwordHash)
|
||||||
|
|
||||||
user, err := s.Store.CreateUser(ctx, userCreate)
|
user, err := s.Store.CreateUser(ctx, userCreate)
|
||||||
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)
|
||||||
|
@ -87,6 +87,34 @@ func (s *Server) registerUserRoutes(g *echo.Group) {
|
|||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
|
|
||||||
|
g.POST("/user/setting", func(c echo.Context) error {
|
||||||
|
ctx := c.Request().Context()
|
||||||
|
userID, ok := c.Get(getUserIDContextKey()).(int)
|
||||||
|
if !ok {
|
||||||
|
return echo.NewHTTPError(http.StatusUnauthorized, "Missing auth session")
|
||||||
|
}
|
||||||
|
|
||||||
|
userSettingUpsert := &api.UserSettingUpsert{}
|
||||||
|
if err := json.NewDecoder(c.Request().Body).Decode(userSettingUpsert); err != nil {
|
||||||
|
return echo.NewHTTPError(http.StatusBadRequest, "Malformatted post user setting upsert request").SetInternal(err)
|
||||||
|
}
|
||||||
|
if err := userSettingUpsert.Validate(); err != nil {
|
||||||
|
return echo.NewHTTPError(http.StatusBadRequest, "Invalid user setting format").SetInternal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
userSettingUpsert.UserID = userID
|
||||||
|
userSetting, err := s.Store.UpsertUserSetting(ctx, userSettingUpsert)
|
||||||
|
if err != nil {
|
||||||
|
return echo.NewHTTPError(http.StatusInternalServerError, "Failed to upsert user setting").SetInternal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
c.Response().Header().Set(echo.HeaderContentType, echo.MIMEApplicationJSONCharsetUTF8)
|
||||||
|
if err := json.NewEncoder(c.Response().Writer).Encode(composeResponse(userSetting)); err != nil {
|
||||||
|
return echo.NewHTTPError(http.StatusInternalServerError, "Failed to encode user setting response").SetInternal(err)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
|
||||||
// GET /api/user/me is used to check if the user is logged in.
|
// GET /api/user/me is used to check if the user is logged in.
|
||||||
g.GET("/user/me", func(c echo.Context) error {
|
g.GET("/user/me", func(c echo.Context) error {
|
||||||
ctx := c.Request().Context()
|
ctx := c.Request().Context()
|
||||||
@ -118,34 +146,6 @@ func (s *Server) registerUserRoutes(g *echo.Group) {
|
|||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
|
|
||||||
g.POST("/user/setting", func(c echo.Context) error {
|
|
||||||
ctx := c.Request().Context()
|
|
||||||
userID, ok := c.Get(getUserIDContextKey()).(int)
|
|
||||||
if !ok {
|
|
||||||
return echo.NewHTTPError(http.StatusUnauthorized, "Missing auth session")
|
|
||||||
}
|
|
||||||
|
|
||||||
userSettingUpsert := &api.UserSettingUpsert{}
|
|
||||||
if err := json.NewDecoder(c.Request().Body).Decode(userSettingUpsert); err != nil {
|
|
||||||
return echo.NewHTTPError(http.StatusBadRequest, "Malformatted post user setting upsert request").SetInternal(err)
|
|
||||||
}
|
|
||||||
if err := userSettingUpsert.Validate(); err != nil {
|
|
||||||
return echo.NewHTTPError(http.StatusBadRequest, "Invalid user setting format").SetInternal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
userSettingUpsert.UserID = userID
|
|
||||||
userSetting, err := s.Store.UpsertUserSetting(ctx, userSettingUpsert)
|
|
||||||
if err != nil {
|
|
||||||
return echo.NewHTTPError(http.StatusInternalServerError, "Failed to upsert user setting").SetInternal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
c.Response().Header().Set(echo.HeaderContentType, echo.MIMEApplicationJSONCharsetUTF8)
|
|
||||||
if err := json.NewEncoder(c.Response().Writer).Encode(composeResponse(userSetting)); err != nil {
|
|
||||||
return echo.NewHTTPError(http.StatusInternalServerError, "Failed to encode user setting response").SetInternal(err)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
|
|
||||||
g.GET("/user/:id", func(c echo.Context) error {
|
g.GET("/user/:id", func(c echo.Context) error {
|
||||||
ctx := c.Request().Context()
|
ctx := c.Request().Context()
|
||||||
id, err := strconv.Atoi(c.Param("id"))
|
id, err := strconv.Atoi(c.Param("id"))
|
||||||
|
@ -25,11 +25,10 @@ export function signin(username: string, password: string) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export function signup(username: string, password: string, role: UserRole) {
|
export function signup(username: string, password: string) {
|
||||||
return axios.post<ResponseObject<User>>("/api/auth/signup", {
|
return axios.post<ResponseObject<User>>("/api/auth/signup", {
|
||||||
username,
|
username,
|
||||||
password,
|
password,
|
||||||
role,
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -84,7 +84,7 @@ const Auth = () => {
|
|||||||
actionBtnLoadingState.setFinish();
|
actionBtnLoadingState.setFinish();
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleSignUpBtnsClick = async (role: UserRole) => {
|
const handleSignUpBtnsClick = async () => {
|
||||||
if (actionBtnLoadingState.isLoading) {
|
if (actionBtnLoadingState.isLoading) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -103,7 +103,7 @@ const Auth = () => {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
actionBtnLoadingState.setLoading();
|
actionBtnLoadingState.setLoading();
|
||||||
await api.signup(username, password, role);
|
await api.signup(username, password);
|
||||||
const user = await userStore.doSignIn();
|
const user = await userStore.doSignIn();
|
||||||
if (user) {
|
if (user) {
|
||||||
navigate("/");
|
navigate("/");
|
||||||
@ -157,10 +157,7 @@ const Auth = () => {
|
|||||||
{actionBtnLoadingState.isLoading && <Icon.Loader className="w-4 h-auto mr-2 animate-spin dark:text-gray-300" />}
|
{actionBtnLoadingState.isLoading && <Icon.Loader className="w-4 h-auto mr-2 animate-spin dark:text-gray-300" />}
|
||||||
{systemStatus?.allowSignUp && (
|
{systemStatus?.allowSignUp && (
|
||||||
<>
|
<>
|
||||||
<button
|
<button className={`btn-text ${actionBtnLoadingState.isLoading ? "requesting" : ""}`} onClick={handleSignUpBtnsClick}>
|
||||||
className={`btn-text ${actionBtnLoadingState.isLoading ? "requesting" : ""}`}
|
|
||||||
onClick={() => handleSignUpBtnsClick("USER")}
|
|
||||||
>
|
|
||||||
{t("common.sign-up")}
|
{t("common.sign-up")}
|
||||||
</button>
|
</button>
|
||||||
<span className="mr-2 font-mono text-gray-200">/</span>
|
<span className="mr-2 font-mono text-gray-200">/</span>
|
||||||
@ -172,10 +169,7 @@ const Auth = () => {
|
|||||||
</>
|
</>
|
||||||
) : (
|
) : (
|
||||||
<>
|
<>
|
||||||
<button
|
<button className={`btn-primary ${actionBtnLoadingState.isLoading ? "requesting" : ""}`} onClick={handleSignUpBtnsClick}>
|
||||||
className={`btn-primary ${actionBtnLoadingState.isLoading ? "requesting" : ""}`}
|
|
||||||
onClick={() => handleSignUpBtnsClick("HOST")}
|
|
||||||
>
|
|
||||||
{t("auth.signup-as-host")}
|
{t("auth.signup-as-host")}
|
||||||
</button>
|
</button>
|
||||||
</>
|
</>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user