diff --git a/api/auth.go b/api/auth.go deleted file mode 100644 index 898042b4..00000000 --- a/api/auth.go +++ /dev/null @@ -1,17 +0,0 @@ -package api - -type SignIn struct { - Username string `json:"username"` - Password string `json:"password"` -} - -type SSOSignIn struct { - IdentityProviderID int `json:"identityProviderId"` - Code string `json:"code"` - RedirectURI string `json:"redirectUri"` -} - -type SignUp struct { - Username string `json:"username"` - Password string `json:"password"` -} diff --git a/server/auth.go b/api/v1/auth.go similarity index 87% rename from server/auth.go rename to api/v1/auth.go index f874b7e9..dd70d82d 100644 --- a/server/auth.go +++ b/api/v1/auth.go @@ -1,4 +1,4 @@ -package server +package v1 import ( "encoding/json" @@ -6,21 +6,37 @@ import ( "net/http" "regexp" + "github.com/labstack/echo/v4" "github.com/pkg/errors" "github.com/usememos/memos/api" "github.com/usememos/memos/common" "github.com/usememos/memos/plugin/idp" "github.com/usememos/memos/plugin/idp/oauth2" + "github.com/usememos/memos/server/auth" "github.com/usememos/memos/store" - - "github.com/labstack/echo/v4" "golang.org/x/crypto/bcrypt" ) -func (s *Server) registerAuthRoutes(g *echo.Group, secret string) { +type SignIn struct { + Username string `json:"username"` + Password string `json:"password"` +} + +type SSOSignIn struct { + IdentityProviderID int `json:"identityProviderId"` + Code string `json:"code"` + RedirectURI string `json:"redirectUri"` +} + +type SignUp struct { + Username string `json:"username"` + Password string `json:"password"` +} + +func (s *APIV1Service) registerAuthRoutes(g *echo.Group, secret string) { g.POST("/auth/signin", func(c echo.Context) error { ctx := c.Request().Context() - signin := &api.SignIn{} + signin := &SignIn{} if err := json.NewDecoder(c.Request().Body).Decode(signin); err != nil { return echo.NewHTTPError(http.StatusBadRequest, "Malformatted signin request").SetInternal(err) } @@ -44,18 +60,18 @@ func (s *Server) registerAuthRoutes(g *echo.Group, secret string) { return echo.NewHTTPError(http.StatusUnauthorized, "Incorrect login credentials, please try again") } - if err := GenerateTokensAndSetCookies(c, user, secret); err != nil { + if err := auth.GenerateTokensAndSetCookies(c, user, secret); err != nil { return echo.NewHTTPError(http.StatusInternalServerError, "Failed to generate tokens").SetInternal(err) } - if err := s.createUserAuthSignInActivity(c, user); err != nil { + if err := s.createAuthSignInActivity(c, user); err != nil { return echo.NewHTTPError(http.StatusInternalServerError, "Failed to create activity").SetInternal(err) } - return c.JSON(http.StatusOK, composeResponse(user)) + return c.JSON(http.StatusOK, user) }) g.POST("/auth/signin/sso", func(c echo.Context) error { ctx := c.Request().Context() - signin := &api.SSOSignIn{} + signin := &SSOSignIn{} if err := json.NewDecoder(c.Request().Body).Decode(signin); err != nil { return echo.NewHTTPError(http.StatusBadRequest, "Malformatted signin request").SetInternal(err) } @@ -128,18 +144,18 @@ func (s *Server) registerAuthRoutes(g *echo.Group, secret string) { return echo.NewHTTPError(http.StatusForbidden, fmt.Sprintf("User has been archived with username %s", userInfo.Identifier)) } - if err := GenerateTokensAndSetCookies(c, user, secret); err != nil { + if err := auth.GenerateTokensAndSetCookies(c, user, secret); err != nil { return echo.NewHTTPError(http.StatusInternalServerError, "Failed to generate tokens").SetInternal(err) } - if err := s.createUserAuthSignInActivity(c, user); err != nil { + if err := s.createAuthSignInActivity(c, user); err != nil { return echo.NewHTTPError(http.StatusInternalServerError, "Failed to create activity").SetInternal(err) } - return c.JSON(http.StatusOK, composeResponse(user)) + return c.JSON(http.StatusOK, user) }) g.POST("/auth/signup", func(c echo.Context) error { ctx := c.Request().Context() - signup := &api.SignUp{} + signup := &SignUp{} if err := json.NewDecoder(c.Request().Body).Decode(signup); err != nil { return echo.NewHTTPError(http.StatusBadRequest, "Malformatted signup request").SetInternal(err) } @@ -196,23 +212,23 @@ func (s *Server) registerAuthRoutes(g *echo.Group, secret string) { if err != nil { return echo.NewHTTPError(http.StatusInternalServerError, "Failed to create user").SetInternal(err) } - if err := GenerateTokensAndSetCookies(c, user, secret); err != nil { + if err := auth.GenerateTokensAndSetCookies(c, user, secret); err != nil { return echo.NewHTTPError(http.StatusInternalServerError, "Failed to generate tokens").SetInternal(err) } - if err := s.createUserAuthSignUpActivity(c, user); err != nil { + if err := s.createAuthSignUpActivity(c, user); err != nil { return echo.NewHTTPError(http.StatusInternalServerError, "Failed to create activity").SetInternal(err) } - return c.JSON(http.StatusOK, composeResponse(user)) + return c.JSON(http.StatusOK, user) }) g.POST("/auth/signout", func(c echo.Context) error { - RemoveTokensAndCookies(c) + auth.RemoveTokensAndCookies(c) return c.JSON(http.StatusOK, true) }) } -func (s *Server) createUserAuthSignInActivity(c echo.Context, user *api.User) error { +func (s *APIV1Service) createAuthSignInActivity(c echo.Context, user *api.User) error { ctx := c.Request().Context() payload := api.ActivityUserAuthSignInPayload{ UserID: user.ID, @@ -234,7 +250,7 @@ func (s *Server) createUserAuthSignInActivity(c echo.Context, user *api.User) er return err } -func (s *Server) createUserAuthSignUpActivity(c echo.Context, user *api.User) error { +func (s *APIV1Service) createAuthSignUpActivity(c echo.Context, user *api.User) error { ctx := c.Request().Context() payload := api.ActivityUserAuthSignUpPayload{ Username: user.Username, diff --git a/api/v1/test.go b/api/v1/test.go new file mode 100644 index 00000000..eafac9de --- /dev/null +++ b/api/v1/test.go @@ -0,0 +1,9 @@ +package v1 + +import "github.com/labstack/echo/v4" + +func (*APIV1Service) registerTestRoutes(g *echo.Group) { + g.GET("/test", func(c echo.Context) error { + return c.String(200, "Hello World") + }) +} diff --git a/api/v1/v1.go b/api/v1/v1.go new file mode 100644 index 00000000..023f52be --- /dev/null +++ b/api/v1/v1.go @@ -0,0 +1,27 @@ +package v1 + +import ( + "github.com/labstack/echo/v4" + "github.com/usememos/memos/server/profile" + "github.com/usememos/memos/store" +) + +type APIV1Service struct { + Secret string + Profile *profile.Profile + Store *store.Store +} + +func NewAPIV1Service(secret string, profile *profile.Profile, store *store.Store) *APIV1Service { + return &APIV1Service{ + Secret: secret, + Profile: profile, + Store: store, + } +} + +func (s *APIV1Service) Register(e *echo.Echo) { + apiV1Group := e.Group("/api/v1") + s.registerTestRoutes(apiV1Group) + s.registerAuthRoutes(apiV1Group, s.Secret) +} diff --git a/cmd/memos.go b/cmd/memos.go index a621a9f0..dbc1940c 100644 --- a/cmd/memos.go +++ b/cmd/memos.go @@ -41,7 +41,15 @@ var ( Short: `An open-source, self-hosted memo hub with knowledge management and social networking.`, Run: func(_cmd *cobra.Command, _args []string) { ctx, cancel := context.WithCancel(context.Background()) - s, err := server.NewServer(ctx, profile) + db := db.NewDB(profile) + if err := db.Open(ctx); err != nil { + cancel() + fmt.Printf("failed to open db, error: %+v\n", err) + return + } + + store := store.New(db.DBInstance, profile) + s, err := server.NewServer(ctx, profile, store) if err != nil { cancel() fmt.Printf("failed to create server, error: %+v\n", err) diff --git a/server/auth/auth.go b/server/auth/auth.go index d4b89b88..c926a2c6 100644 --- a/server/auth/auth.go +++ b/server/auth/auth.go @@ -1,10 +1,14 @@ package auth import ( + "net/http" "strconv" "time" "github.com/golang-jwt/jwt/v4" + "github.com/labstack/echo/v4" + "github.com/pkg/errors" + "github.com/usememos/memos/api" ) const ( @@ -59,6 +63,48 @@ func GenerateRefreshToken(userName string, userID int, secret string) (string, e return generateToken(userName, userID, RefreshTokenAudienceName, expirationTime, []byte(secret)) } +// GenerateTokensAndSetCookies generates jwt token and saves it to the http-only cookie. +func GenerateTokensAndSetCookies(c echo.Context, user *api.User, secret string) error { + accessToken, err := GenerateAccessToken(user.Username, user.ID, secret) + if err != nil { + return errors.Wrap(err, "failed to generate access token") + } + + cookieExp := time.Now().Add(CookieExpDuration) + setTokenCookie(c, AccessTokenCookieName, accessToken, cookieExp) + + // We generate here a new refresh token and saving it to the cookie. + refreshToken, err := GenerateRefreshToken(user.Username, user.ID, secret) + if err != nil { + return errors.Wrap(err, "failed to generate refresh token") + } + setTokenCookie(c, RefreshTokenCookieName, refreshToken, cookieExp) + + return nil +} + +// RemoveTokensAndCookies removes the jwt token and refresh token from the cookies. +func RemoveTokensAndCookies(c echo.Context) { + // We set the expiration time to the past, so that the cookie will be removed. + cookieExp := time.Now().Add(-1 * time.Hour) + setTokenCookie(c, AccessTokenCookieName, "", cookieExp) + setTokenCookie(c, RefreshTokenCookieName, "", cookieExp) +} + +// setTokenCookie sets the token to the cookie. +func setTokenCookie(c echo.Context, name, token string, expiration time.Time) { + cookie := new(http.Cookie) + cookie.Name = name + cookie.Value = token + cookie.Expires = expiration + cookie.Path = "/" + // Http-only helps mitigate the risk of client side script accessing the protected cookie. + cookie.HttpOnly = true + cookie.SameSite = http.SameSiteStrictMode + c.SetCookie(cookie) +} + +// generateToken generates a jwt token. func generateToken(username string, userID int, aud string, expirationTime time.Time, secret []byte) (string, error) { // Create the JWT claims, which includes the username and expiry time. claims := &claimsMessage{ diff --git a/server/common.go b/server/common.go index 6a15ffa5..6ee11084 100644 --- a/server/common.go +++ b/server/common.go @@ -27,12 +27,12 @@ func defaultAPIRequestSkipper(c echo.Context) bool { return common.HasPrefixes(path, "/api") } -func (server *Server) defaultAuthSkipper(c echo.Context) bool { +func (s *Server) defaultAuthSkipper(c echo.Context) bool { ctx := c.Request().Context() path := c.Path() // Skip auth. - if common.HasPrefixes(path, "/api/auth") { + if common.HasPrefixes(path, "/api/v1/auth") { return true } @@ -42,7 +42,7 @@ func (server *Server) defaultAuthSkipper(c echo.Context) bool { userFind := &api.UserFind{ OpenID: &openID, } - user, err := server.Store.FindUser(ctx, userFind) + user, err := s.Store.FindUser(ctx, userFind) if err != nil && common.ErrorCode(err) != common.NotFound { return false } diff --git a/server/jwt.go b/server/jwt.go index f8f5317d..c16e3d14 100644 --- a/server/jwt.go +++ b/server/jwt.go @@ -33,47 +33,6 @@ func getUserIDContextKey() string { return userIDContextKey } -// GenerateTokensAndSetCookies generates jwt token and saves it to the http-only cookie. -func GenerateTokensAndSetCookies(c echo.Context, user *api.User, secret string) error { - accessToken, err := auth.GenerateAccessToken(user.Username, user.ID, secret) - if err != nil { - return errors.Wrap(err, "failed to generate access token") - } - - cookieExp := time.Now().Add(auth.CookieExpDuration) - setTokenCookie(c, auth.AccessTokenCookieName, accessToken, cookieExp) - - // We generate here a new refresh token and saving it to the cookie. - refreshToken, err := auth.GenerateRefreshToken(user.Username, user.ID, secret) - if err != nil { - return errors.Wrap(err, "failed to generate refresh token") - } - setTokenCookie(c, auth.RefreshTokenCookieName, refreshToken, cookieExp) - - return nil -} - -// RemoveTokensAndCookies removes the jwt token and refresh token from the cookies. -func RemoveTokensAndCookies(c echo.Context) { - // We set the expiration time to the past, so that the cookie will be removed. - cookieExp := time.Now().Add(-1 * time.Hour) - setTokenCookie(c, auth.AccessTokenCookieName, "", cookieExp) - setTokenCookie(c, auth.RefreshTokenCookieName, "", cookieExp) -} - -// Here we are creating a new cookie, which will store the valid JWT token. -func setTokenCookie(c echo.Context, name, token string, expiration time.Time) { - cookie := new(http.Cookie) - cookie.Name = name - cookie.Value = token - cookie.Expires = expiration - cookie.Path = "/" - // Http-only helps mitigate the risk of client side script accessing the protected cookie. - cookie.HttpOnly = true - cookie.SameSite = http.SameSiteStrictMode - c.SetCookie(cookie) -} - func extractTokenFromHeader(c echo.Context) (string, error) { authHeader := c.Request().Header.Get("Authorization") if authHeader == "" { @@ -101,6 +60,15 @@ func findAccessToken(c echo.Context) string { return accessToken } +func audienceContains(audience jwt.ClaimStrings, token string) bool { + for _, v := range audience { + if v == token { + return true + } + } + return false +} + // JWTMiddleware validates the access token. // If the access token is about to expire or has expired and the request has a valid refresh token, it // will try to generate new access token and refresh token. @@ -226,7 +194,7 @@ func JWTMiddleware(server *Server, next echo.HandlerFunc, secret string) echo.Ha // If we have a valid refresh token, we will generate new access token and refresh token if refreshToken != nil && refreshToken.Valid { - if err := GenerateTokensAndSetCookies(c, user, secret); err != nil { + if err := auth.GenerateTokensAndSetCookies(c, user, secret); err != nil { return echo.NewHTTPError(http.StatusInternalServerError, fmt.Sprintf("Server error to refresh expired token. User Id %d", userID)).SetInternal(err) } } @@ -246,12 +214,3 @@ func JWTMiddleware(server *Server, next echo.HandlerFunc, secret string) echo.Ha return next(c) } } - -func audienceContains(audience jwt.ClaimStrings, token string) bool { - for _, v := range audience { - if v == token { - return true - } - } - return false -} diff --git a/server/server.go b/server/server.go index c84d7256..4030fc4d 100644 --- a/server/server.go +++ b/server/server.go @@ -2,53 +2,45 @@ package server import ( "context" - "database/sql" "encoding/json" "fmt" "time" "github.com/pkg/errors" "github.com/usememos/memos/api" + apiV1 "github.com/usememos/memos/api/v1" "github.com/usememos/memos/plugin/telegram" "github.com/usememos/memos/server/profile" "github.com/usememos/memos/store" - "github.com/usememos/memos/store/db" "github.com/labstack/echo/v4" "github.com/labstack/echo/v4/middleware" ) type Server struct { - e *echo.Echo - db *sql.DB + e *echo.Echo ID string + Secret string Profile *profile.Profile Store *store.Store telegramBot *telegram.Bot } -func NewServer(ctx context.Context, profile *profile.Profile) (*Server, error) { +func NewServer(ctx context.Context, profile *profile.Profile, store *store.Store) (*Server, error) { e := echo.New() e.Debug = true e.HideBanner = true e.HidePort = true - db := db.NewDB(profile) - if err := db.Open(ctx); err != nil { - return nil, errors.Wrap(err, "cannot open db") - } - s := &Server{ e: e, - db: db.DBInstance, + Store: store, Profile: profile, } - storeInstance := store.New(db.DBInstance, profile) - s.Store = storeInstance - telegramBotHandler := newTelegramHandler(storeInstance) + telegramBotHandler := newTelegramHandler(store) s.telegramBot = telegram.NewBotWithHandler(telegramBotHandler) e.Use(middleware.LoggerWithConfig(middleware.LoggerConfig{ @@ -89,23 +81,23 @@ func NewServer(ctx context.Context, profile *profile.Profile) (*Server, error) { return nil, err } } + s.Secret = secret rootGroup := e.Group("") s.registerRSSRoutes(rootGroup) publicGroup := e.Group("/o") publicGroup.Use(func(next echo.HandlerFunc) echo.HandlerFunc { - return JWTMiddleware(s, next, secret) + return JWTMiddleware(s, next, s.Secret) }) registerGetterPublicRoutes(publicGroup) s.registerResourcePublicRoutes(publicGroup) apiGroup := e.Group("/api") apiGroup.Use(func(next echo.HandlerFunc) echo.HandlerFunc { - return JWTMiddleware(s, next, secret) + return JWTMiddleware(s, next, s.Secret) }) s.registerSystemRoutes(apiGroup) - s.registerAuthRoutes(apiGroup, secret) s.registerUserRoutes(apiGroup) s.registerMemoRoutes(apiGroup) s.registerMemoResourceRoutes(apiGroup) @@ -117,6 +109,9 @@ func NewServer(ctx context.Context, profile *profile.Profile) (*Server, error) { s.registerOpenAIRoutes(apiGroup) s.registerMemoRelationRoutes(apiGroup) + apiV1Service := apiV1.NewAPIV1Service(s.Secret, profile, store) + apiV1Service.Register(e) + return s, nil } @@ -140,7 +135,7 @@ func (s *Server) Shutdown(ctx context.Context) { } // Close database connection - if err := s.db.Close(); err != nil { + if err := s.Store.GetDB().Close(); err != nil { fmt.Printf("failed to close database, error: %v\n", err) } diff --git a/store/store.go b/store/store.go index 159c953a..cd35b1ee 100644 --- a/store/store.go +++ b/store/store.go @@ -28,6 +28,10 @@ func New(db *sql.DB, profile *profile.Profile) *Store { } } +func (s *Store) GetDB() *sql.DB { + return s.db +} + func (s *Store) Vacuum(ctx context.Context) error { tx, err := s.db.BeginTx(ctx, nil) if err != nil { diff --git a/test/server/auth_test.go b/test/server/auth_test.go index 51cf9f79..d0c350fd 100644 --- a/test/server/auth_test.go +++ b/test/server/auth_test.go @@ -9,6 +9,7 @@ import ( "github.com/pkg/errors" "github.com/stretchr/testify/require" "github.com/usememos/memos/api" + apiv1 "github.com/usememos/memos/api/v1" ) func TestAuthServer(t *testing.T) { @@ -17,7 +18,7 @@ func TestAuthServer(t *testing.T) { require.NoError(t, err) defer s.Shutdown(ctx) - signup := &api.SignUp{ + signup := &apiv1.SignUp{ Username: "testuser", Password: "testpassword", } @@ -26,15 +27,15 @@ func TestAuthServer(t *testing.T) { require.Equal(t, signup.Username, user.Username) } -func (s *TestingServer) postAuthSignup(signup *api.SignUp) (*api.User, error) { +func (s *TestingServer) postAuthSignup(signup *apiv1.SignUp) (*api.User, error) { rawData, err := json.Marshal(&signup) if err != nil { return nil, errors.Wrap(err, "failed to marshal signup") } reader := bytes.NewReader(rawData) - body, err := s.post("/api/auth/signup", reader, nil) + body, err := s.post("/api/v1/auth/signup", reader, nil) if err != nil { - return nil, err + return nil, errors.Wrap(err, "fail to post request") } buf := &bytes.Buffer{} @@ -43,12 +44,9 @@ func (s *TestingServer) postAuthSignup(signup *api.SignUp) (*api.User, error) { return nil, errors.Wrap(err, "fail to read response body") } - type AuthSignupResponse struct { - Data *api.User `json:"data"` - } - res := new(AuthSignupResponse) - if err = json.Unmarshal(buf.Bytes(), res); err != nil { + user := &api.User{} + if err = json.Unmarshal(buf.Bytes(), user); err != nil { return nil, errors.Wrap(err, "fail to unmarshal post signup response") } - return res.Data, nil + return user, nil } diff --git a/test/server/memo_relation_test.go b/test/server/memo_relation_test.go index cc2339fd..a1cb840b 100644 --- a/test/server/memo_relation_test.go +++ b/test/server/memo_relation_test.go @@ -10,6 +10,7 @@ import ( "github.com/pkg/errors" "github.com/stretchr/testify/require" "github.com/usememos/memos/api" + apiv1 "github.com/usememos/memos/api/v1" ) func TestMemoRelationServer(t *testing.T) { @@ -18,7 +19,7 @@ func TestMemoRelationServer(t *testing.T) { require.NoError(t, err) defer s.Shutdown(ctx) - signup := &api.SignUp{ + signup := &apiv1.SignUp{ Username: "testuser", Password: "testpassword", } diff --git a/test/server/memo_test.go b/test/server/memo_test.go index ccfd92cc..d1c61a31 100644 --- a/test/server/memo_test.go +++ b/test/server/memo_test.go @@ -10,6 +10,7 @@ import ( "github.com/pkg/errors" "github.com/stretchr/testify/require" "github.com/usememos/memos/api" + apiv1 "github.com/usememos/memos/api/v1" ) func TestMemoServer(t *testing.T) { @@ -18,7 +19,7 @@ func TestMemoServer(t *testing.T) { require.NoError(t, err) defer s.Shutdown(ctx) - signup := &api.SignUp{ + signup := &apiv1.SignUp{ Username: "testuser", Password: "testpassword", } diff --git a/test/server/server.go b/test/server/server.go index e1a9da62..d2c1b217 100644 --- a/test/server/server.go +++ b/test/server/server.go @@ -13,6 +13,7 @@ import ( "github.com/pkg/errors" "github.com/usememos/memos/server" "github.com/usememos/memos/server/profile" + "github.com/usememos/memos/store" "github.com/usememos/memos/store/db" "github.com/usememos/memos/test" @@ -34,19 +35,19 @@ func NewTestingServer(ctx context.Context, t *testing.T) (*TestingServer, error) return nil, errors.Wrap(err, "failed to open db") } - server, err := server.NewServer(ctx, profile) + store := store.New(db.DBInstance, profile) + server, err := server.NewServer(ctx, profile, store) if err != nil { return nil, errors.Wrap(err, "failed to create server") } - errChan := make(chan error, 1) - s := &TestingServer{ server: server, client: &http.Client{}, profile: profile, cookie: "", } + errChan := make(chan error, 1) go func() { if err := s.server.Start(ctx); err != nil { @@ -126,7 +127,7 @@ func (s *TestingServer) request(method, uri string, body io.Reader, params, head } if method == "POST" { - if strings.Contains(uri, "/api/auth/login") || strings.Contains(uri, "/api/auth/signup") { + if strings.Contains(uri, "/api/v1/auth/login") || strings.Contains(uri, "/api/v1/auth/signup") { cookie := "" h := resp.Header.Get("Set-Cookie") parts := strings.Split(h, "; ") @@ -140,7 +141,7 @@ func (s *TestingServer) request(method, uri string, body io.Reader, params, head return nil, errors.Errorf("unable to find access token in the login response headers") } s.cookie = cookie - } else if strings.Contains(uri, "/api/auth/logout") { + } else if strings.Contains(uri, "/api/v1/auth/logout") { s.cookie = "" } } diff --git a/test/server/system_test.go b/test/server/system_test.go index ef0a11dc..478a1184 100644 --- a/test/server/system_test.go +++ b/test/server/system_test.go @@ -9,6 +9,7 @@ import ( "github.com/pkg/errors" "github.com/stretchr/testify/require" "github.com/usememos/memos/api" + apiv1 "github.com/usememos/memos/api/v1" ) func TestSystemServer(t *testing.T) { @@ -21,7 +22,7 @@ func TestSystemServer(t *testing.T) { require.NoError(t, err) require.Equal(t, (*api.User)(nil), status.Host) - signup := &api.SignUp{ + signup := &apiv1.SignUp{ Username: "testuser", Password: "testpassword", } diff --git a/web/src/helpers/api.ts b/web/src/helpers/api.ts index 7eaa91a3..495af373 100644 --- a/web/src/helpers/api.ts +++ b/web/src/helpers/api.ts @@ -23,14 +23,14 @@ export function vacuumDatabase() { } export function signin(username: string, password: string) { - return axios.post>("/api/auth/signin", { + return axios.post("/api/v1/auth/signin", { username, password, }); } export function signinWithSSO(identityProviderId: IdentityProviderId, code: string, redirectUri: string) { - return axios.post>("/api/auth/signin/sso", { + return axios.post("/api/v1/auth/signin/sso", { identityProviderId, code, redirectUri, @@ -38,14 +38,14 @@ export function signinWithSSO(identityProviderId: IdentityProviderId, code: stri } export function signup(username: string, password: string) { - return axios.post>("/api/auth/signup", { + return axios.post("/api/v1/auth/signup", { username, password, }); } export function signout() { - return axios.post("/api/auth/signout"); + return axios.post("/api/v1/auth/signout"); } export function createUser(userCreate: UserCreate) {