diff --git a/api/auth.go b/api/auth.go index 5ed4ebf1..b0a98bdd 100644 --- a/api/auth.go +++ b/api/auth.go @@ -8,5 +8,4 @@ type SignIn struct { type SignUp struct { Username string `json:"username"` Password string `json:"password"` - Role Role `json:"role"` } diff --git a/api/api.go b/api/common.go similarity index 100% rename from api/api.go rename to api/common.go diff --git a/api/user.go b/api/user.go index ef7c1e4b..4032eb26 100644 --- a/api/user.go +++ b/api/user.go @@ -60,15 +60,12 @@ type UserCreate struct { } func (create UserCreate) Validate() error { - if len(create.Username) < 4 { - return fmt.Errorf("username is too short, minimum length is 4") + if len(create.Username) < 3 { + return fmt.Errorf("username is too short, minimum length is 3") } if len(create.Username) > 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 { return fmt.Errorf("nickname is too long, maximum length is 64") } @@ -102,15 +99,12 @@ type UserPatch struct { } func (patch UserPatch) Validate() error { - if patch.Username != nil && len(*patch.Username) < 4 { - return fmt.Errorf("username is too short, minimum length is 4") + if patch.Username != nil && len(*patch.Username) < 3 { + return fmt.Errorf("username is too short, minimum length is 3") } if patch.Username != nil && len(*patch.Username) > 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 { return fmt.Errorf("nickname is too long, maximum length is 64") } diff --git a/docker-compose.uffizzi.yml b/docker-compose.uffizzi.yml index 14be8bd2..42b0bb8f 100644 --- a/docker-compose.uffizzi.yml +++ b/docker-compose.uffizzi.yml @@ -15,4 +15,3 @@ services: volumes: memos_volume: - diff --git a/server/auth.go b/server/auth.go index ba67872e..5af8d617 100644 --- a/server/auth.go +++ b/server/auth.go @@ -62,44 +62,45 @@ func (s *Server) registerAuthRoutes(g *echo.Group) { 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{ Username: signup.Username, - Role: api.Role(signup.Role), + // The new signup user should be normal user by default. + Role: api.NormalUser, Nickname: signup.Username, Password: signup.Password, 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 { 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) - user, err := s.Store.CreateUser(ctx, userCreate) if err != nil { return echo.NewHTTPError(http.StatusInternalServerError, "Failed to create user").SetInternal(err) diff --git a/server/user.go b/server/user.go index 8a5fbb65..410ff736 100644 --- a/server/user.go +++ b/server/user.go @@ -87,6 +87,34 @@ func (s *Server) registerUserRoutes(g *echo.Group) { 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. g.GET("/user/me", func(c echo.Context) error { ctx := c.Request().Context() @@ -118,34 +146,6 @@ func (s *Server) registerUserRoutes(g *echo.Group) { 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 { ctx := c.Request().Context() id, err := strconv.Atoi(c.Param("id")) diff --git a/web/src/helpers/api.ts b/web/src/helpers/api.ts index 6c6a8eb8..ff16371a 100644 --- a/web/src/helpers/api.ts +++ b/web/src/helpers/api.ts @@ -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>("/api/auth/signup", { username, password, - role, }); } diff --git a/web/src/pages/Auth.tsx b/web/src/pages/Auth.tsx index a270bb4e..d8469d2e 100644 --- a/web/src/pages/Auth.tsx +++ b/web/src/pages/Auth.tsx @@ -84,7 +84,7 @@ const Auth = () => { actionBtnLoadingState.setFinish(); }; - const handleSignUpBtnsClick = async (role: UserRole) => { + const handleSignUpBtnsClick = async () => { if (actionBtnLoadingState.isLoading) { return; } @@ -103,7 +103,7 @@ const Auth = () => { try { actionBtnLoadingState.setLoading(); - await api.signup(username, password, role); + await api.signup(username, password); const user = await userStore.doSignIn(); if (user) { navigate("/"); @@ -157,10 +157,7 @@ const Auth = () => { {actionBtnLoadingState.isLoading && } {systemStatus?.allowSignUp && ( <> - / @@ -172,10 +169,7 @@ const Auth = () => { ) : ( <> -