mirror of
https://github.com/usememos/memos.git
synced 2025-04-07 14:21:06 +02:00
chore: add acl config (#2128)
This commit is contained in:
parent
0bb5f7f972
commit
e266d88edd
@ -27,30 +27,16 @@ const (
|
|||||||
UserIDContextKey ContextKey = iota
|
UserIDContextKey ContextKey = iota
|
||||||
)
|
)
|
||||||
|
|
||||||
var authenticationAllowlistMethods = map[string]bool{
|
|
||||||
"/memos.api.v2.SystemService/GetSystemInfo": true,
|
|
||||||
"/memos.api.v2.UserService/GetUser": true,
|
|
||||||
"/memos.api.v2.MemoService/ListMemos": true,
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsAuthenticationAllowed returns whether the method is exempted from authentication.
|
|
||||||
func IsAuthenticationAllowed(fullMethodName string) bool {
|
|
||||||
if strings.HasPrefix(fullMethodName, "/grpc.reflection") {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
return authenticationAllowlistMethods[fullMethodName]
|
|
||||||
}
|
|
||||||
|
|
||||||
// GRPCAuthInterceptor is the auth interceptor for gRPC server.
|
// GRPCAuthInterceptor is the auth interceptor for gRPC server.
|
||||||
type GRPCAuthInterceptor struct {
|
type GRPCAuthInterceptor struct {
|
||||||
store *store.Store
|
Store *store.Store
|
||||||
secret string
|
secret string
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewGRPCAuthInterceptor returns a new API auth interceptor.
|
// NewGRPCAuthInterceptor returns a new API auth interceptor.
|
||||||
func NewGRPCAuthInterceptor(store *store.Store, secret string) *GRPCAuthInterceptor {
|
func NewGRPCAuthInterceptor(store *store.Store, secret string) *GRPCAuthInterceptor {
|
||||||
return &GRPCAuthInterceptor{
|
return &GRPCAuthInterceptor{
|
||||||
store: store,
|
Store: store,
|
||||||
secret: secret,
|
secret: secret,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -68,11 +54,23 @@ func (in *GRPCAuthInterceptor) AuthenticationInterceptor(ctx context.Context, re
|
|||||||
|
|
||||||
userID, err := in.authenticate(ctx, accessTokenStr)
|
userID, err := in.authenticate(ctx, accessTokenStr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if IsAuthenticationAllowed(serverInfo.FullMethod) {
|
if isUnauthorizeAllowedMethod(serverInfo.FullMethod) {
|
||||||
return handler(ctx, request)
|
return handler(ctx, request)
|
||||||
}
|
}
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
user, err := in.Store.GetUser(ctx, &store.FindUser{
|
||||||
|
ID: &userID,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrap(err, "failed to get user")
|
||||||
|
}
|
||||||
|
if user == nil {
|
||||||
|
return nil, status.Errorf(codes.Unauthenticated, "user ID %q not exists in the access token", userID)
|
||||||
|
}
|
||||||
|
if isOnlyForAdminAllowedMethod(serverInfo.FullMethod) && user.Role != store.RoleHost && user.Role != store.RoleAdmin {
|
||||||
|
return nil, status.Errorf(codes.PermissionDenied, "user ID %q is not admin", userID)
|
||||||
|
}
|
||||||
|
|
||||||
// Stores userID into context.
|
// Stores userID into context.
|
||||||
childCtx := context.WithValue(ctx, UserIDContextKey, userID)
|
childCtx := context.WithValue(ctx, UserIDContextKey, userID)
|
||||||
@ -110,7 +108,7 @@ func (in *GRPCAuthInterceptor) authenticate(ctx context.Context, accessTokenStr
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, status.Errorf(codes.Unauthenticated, "malformed ID %q in the access token", claims.Subject)
|
return 0, status.Errorf(codes.Unauthenticated, "malformed ID %q in the access token", claims.Subject)
|
||||||
}
|
}
|
||||||
user, err := in.store.GetUser(ctx, &store.FindUser{
|
user, err := in.Store.GetUser(ctx, &store.FindUser{
|
||||||
ID: &userID,
|
ID: &userID,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
26
api/v2/acl_config.go
Normal file
26
api/v2/acl_config.go
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
package v2
|
||||||
|
|
||||||
|
import "strings"
|
||||||
|
|
||||||
|
var authenticationAllowlistMethods = map[string]bool{
|
||||||
|
"/memos.api.v2.SystemService/GetSystemInfo": true,
|
||||||
|
"/memos.api.v2.UserService/GetUser": true,
|
||||||
|
"/memos.api.v2.MemoService/ListMemos": true,
|
||||||
|
}
|
||||||
|
|
||||||
|
// isUnauthorizeAllowedMethod returns whether the method is exempted from authentication.
|
||||||
|
func isUnauthorizeAllowedMethod(fullMethodName string) bool {
|
||||||
|
if strings.HasPrefix(fullMethodName, "/grpc.reflection") {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return authenticationAllowlistMethods[fullMethodName]
|
||||||
|
}
|
||||||
|
|
||||||
|
var allowedMethodsOnlyForAdmin = map[string]bool{
|
||||||
|
"/memos.api.v2.UserService/CreateUser": true,
|
||||||
|
}
|
||||||
|
|
||||||
|
// isOnlyForAdminAllowedMethod returns true if the method is allowed to be called only by admin.
|
||||||
|
func isOnlyForAdminAllowedMethod(methodName string) bool {
|
||||||
|
return allowedMethodsOnlyForAdmin[methodName]
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user