diff --git a/api/v2/acl_config.go b/api/v2/acl_config.go index 72f7240a..7bb54422 100644 --- a/api/v2/acl_config.go +++ b/api/v2/acl_config.go @@ -5,6 +5,10 @@ import "strings" var authenticationAllowlistMethods = map[string]bool{ "/memos.api.v2.WorkspaceService/GetWorkspaceProfile": true, "/memos.api.v2.AuthService/GetAuthStatus": true, + "/memos.api.v2.AuthService/SignIn": true, + "/memos.api.v2.AuthService/SignInWithSSO": true, + "/memos.api.v2.AuthService/SignOut": true, + "/memos.api.v2.AuthService/SignUp": true, "/memos.api.v2.UserService/GetUser": true, "/memos.api.v2.MemoService/ListMemos": true, "/memos.api.v2.MemoService/GetMemo": true, diff --git a/api/v2/apidocs.swagger.yaml b/api/v2/apidocs.swagger.yaml index a1630073..1cd0b128 100644 --- a/api/v2/apidocs.swagger.yaml +++ b/api/v2/apidocs.swagger.yaml @@ -40,6 +40,10 @@ paths: in: query required: false type: string + - name: neverExpire + in: query + required: false + type: boolean tags: - AuthService /api/v2/auth/signin/sso: diff --git a/api/v2/auth_service.go b/api/v2/auth_service.go index 98b96e97..35cd01c9 100644 --- a/api/v2/auth_service.go +++ b/api/v2/auth_service.go @@ -3,15 +3,25 @@ package v2 import ( "context" "fmt" + "regexp" + "time" "github.com/pkg/errors" + "golang.org/x/crypto/bcrypt" "google.golang.org/grpc" "google.golang.org/grpc/codes" "google.golang.org/grpc/metadata" "google.golang.org/grpc/status" + "google.golang.org/protobuf/proto" "github.com/usememos/memos/api/auth" + "github.com/usememos/memos/internal/util" + "github.com/usememos/memos/plugin/idp" + "github.com/usememos/memos/plugin/idp/oauth2" apiv2pb "github.com/usememos/memos/proto/gen/api/v2" + storepb "github.com/usememos/memos/proto/gen/store" + "github.com/usememos/memos/server/service/metric" + "github.com/usememos/memos/store" ) func (s *APIV2Service) GetAuthStatus(ctx context.Context, _ *apiv2pb.GetAuthStatusRequest) (*apiv2pb.GetAuthStatusResponse, error) { @@ -31,6 +41,190 @@ func (s *APIV2Service) GetAuthStatus(ctx context.Context, _ *apiv2pb.GetAuthStat }, nil } +func (s *APIV2Service) SignIn(ctx context.Context, request *apiv2pb.SignInRequest) (*apiv2pb.SignInResponse, error) { + user, err := s.Store.GetUser(ctx, &store.FindUser{ + Username: &request.Username, + }) + if err != nil { + return nil, status.Errorf(codes.Internal, fmt.Sprintf("failed to find user by username %s", request.Username)) + } + if user == nil { + return nil, status.Errorf(codes.InvalidArgument, fmt.Sprintf("user not found with username %s", request.Username)) + } else if user.RowStatus == store.Archived { + return nil, status.Errorf(codes.PermissionDenied, fmt.Sprintf("user has been archived with username %s", request.Username)) + } + + // Compare the stored hashed password, with the hashed version of the password that was received. + if err := bcrypt.CompareHashAndPassword([]byte(user.PasswordHash), []byte(request.Password)); err != nil { + return nil, status.Errorf(codes.InvalidArgument, "unmatched email and password") + } + + expireTime := time.Now().Add(auth.AccessTokenDuration) + if request.NeverExpire { + // Zero time means never expire. + expireTime = time.Time{} + } + if err := s.doSignIn(ctx, user, expireTime); err != nil { + return nil, status.Errorf(codes.Internal, fmt.Sprintf("failed to sign in, err: %s", err)) + } + return &apiv2pb.SignInResponse{ + User: convertUserFromStore(user), + }, nil +} + +func (s *APIV2Service) SignInWithSSO(ctx context.Context, request *apiv2pb.SignInWithSSORequest) (*apiv2pb.SignInWithSSOResponse, error) { + identityProvider, err := s.Store.GetIdentityProvider(ctx, &store.FindIdentityProvider{ + ID: &request.IdpId, + }) + if err != nil { + return nil, status.Errorf(codes.Internal, fmt.Sprintf("failed to get identity provider, err: %s", err)) + } + if identityProvider == nil { + return nil, status.Errorf(codes.InvalidArgument, fmt.Sprintf("identity provider not found with id %d", request.IdpId)) + } + + var userInfo *idp.IdentityProviderUserInfo + if identityProvider.Type == store.IdentityProviderOAuth2Type { + oauth2IdentityProvider, err := oauth2.NewIdentityProvider(identityProvider.Config.OAuth2Config) + if err != nil { + return nil, status.Errorf(codes.Internal, fmt.Sprintf("failed to create oauth2 identity provider, err: %s", err)) + } + token, err := oauth2IdentityProvider.ExchangeToken(ctx, request.RedirectUri, request.Code) + if err != nil { + return nil, status.Errorf(codes.Internal, fmt.Sprintf("failed to exchange token, err: %s", err)) + } + userInfo, err = oauth2IdentityProvider.UserInfo(token) + if err != nil { + return nil, status.Errorf(codes.Internal, fmt.Sprintf("failed to get user info, err: %s", err)) + } + } + + identifierFilter := identityProvider.IdentifierFilter + if identifierFilter != "" { + identifierFilterRegex, err := regexp.Compile(identifierFilter) + if err != nil { + return nil, status.Errorf(codes.Internal, fmt.Sprintf("failed to compile identifier filter regex, err: %s", err)) + } + if !identifierFilterRegex.MatchString(userInfo.Identifier) { + return nil, status.Errorf(codes.PermissionDenied, fmt.Sprintf("identifier %s is not allowed", userInfo.Identifier)) + } + } + + user, err := s.Store.GetUser(ctx, &store.FindUser{ + Username: &userInfo.Identifier, + }) + if err != nil { + return nil, status.Errorf(codes.Internal, fmt.Sprintf("failed to find user by username %s", userInfo.Identifier)) + } + if user == nil { + userCreate := &store.User{ + Username: userInfo.Identifier, + // The new signup user should be normal user by default. + Role: store.RoleUser, + Nickname: userInfo.DisplayName, + Email: userInfo.Email, + } + password, err := util.RandomString(20) + if err != nil { + return nil, status.Errorf(codes.Internal, fmt.Sprintf("failed to generate random password, err: %s", err)) + } + passwordHash, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost) + if err != nil { + return nil, status.Errorf(codes.Internal, fmt.Sprintf("failed to generate password hash, err: %s", err)) + } + userCreate.PasswordHash = string(passwordHash) + user, err = s.Store.CreateUser(ctx, userCreate) + if err != nil { + return nil, status.Errorf(codes.Internal, fmt.Sprintf("failed to create user, err: %s", err)) + } + } + if user.RowStatus == store.Archived { + return nil, status.Errorf(codes.PermissionDenied, fmt.Sprintf("user has been archived with username %s", userInfo.Identifier)) + } + + if err := s.doSignIn(ctx, user, time.Now().Add(auth.AccessTokenDuration)); err != nil { + return nil, status.Errorf(codes.Internal, fmt.Sprintf("failed to sign in, err: %s", err)) + } + return &apiv2pb.SignInWithSSOResponse{ + User: convertUserFromStore(user), + }, nil +} + +func (s *APIV2Service) doSignIn(ctx context.Context, user *store.User, expireTime time.Time) error { + accessToken, err := auth.GenerateAccessToken(user.Email, user.ID, expireTime, []byte(s.Secret)) + if err != nil { + return status.Errorf(codes.Internal, fmt.Sprintf("failed to generate tokens, err: %s", err)) + } + if err := s.UpsertAccessTokenToStore(ctx, user, accessToken, "user login"); err != nil { + return status.Errorf(codes.Internal, fmt.Sprintf("failed to upsert access token to store, err: %s", err)) + } + + cookieExpires := time.Now().Add(auth.CookieExpDuration) + if expireTime.IsZero() { + // Set cookie expires to 100 years. + cookieExpires = time.Now().AddDate(100, 0, 0) + } + if err := grpc.SetHeader(ctx, metadata.New(map[string]string{ + "Set-Cookie": fmt.Sprintf("%s=%s; Path=/; Expires=%s; HttpOnly; SameSite=Strict", auth.AccessTokenCookieName, accessToken, cookieExpires.Format(time.RFC1123)), + })); err != nil { + return status.Errorf(codes.Internal, "failed to set grpc header, error: %v", err) + } + + metric.Enqueue("user sign in") + return nil +} + +func (s *APIV2Service) SignUp(ctx context.Context, request *apiv2pb.SignUpRequest) (*apiv2pb.SignUpResponse, error) { + workspaceGeneralSetting, err := s.GetWorkspaceGeneralSetting(ctx) + if err != nil { + return nil, status.Errorf(codes.Internal, fmt.Sprintf("failed to get workspace setting, err: %s", err)) + } + if workspaceGeneralSetting.DisallowSignup { + return nil, status.Errorf(codes.PermissionDenied, "sign up is not allowed") + } + + passwordHash, err := bcrypt.GenerateFromPassword([]byte(request.Password), bcrypt.DefaultCost) + if err != nil { + return nil, status.Errorf(codes.Internal, fmt.Sprintf("failed to generate password hash, err: %s", err)) + } + + create := &store.User{ + Username: request.Username, + Nickname: request.Username, + PasswordHash: string(passwordHash), + } + existingUsers, err := s.Store.ListUsers(ctx, &store.FindUser{}) + if err != nil { + return nil, status.Errorf(codes.Internal, fmt.Sprintf("failed to list users, err: %s", err)) + } + // The first user to sign up is an admin by default. + if len(existingUsers) == 0 { + create.Role = store.RoleAdmin + } else { + create.Role = store.RoleUser + } + + user, err := s.Store.CreateUser(ctx, create) + if err != nil { + return nil, status.Errorf(codes.Internal, fmt.Sprintf("failed to create user, err: %s", err)) + } + + if err := s.doSignIn(ctx, user, time.Now().Add(auth.AccessTokenDuration)); err != nil { + return nil, status.Errorf(codes.Internal, fmt.Sprintf("failed to sign in, err: %s", err)) + } + metric.Enqueue("user sign up") + return &apiv2pb.SignUpResponse{ + User: convertUserFromStore(user), + }, nil +} + +func (*APIV2Service) SignOut(ctx context.Context, _ *apiv2pb.SignOutRequest) (*apiv2pb.SignOutResponse, error) { + if err := clearAccessTokenCookie(ctx); err != nil { + return nil, status.Errorf(codes.Internal, "failed to set grpc header, error: %v", err) + } + return &apiv2pb.SignOutResponse{}, nil +} + func clearAccessTokenCookie(ctx context.Context) error { if err := grpc.SetHeader(ctx, metadata.New(map[string]string{ "Set-Cookie": fmt.Sprintf("%s=; Path=/; Expires=Thu, 01 Jan 1970 00:00:00 GMT; HttpOnly; SameSite=Strict", auth.AccessTokenCookieName), @@ -39,3 +233,19 @@ func clearAccessTokenCookie(ctx context.Context) error { } return nil } + +func (s *APIV2Service) GetWorkspaceGeneralSetting(ctx context.Context) (*storepb.WorkspaceGeneralSetting, error) { + workspaceSetting, err := s.Store.GetWorkspaceSetting(ctx, &store.FindWorkspaceSetting{ + Name: storepb.WorkspaceSettingKey_WORKSPACE_SETTING_GENERAL.String(), + }) + if err != nil { + return nil, errors.Wrap(err, "failed to get workspace setting") + } + workspaceGeneralSetting := &storepb.WorkspaceGeneralSetting{} + if workspaceSetting != nil { + if err := proto.Unmarshal([]byte(workspaceSetting.Value), workspaceGeneralSetting); err != nil { + return nil, errors.Wrap(err, "failed to unmarshal workspace setting") + } + } + return workspaceGeneralSetting, nil +} diff --git a/proto/api/v2/auth_service.proto b/proto/api/v2/auth_service.proto index e3f6443a..7dbc8981 100644 --- a/proto/api/v2/auth_service.proto +++ b/proto/api/v2/auth_service.proto @@ -39,6 +39,7 @@ message GetAuthStatusResponse { message SignInRequest { string username = 1; string password = 2; + bool never_expire = 3; } message SignInResponse { diff --git a/proto/gen/api/v2/README.md b/proto/gen/api/v2/README.md index 028790bc..05f1bfc9 100644 --- a/proto/gen/api/v2/README.md +++ b/proto/gen/api/v2/README.md @@ -823,6 +823,7 @@ Used internally for obfuscating the page token. | ----- | ---- | ----- | ----------- | | username | [string](#string) | | | | password | [string](#string) | | | +| never_expire | [bool](#bool) | | | diff --git a/proto/gen/api/v2/auth_service.pb.go b/proto/gen/api/v2/auth_service.pb.go index c2e054cd..cc274573 100644 --- a/proto/gen/api/v2/auth_service.pb.go +++ b/proto/gen/api/v2/auth_service.pb.go @@ -111,8 +111,9 @@ type SignInRequest struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Username string `protobuf:"bytes,1,opt,name=username,proto3" json:"username,omitempty"` - Password string `protobuf:"bytes,2,opt,name=password,proto3" json:"password,omitempty"` + Username string `protobuf:"bytes,1,opt,name=username,proto3" json:"username,omitempty"` + Password string `protobuf:"bytes,2,opt,name=password,proto3" json:"password,omitempty"` + NeverExpire bool `protobuf:"varint,3,opt,name=never_expire,json=neverExpire,proto3" json:"never_expire,omitempty"` } func (x *SignInRequest) Reset() { @@ -161,6 +162,13 @@ func (x *SignInRequest) GetPassword() string { return "" } +func (x *SignInRequest) GetNeverExpire() bool { + if x != nil { + return x.NeverExpire + } + return false +} + type SignInResponse struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -510,82 +518,84 @@ var file_api_v2_auth_service_proto_rawDesc = []byte{ 0x74, 0x41, 0x75, 0x74, 0x68, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x26, 0x0a, 0x04, 0x75, 0x73, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 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, 0x47, 0x0a, 0x0d, 0x53, + 0x2e, 0x55, 0x73, 0x65, 0x72, 0x52, 0x04, 0x75, 0x73, 0x65, 0x72, 0x22, 0x6a, 0x0a, 0x0d, 0x53, 0x69, 0x67, 0x6e, 0x49, 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, 0x1a, 0x0a, 0x08, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x61, 0x73, 0x73, - 0x77, 0x6f, 0x72, 0x64, 0x22, 0x38, 0x0a, 0x0e, 0x53, 0x69, 0x67, 0x6e, 0x49, 0x6e, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x26, 0x0a, 0x04, 0x75, 0x73, 0x65, 0x72, 0x18, 0x01, - 0x20, 0x01, 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, 0x64, - 0x0a, 0x14, 0x53, 0x69, 0x67, 0x6e, 0x49, 0x6e, 0x57, 0x69, 0x74, 0x68, 0x53, 0x53, 0x4f, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x15, 0x0a, 0x06, 0x69, 0x64, 0x70, 0x5f, 0x69, 0x64, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x69, 0x64, 0x70, 0x49, 0x64, 0x12, 0x12, 0x0a, - 0x04, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x63, 0x6f, 0x64, - 0x65, 0x12, 0x21, 0x0a, 0x0c, 0x72, 0x65, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x5f, 0x75, 0x72, - 0x69, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x72, 0x65, 0x64, 0x69, 0x72, 0x65, 0x63, - 0x74, 0x55, 0x72, 0x69, 0x22, 0x3f, 0x0a, 0x15, 0x53, 0x69, 0x67, 0x6e, 0x49, 0x6e, 0x57, 0x69, - 0x74, 0x68, 0x53, 0x53, 0x4f, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x26, 0x0a, - 0x04, 0x75, 0x73, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 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, 0x47, 0x0a, 0x0d, 0x53, 0x69, 0x67, 0x6e, 0x55, 0x70, 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, 0x1a, 0x0a, 0x08, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x22, 0x38, - 0x0a, 0x0e, 0x53, 0x69, 0x67, 0x6e, 0x55, 0x70, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x77, 0x6f, 0x72, 0x64, 0x12, 0x21, 0x0a, 0x0c, 0x6e, 0x65, 0x76, 0x65, 0x72, 0x5f, 0x65, 0x78, + 0x70, 0x69, 0x72, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, 0x6e, 0x65, 0x76, 0x65, + 0x72, 0x45, 0x78, 0x70, 0x69, 0x72, 0x65, 0x22, 0x38, 0x0a, 0x0e, 0x53, 0x69, 0x67, 0x6e, 0x49, + 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x26, 0x0a, 0x04, 0x75, 0x73, 0x65, + 0x72, 0x18, 0x01, 0x20, 0x01, 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, 0x64, 0x0a, 0x14, 0x53, 0x69, 0x67, 0x6e, 0x49, 0x6e, 0x57, 0x69, 0x74, 0x68, 0x53, + 0x53, 0x4f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x15, 0x0a, 0x06, 0x69, 0x64, 0x70, + 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x69, 0x64, 0x70, 0x49, 0x64, + 0x12, 0x12, 0x0a, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, + 0x63, 0x6f, 0x64, 0x65, 0x12, 0x21, 0x0a, 0x0c, 0x72, 0x65, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, + 0x5f, 0x75, 0x72, 0x69, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x72, 0x65, 0x64, 0x69, + 0x72, 0x65, 0x63, 0x74, 0x55, 0x72, 0x69, 0x22, 0x3f, 0x0a, 0x15, 0x53, 0x69, 0x67, 0x6e, 0x49, + 0x6e, 0x57, 0x69, 0x74, 0x68, 0x53, 0x53, 0x4f, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x26, 0x0a, 0x04, 0x75, 0x73, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 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, 0x10, 0x0a, 0x0e, 0x53, 0x69, 0x67, 0x6e, - 0x4f, 0x75, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x11, 0x0a, 0x0f, 0x53, 0x69, - 0x67, 0x6e, 0x4f, 0x75, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x32, 0xa9, 0x04, - 0x0a, 0x0b, 0x41, 0x75, 0x74, 0x68, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x75, 0x0a, - 0x0d, 0x47, 0x65, 0x74, 0x41, 0x75, 0x74, 0x68, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x22, - 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x32, 0x2e, 0x47, 0x65, - 0x74, 0x41, 0x75, 0x74, 0x68, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x23, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, - 0x32, 0x2e, 0x47, 0x65, 0x74, 0x41, 0x75, 0x74, 0x68, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1b, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x15, 0x22, - 0x13, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x32, 0x2f, 0x61, 0x75, 0x74, 0x68, 0x2f, 0x73, 0x74, - 0x61, 0x74, 0x75, 0x73, 0x12, 0x60, 0x0a, 0x06, 0x53, 0x69, 0x67, 0x6e, 0x49, 0x6e, 0x12, 0x1b, + 0x65, 0x72, 0x52, 0x04, 0x75, 0x73, 0x65, 0x72, 0x22, 0x47, 0x0a, 0x0d, 0x53, 0x69, 0x67, 0x6e, + 0x55, 0x70, 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, 0x1a, 0x0a, 0x08, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, + 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, + 0x64, 0x22, 0x38, 0x0a, 0x0e, 0x53, 0x69, 0x67, 0x6e, 0x55, 0x70, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x12, 0x26, 0x0a, 0x04, 0x75, 0x73, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 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, 0x10, 0x0a, 0x0e, 0x53, + 0x69, 0x67, 0x6e, 0x4f, 0x75, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x11, 0x0a, + 0x0f, 0x53, 0x69, 0x67, 0x6e, 0x4f, 0x75, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x32, 0xa9, 0x04, 0x0a, 0x0b, 0x41, 0x75, 0x74, 0x68, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, + 0x12, 0x75, 0x0a, 0x0d, 0x47, 0x65, 0x74, 0x41, 0x75, 0x74, 0x68, 0x53, 0x74, 0x61, 0x74, 0x75, + 0x73, 0x12, 0x22, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x32, + 0x2e, 0x47, 0x65, 0x74, 0x41, 0x75, 0x74, 0x68, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x23, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, + 0x69, 0x2e, 0x76, 0x32, 0x2e, 0x47, 0x65, 0x74, 0x41, 0x75, 0x74, 0x68, 0x53, 0x74, 0x61, 0x74, + 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1b, 0x82, 0xd3, 0xe4, 0x93, + 0x02, 0x15, 0x22, 0x13, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x32, 0x2f, 0x61, 0x75, 0x74, 0x68, + 0x2f, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x60, 0x0a, 0x06, 0x53, 0x69, 0x67, 0x6e, 0x49, + 0x6e, 0x12, 0x1b, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x32, + 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x49, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x32, 0x2e, 0x53, 0x69, - 0x67, 0x6e, 0x49, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x6d, 0x65, - 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x32, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x49, - 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1b, 0x82, 0xd3, 0xe4, 0x93, 0x02, - 0x15, 0x22, 0x13, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x32, 0x2f, 0x61, 0x75, 0x74, 0x68, 0x2f, - 0x73, 0x69, 0x67, 0x6e, 0x69, 0x6e, 0x12, 0x79, 0x0a, 0x0d, 0x53, 0x69, 0x67, 0x6e, 0x49, 0x6e, - 0x57, 0x69, 0x74, 0x68, 0x53, 0x53, 0x4f, 0x12, 0x22, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, - 0x61, 0x70, 0x69, 0x2e, 0x76, 0x32, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x49, 0x6e, 0x57, 0x69, 0x74, - 0x68, 0x53, 0x53, 0x4f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x23, 0x2e, 0x6d, 0x65, - 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x32, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x49, - 0x6e, 0x57, 0x69, 0x74, 0x68, 0x53, 0x53, 0x4f, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x22, 0x1f, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x19, 0x22, 0x17, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, - 0x32, 0x2f, 0x61, 0x75, 0x74, 0x68, 0x2f, 0x73, 0x69, 0x67, 0x6e, 0x69, 0x6e, 0x2f, 0x73, 0x73, - 0x6f, 0x12, 0x60, 0x0a, 0x06, 0x53, 0x69, 0x67, 0x6e, 0x55, 0x70, 0x12, 0x1b, 0x2e, 0x6d, 0x65, + 0x67, 0x6e, 0x49, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1b, 0x82, 0xd3, + 0xe4, 0x93, 0x02, 0x15, 0x22, 0x13, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x32, 0x2f, 0x61, 0x75, + 0x74, 0x68, 0x2f, 0x73, 0x69, 0x67, 0x6e, 0x69, 0x6e, 0x12, 0x79, 0x0a, 0x0d, 0x53, 0x69, 0x67, + 0x6e, 0x49, 0x6e, 0x57, 0x69, 0x74, 0x68, 0x53, 0x53, 0x4f, 0x12, 0x22, 0x2e, 0x6d, 0x65, 0x6d, + 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x32, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x49, 0x6e, + 0x57, 0x69, 0x74, 0x68, 0x53, 0x53, 0x4f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x23, + 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x32, 0x2e, 0x53, 0x69, + 0x67, 0x6e, 0x49, 0x6e, 0x57, 0x69, 0x74, 0x68, 0x53, 0x53, 0x4f, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x22, 0x1f, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x19, 0x22, 0x17, 0x2f, 0x61, 0x70, + 0x69, 0x2f, 0x76, 0x32, 0x2f, 0x61, 0x75, 0x74, 0x68, 0x2f, 0x73, 0x69, 0x67, 0x6e, 0x69, 0x6e, + 0x2f, 0x73, 0x73, 0x6f, 0x12, 0x60, 0x0a, 0x06, 0x53, 0x69, 0x67, 0x6e, 0x55, 0x70, 0x12, 0x1b, + 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x32, 0x2e, 0x53, 0x69, + 0x67, 0x6e, 0x55, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x32, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x55, - 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, - 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x32, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x55, 0x70, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1b, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x15, 0x22, 0x13, - 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x32, 0x2f, 0x61, 0x75, 0x74, 0x68, 0x2f, 0x73, 0x69, 0x67, - 0x6e, 0x75, 0x70, 0x12, 0x64, 0x0a, 0x07, 0x53, 0x69, 0x67, 0x6e, 0x4f, 0x75, 0x74, 0x12, 0x1c, - 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x32, 0x2e, 0x53, 0x69, - 0x67, 0x6e, 0x4f, 0x75, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x6d, - 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x32, 0x2e, 0x53, 0x69, 0x67, 0x6e, - 0x4f, 0x75, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1c, 0x82, 0xd3, 0xe4, - 0x93, 0x02, 0x16, 0x22, 0x14, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x32, 0x2f, 0x61, 0x75, 0x74, - 0x68, 0x2f, 0x73, 0x69, 0x67, 0x6e, 0x6f, 0x75, 0x74, 0x42, 0xa8, 0x01, 0x0a, 0x10, 0x63, 0x6f, - 0x6d, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x32, 0x42, 0x10, - 0x41, 0x75, 0x74, 0x68, 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, + 0x70, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1b, 0x82, 0xd3, 0xe4, 0x93, 0x02, + 0x15, 0x22, 0x13, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x32, 0x2f, 0x61, 0x75, 0x74, 0x68, 0x2f, + 0x73, 0x69, 0x67, 0x6e, 0x75, 0x70, 0x12, 0x64, 0x0a, 0x07, 0x53, 0x69, 0x67, 0x6e, 0x4f, 0x75, + 0x74, 0x12, 0x1c, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x32, + 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x4f, 0x75, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x1d, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x32, 0x2e, 0x53, + 0x69, 0x67, 0x6e, 0x4f, 0x75, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1c, + 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x16, 0x22, 0x14, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x32, 0x2f, + 0x61, 0x75, 0x74, 0x68, 0x2f, 0x73, 0x69, 0x67, 0x6e, 0x6f, 0x75, 0x74, 0x42, 0xa8, 0x01, 0x0a, + 0x10, 0x63, 0x6f, 0x6d, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, + 0x32, 0x42, 0x10, 0x41, 0x75, 0x74, 0x68, 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 ( diff --git a/web/src/components/UserBanner.tsx b/web/src/components/UserBanner.tsx index 5686e2ea..cb1cc7ac 100644 --- a/web/src/components/UserBanner.tsx +++ b/web/src/components/UserBanner.tsx @@ -1,6 +1,6 @@ import { Dropdown, Menu, MenuButton, MenuItem } from "@mui/joy"; import classNames from "classnames"; -import * as api from "@/helpers/api"; +import { authServiceClient } from "@/grpcweb"; import useCurrentUser from "@/hooks/useCurrentUser"; import { useGlobalStore } from "@/store/module"; import { useTranslate } from "@/utils/i18n"; @@ -21,7 +21,7 @@ const UserBanner = (props: Props) => { const avatarUrl = user ? user.avatarUrl : systemStatus.customizedProfile.logoUrl; const handleSignOut = async () => { - await api.signout(); + await authServiceClient.signOut({}); window.location.href = "/auth"; }; diff --git a/web/src/helpers/api.ts b/web/src/helpers/api.ts index 2083b2f6..6fa1bf85 100644 --- a/web/src/helpers/api.ts +++ b/web/src/helpers/api.ts @@ -13,33 +13,6 @@ export function upsertSystemSetting(systemSetting: SystemSetting) { return axios.post("/api/v1/system/setting", systemSetting); } -export function signin(username: string, password: string, remember: boolean) { - return axios.post("/api/v1/auth/signin", { - username, - password, - remember, - }); -} - -export function signinWithSSO(identityProviderId: IdentityProviderId, code: string, redirectUri: string) { - return axios.post("/api/v1/auth/signin/sso", { - identityProviderId, - code, - redirectUri, - }); -} - -export function signup(username: string, password: string) { - return axios.post("/api/v1/auth/signup", { - username, - password, - }); -} - -export function signout() { - return axios.post("/api/v1/auth/signout"); -} - export function createResourceWithBlob(formData: FormData) { return axios.post("/api/v1/resource/blob", formData); } diff --git a/web/src/pages/AuthCallback.tsx b/web/src/pages/AuthCallback.tsx index 04f5c100..c4756bca 100644 --- a/web/src/pages/AuthCallback.tsx +++ b/web/src/pages/AuthCallback.tsx @@ -3,7 +3,7 @@ import { useEffect, useState } from "react"; import { toast } from "react-hot-toast"; import { useSearchParams } from "react-router-dom"; import Icon from "@/components/Icon"; -import * as api from "@/helpers/api"; +import { authServiceClient } from "@/grpcweb"; import { absolutifyLink } from "@/helpers/utils"; import useNavigateTo from "@/hooks/useNavigateTo"; import { useUserStore } from "@/store/v1"; @@ -32,9 +32,13 @@ const AuthCallback = () => { const redirectUri = absolutifyLink("/auth/callback"); const identityProviderId = Number(last(state.split("-"))); if (identityProviderId) { - api - .signinWithSSO(identityProviderId, code, redirectUri) - .then(async ({ data: user }) => { + authServiceClient + .signInWithSSO({ + idpId: identityProviderId, + code, + redirectUri, + }) + .then(async ({ user }) => { setState({ loading: false, errorMessage: "", diff --git a/web/src/pages/SignIn.tsx b/web/src/pages/SignIn.tsx index 04b8c70e..4372ef2e 100644 --- a/web/src/pages/SignIn.tsx +++ b/web/src/pages/SignIn.tsx @@ -4,6 +4,7 @@ import { toast } from "react-hot-toast"; import { Link } from "react-router-dom"; import AppearanceSelect from "@/components/AppearanceSelect"; import LocaleSelect from "@/components/LocaleSelect"; +import { authServiceClient } from "@/grpcweb"; import * as api from "@/helpers/api"; import { absolutifyLink } from "@/helpers/utils"; import useLoading from "@/hooks/useLoading"; @@ -75,7 +76,7 @@ const SignIn = () => { try { actionBtnLoadingState.setLoading(); - const { data: user } = await api.signin(username, password, remember); + const { user } = await authServiceClient.signIn({ username, password, neverExpire: remember }); if (user) { await userStore.fetchCurrentUser(); navigateTo("/"); diff --git a/web/src/pages/SignUp.tsx b/web/src/pages/SignUp.tsx index 96b6e90f..2b665716 100644 --- a/web/src/pages/SignUp.tsx +++ b/web/src/pages/SignUp.tsx @@ -4,7 +4,7 @@ import { toast } from "react-hot-toast"; import { Link } from "react-router-dom"; import AppearanceSelect from "@/components/AppearanceSelect"; import LocaleSelect from "@/components/LocaleSelect"; -import * as api from "@/helpers/api"; +import { authServiceClient } from "@/grpcweb"; import useLoading from "@/hooks/useLoading"; import useNavigateTo from "@/hooks/useNavigateTo"; import { useGlobalStore } from "@/store/module"; @@ -55,7 +55,7 @@ const SignUp = () => { try { actionBtnLoadingState.setLoading(); - const { data: user } = await api.signup(username, password); + const { user } = await authServiceClient.signUp({ username, password }); if (user) { await userStore.fetchCurrentUser(); navigateTo("/");