mirror of https://github.com/usememos/memos.git
Merge d88a116fbc into 7c708ee27e
This commit is contained in:
commit
c6e4e87bb5
|
|
@ -6,8 +6,8 @@ import (
|
|||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"log/slog"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"golang.org/x/oauth2"
|
||||
|
|
@ -79,7 +79,7 @@ func (p *IdentityProvider) ExchangeToken(ctx context.Context, redirectURL, code,
|
|||
|
||||
// UserInfo returns the parsed user information using the given OAuth2 token.
|
||||
func (p *IdentityProvider) UserInfo(token string) (*idp.IdentityProviderUserInfo, error) {
|
||||
client := &http.Client{}
|
||||
client := &http.Client{Timeout: 10 * time.Second}
|
||||
req, err := http.NewRequest(http.MethodGet, p.config.UserInfoUrl, nil)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "failed to create http request")
|
||||
|
|
@ -101,7 +101,6 @@ func (p *IdentityProvider) UserInfo(token string) (*idp.IdentityProviderUserInfo
|
|||
if err := json.Unmarshal(body, &claims); err != nil {
|
||||
return nil, errors.Wrap(err, "failed to unmarshal response body")
|
||||
}
|
||||
slog.Info("user info claims", "claims", claims)
|
||||
userInfo := &idp.IdentityProviderUserInfo{}
|
||||
if v, ok := claims[p.config.FieldMapping.Identifier].(string); ok {
|
||||
userInfo.Identifier = v
|
||||
|
|
@ -129,6 +128,5 @@ func (p *IdentityProvider) UserInfo(token string) (*idp.IdentityProviderUserInfo
|
|||
userInfo.AvatarURL = v
|
||||
}
|
||||
}
|
||||
slog.Info("user info", "userInfo", userInfo)
|
||||
return userInfo, nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -83,8 +83,8 @@ func (s *APIV1Service) SignIn(ctx context.Context, request *v1pb.SignInRequest)
|
|||
if err != nil {
|
||||
return nil, status.Errorf(codes.Internal, "failed to get instance general setting, error: %v", err)
|
||||
}
|
||||
// Check if the password auth in is allowed.
|
||||
if instanceGeneralSetting.DisallowPasswordAuth && user.Role == store.RoleUser {
|
||||
// Check if password auth is allowed. Enforce for all roles including admins.
|
||||
if instanceGeneralSetting.DisallowPasswordAuth {
|
||||
return nil, status.Errorf(codes.PermissionDenied, "password signin is not allowed")
|
||||
}
|
||||
existingUser = user
|
||||
|
|
|
|||
|
|
@ -139,6 +139,9 @@ func (s *APIV1Service) CreateUser(ctx context.Context, request *v1pb.CreateUserR
|
|||
}, nil
|
||||
}
|
||||
|
||||
if len(request.User.Password) < 8 {
|
||||
return nil, status.Errorf(codes.InvalidArgument, "password must be at least 8 characters")
|
||||
}
|
||||
passwordHash, err := bcrypt.GenerateFromPassword([]byte(request.User.Password), bcrypt.DefaultCost)
|
||||
if err != nil {
|
||||
return nil, status.Errorf(codes.Internal, "failed to generate password hash: %v", err)
|
||||
|
|
@ -242,6 +245,9 @@ func (s *APIV1Service) UpdateUser(ctx context.Context, request *v1pb.UpdateUserR
|
|||
role := convertUserRoleToStore(request.User.Role)
|
||||
update.Role = &role
|
||||
case "password":
|
||||
if len(request.User.Password) < 8 {
|
||||
return nil, status.Errorf(codes.InvalidArgument, "password must be at least 8 characters")
|
||||
}
|
||||
passwordHash, err := bcrypt.GenerateFromPassword([]byte(request.User.Password), bcrypt.DefaultCost)
|
||||
if err != nil {
|
||||
return nil, status.Errorf(codes.Internal, "failed to generate password hash: %v", err)
|
||||
|
|
|
|||
|
|
@ -111,7 +111,17 @@ func (s *APIV1Service) RegisterGateway(ctx context.Context, echoServer *echo.Ech
|
|||
}
|
||||
gwGroup := echoServer.Group("")
|
||||
gwGroup.Use(middleware.CORSWithConfig(middleware.CORSConfig{
|
||||
AllowOrigins: []string{"*"},
|
||||
UnsafeAllowOriginFunc: func(_ *echo.Context, origin string) (string, bool, error) {
|
||||
// In demo mode, allow all origins for development convenience.
|
||||
// In production, deny cross-origin requests (same-origin only).
|
||||
if s.Profile.Demo {
|
||||
return origin, true, nil
|
||||
}
|
||||
return "", false, nil
|
||||
},
|
||||
AllowMethods: []string{http.MethodGet, http.MethodPost, http.MethodPut, http.MethodPatch, http.MethodDelete, http.MethodOptions},
|
||||
AllowHeaders: []string{"Content-Type", "Authorization"},
|
||||
AllowCredentials: true,
|
||||
}))
|
||||
// Register SSE endpoint with same CORS as rest of /api/v1.
|
||||
RegisterSSERoutes(gwGroup, s.SSEHub, s.Store, s.Secret)
|
||||
|
|
@ -135,7 +145,11 @@ func (s *APIV1Service) RegisterGateway(ctx context.Context, echoServer *echo.Ech
|
|||
// Wrap with CORS for browser access
|
||||
corsHandler := middleware.CORSWithConfig(middleware.CORSConfig{
|
||||
UnsafeAllowOriginFunc: func(_ *echo.Context, origin string) (string, bool, error) {
|
||||
return origin, true, nil
|
||||
// In demo mode, allow all origins for development convenience.
|
||||
if s.Profile.Demo {
|
||||
return origin, true, nil
|
||||
}
|
||||
return "", false, nil
|
||||
},
|
||||
AllowMethods: []string{http.MethodGet, http.MethodPost, http.MethodOptions},
|
||||
AllowHeaders: []string{"*"},
|
||||
|
|
|
|||
|
|
@ -50,11 +50,9 @@ func NewServer(ctx context.Context, profile *profile.Profile, store *store.Store
|
|||
return nil, errors.Wrap(err, "failed to get instance basic setting")
|
||||
}
|
||||
|
||||
secret := "usememos"
|
||||
if !profile.Demo {
|
||||
secret = instanceBasicSetting.SecretKey
|
||||
}
|
||||
s.Secret = secret
|
||||
// Always use the instance secret key, regardless of mode.
|
||||
// Never fall back to a hardcoded secret, as it allows token forgery.
|
||||
s.Secret = instanceBasicSetting.SecretKey
|
||||
|
||||
// Register healthz endpoint.
|
||||
echoServer.GET("/healthz", func(c *echo.Context) error {
|
||||
|
|
|
|||
Loading…
Reference in New Issue