fix: require Wayne user ID for role binding
This commit is contained in:
+6
-5
@@ -285,14 +285,14 @@ Wayne 会把回调地址拼成:
|
|||||||
|
|
||||||
## Wayne 授权代理接口
|
## Wayne 授权代理接口
|
||||||
|
|
||||||
AuthServer 的 Wayne 授权代理接口不要求调用方传 Wayne user ID。后端会从当前 `authserver_token` 里取 `email`,把它作为 Wayne username 传给 Wayne internal API。
|
AuthServer 的 Wayne 授权代理接口要求调用方传目标 Wayne `userId`。后端会从当前 `authserver_token` 里取 `email` 作为操作者 `operatorName`,目标用户 ID 由请求体或路径参数提供。
|
||||||
|
|
||||||
对外接口:
|
对外接口:
|
||||||
|
|
||||||
```text
|
```text
|
||||||
GET /auth/api/v1/wayne/namespaces
|
GET /auth/api/v1/wayne/namespaces
|
||||||
GET /auth/api/v1/wayne/groups
|
GET /auth/api/v1/wayne/groups
|
||||||
GET /auth/api/v1/wayne/users/me/roles
|
GET /auth/api/v1/wayne/users/:userid/roles
|
||||||
GET /auth/api/v1/wayne/namespaces/:namespaceid/operator-permissions
|
GET /auth/api/v1/wayne/namespaces/:namespaceid/operator-permissions
|
||||||
GET /auth/api/v1/wayne/apps/:appid/operator-permissions
|
GET /auth/api/v1/wayne/apps/:appid/operator-permissions
|
||||||
PUT /auth/api/v1/wayne/namespaces/:namespaceid/roles
|
PUT /auth/api/v1/wayne/namespaces/:namespaceid/roles
|
||||||
@@ -309,6 +309,7 @@ Authorization: Bearer <authserver_token>
|
|||||||
Content-Type: application/json
|
Content-Type: application/json
|
||||||
|
|
||||||
{
|
{
|
||||||
|
"userId": 2001,
|
||||||
"groupIds": [10, 11],
|
"groupIds": [10, 11],
|
||||||
"replace": false,
|
"replace": false,
|
||||||
"requestId": "req-001",
|
"requestId": "req-001",
|
||||||
@@ -316,13 +317,13 @@ Content-Type: application/json
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
AuthServer 转发到 Wayne internal API 时会使用 token email:
|
AuthServer 转发到 Wayne internal API 时会使用请求体里的 `userId`:
|
||||||
|
|
||||||
```text
|
```text
|
||||||
PUT /api/v1/internal/namespaces/1/users/<token-email>/roles
|
PUT /api/v1/internal/namespaces/1/users/2001/roles
|
||||||
```
|
```
|
||||||
|
|
||||||
并覆盖请求体中的 `operatorName` 为 token email,忽略外部传入的 `operatorUserId`。
|
并覆盖请求体中的 `operatorName` 为 token email,忽略外部传入的 `operatorUserId`。`userId` 只用于 Wayne path,不会透传到 Wayne 请求体。
|
||||||
|
|
||||||
相关配置:
|
相关配置:
|
||||||
|
|
||||||
|
|||||||
@@ -64,11 +64,11 @@ func (h *WayneRoleBindingHandler) ListGroups(c *gin.Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (h *WayneRoleBindingHandler) GetCurrentUserRoles(c *gin.Context) {
|
func (h *WayneRoleBindingHandler) GetCurrentUserRoles(c *gin.Context) {
|
||||||
username, ok := currentTokenEmail(c)
|
userID, ok := parseUintPathParam(c, "userid")
|
||||||
if !ok {
|
if !ok {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
h.handleQuery(c, "user_roles", 0, username)
|
h.handleQuery(c, "user_roles", userID, "")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *WayneRoleBindingHandler) NamespaceOperatorPermissions(c *gin.Context) {
|
func (h *WayneRoleBindingHandler) NamespaceOperatorPermissions(c *gin.Context) {
|
||||||
@@ -111,30 +111,34 @@ func (h *WayneRoleBindingHandler) handle(c *gin.Context, scope string, method st
|
|||||||
if !ok {
|
if !ok {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
targetUserID, ok := roleBindingTargetUserID(c, req)
|
||||||
|
if !ok {
|
||||||
|
return
|
||||||
|
}
|
||||||
if method == http.MethodPut && len(req.GroupIDs) == 0 {
|
if method == http.MethodPut && len(req.GroupIDs) == 0 {
|
||||||
c.JSON(http.StatusBadRequest, gin.H{"error": "groupIds is required"})
|
c.JSON(http.StatusBadRequest, gin.H{"error": "groupIds is required"})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
result, err := h.call(c, scope, method, resourceID, operatorEmail, req)
|
result, err := h.call(c, scope, method, resourceID, targetUserID, operatorEmail, req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
h.writeAudit(c, claims.UserID, operatorEmail, scope, resourceID, operatorEmail, "deny", req.RequestID, err.Error())
|
h.writeAudit(c, claims.UserID, operatorEmail, scope, resourceID, targetUserID, "deny", req.RequestID, err.Error())
|
||||||
writeWayneRoleBindingError(c, result, err)
|
writeWayneRoleBindingError(c, result, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
h.writeAudit(c, claims.UserID, operatorEmail, scope, resourceID, operatorEmail, "allow", req.RequestID, "")
|
h.writeAudit(c, claims.UserID, operatorEmail, scope, resourceID, targetUserID, "allow", req.RequestID, "")
|
||||||
writeWayneRoleBindingResult(c, result)
|
writeWayneRoleBindingResult(c, result)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *WayneRoleBindingHandler) handleQuery(c *gin.Context, resourceType string, resourceID uint64, username string) {
|
func (h *WayneRoleBindingHandler) handleQuery(c *gin.Context, resourceType string, resourceID uint64, _ string) {
|
||||||
var result *service.WayneRoleBindingResult
|
var result *service.WayneRoleBindingResult
|
||||||
var err error
|
var err error
|
||||||
switch resourceType {
|
switch resourceType {
|
||||||
case "namespaces":
|
case "namespaces":
|
||||||
result, err = h.wayne.ListNamespaces(c.Request.Context())
|
result, err = h.wayne.ListNamespaces(c.Request.Context())
|
||||||
case "user_roles":
|
case "user_roles":
|
||||||
result, err = h.wayne.GetUserRoles(c.Request.Context(), username)
|
result, err = h.wayne.GetUserRoles(c.Request.Context(), resourceID)
|
||||||
default:
|
default:
|
||||||
c.JSON(http.StatusBadRequest, gin.H{"error": "unsupported query resource"})
|
c.JSON(http.StatusBadRequest, gin.H{"error": "unsupported query resource"})
|
||||||
return
|
return
|
||||||
@@ -177,17 +181,17 @@ func (h *WayneRoleBindingHandler) handleOperatorPermissions(c *gin.Context, scop
|
|||||||
writeWayneRoleBindingResult(c, result)
|
writeWayneRoleBindingResult(c, result)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *WayneRoleBindingHandler) call(c *gin.Context, scope, method string, resourceID uint64, operatorEmail string, req service.WayneRoleBindingRequest) (*service.WayneRoleBindingResult, error) {
|
func (h *WayneRoleBindingHandler) call(c *gin.Context, scope, method string, resourceID uint64, targetUserID uint64, operatorEmail string, req service.WayneRoleBindingRequest) (*service.WayneRoleBindingResult, error) {
|
||||||
if scope == "namespace" {
|
if scope == "namespace" {
|
||||||
if method == http.MethodPut {
|
if method == http.MethodPut {
|
||||||
return h.wayne.BindNamespace(c.Request.Context(), resourceID, operatorEmail, req)
|
return h.wayne.BindNamespace(c.Request.Context(), resourceID, targetUserID, operatorEmail, req)
|
||||||
}
|
}
|
||||||
return h.wayne.UnbindNamespace(c.Request.Context(), resourceID, operatorEmail, req)
|
return h.wayne.UnbindNamespace(c.Request.Context(), resourceID, targetUserID, operatorEmail, req)
|
||||||
}
|
}
|
||||||
if method == http.MethodPut {
|
if method == http.MethodPut {
|
||||||
return h.wayne.BindApp(c.Request.Context(), resourceID, operatorEmail, req)
|
return h.wayne.BindApp(c.Request.Context(), resourceID, targetUserID, operatorEmail, req)
|
||||||
}
|
}
|
||||||
return h.wayne.UnbindApp(c.Request.Context(), resourceID, operatorEmail, req)
|
return h.wayne.UnbindApp(c.Request.Context(), resourceID, targetUserID, operatorEmail, req)
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseRoleBindingRequest(c *gin.Context) (service.WayneRoleBindingRequest, bool) {
|
func parseRoleBindingRequest(c *gin.Context) (service.WayneRoleBindingRequest, bool) {
|
||||||
@@ -208,6 +212,26 @@ func parseRoleBindingRequest(c *gin.Context) (service.WayneRoleBindingRequest, b
|
|||||||
return req, true
|
return req, true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func roleBindingTargetUserID(c *gin.Context, req service.WayneRoleBindingRequest) (uint64, bool) {
|
||||||
|
if req.UserID != nil && *req.UserID != 0 {
|
||||||
|
return *req.UserID, true
|
||||||
|
}
|
||||||
|
for _, key := range []string{"userId", "user_id", "userid"} {
|
||||||
|
raw := strings.TrimSpace(c.Query(key))
|
||||||
|
if raw == "" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
value, err := strconv.ParseUint(raw, 10, 64)
|
||||||
|
if err != nil || value == 0 {
|
||||||
|
c.JSON(http.StatusBadRequest, gin.H{"error": "invalid userId"})
|
||||||
|
return 0, false
|
||||||
|
}
|
||||||
|
return value, true
|
||||||
|
}
|
||||||
|
c.JSON(http.StatusBadRequest, gin.H{"error": "userId is required"})
|
||||||
|
return 0, false
|
||||||
|
}
|
||||||
|
|
||||||
func parseUintPathParam(c *gin.Context, name string) (uint64, bool) {
|
func parseUintPathParam(c *gin.Context, name string) (uint64, bool) {
|
||||||
raw := strings.TrimSpace(c.Param(name))
|
raw := strings.TrimSpace(c.Param(name))
|
||||||
value, err := strconv.ParseUint(raw, 10, 64)
|
value, err := strconv.ParseUint(raw, 10, 64)
|
||||||
@@ -256,21 +280,7 @@ func writeWayneRoleBindingError(c *gin.Context, result *service.WayneRoleBinding
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func currentTokenEmail(c *gin.Context) (string, bool) {
|
func (h *WayneRoleBindingHandler) writeAudit(c *gin.Context, userID uint64, operatorEmail, scope string, resourceID uint64, targetUserID uint64, decision, requestID, reason string) {
|
||||||
claims, ok := CurrentClaims(c)
|
|
||||||
if !ok {
|
|
||||||
c.JSON(http.StatusUnauthorized, gin.H{"error": "missing current user"})
|
|
||||||
return "", false
|
|
||||||
}
|
|
||||||
email := strings.TrimSpace(claims.Email)
|
|
||||||
if email == "" {
|
|
||||||
c.JSON(http.StatusBadRequest, gin.H{"error": "email is missing in token"})
|
|
||||||
return "", false
|
|
||||||
}
|
|
||||||
return email, true
|
|
||||||
}
|
|
||||||
|
|
||||||
func (h *WayneRoleBindingHandler) writeAudit(c *gin.Context, userID uint64, operatorEmail, scope string, resourceID uint64, targetUsername string, decision, requestID, reason string) {
|
|
||||||
h.audit.Write(service.AuditEntry{
|
h.audit.Write(service.AuditEntry{
|
||||||
RequestID: requestID,
|
RequestID: requestID,
|
||||||
ActorUserID: userID,
|
ActorUserID: userID,
|
||||||
@@ -283,9 +293,9 @@ func (h *WayneRoleBindingHandler) writeAudit(c *gin.Context, userID uint64, oper
|
|||||||
ScopeType: scope,
|
ScopeType: scope,
|
||||||
ScopeID: resourceID,
|
ScopeID: resourceID,
|
||||||
Decision: decision,
|
Decision: decision,
|
||||||
Reason: reason,
|
Reason: truncateAuditReason(reason),
|
||||||
Metadata: map[string]any{
|
Metadata: map[string]any{
|
||||||
"targetUsername": targetUsername,
|
"targetUserId": targetUserID,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -310,6 +320,14 @@ func (h *WayneRoleBindingHandler) writeQueryAudit(c *gin.Context, resourceType s
|
|||||||
ResourceType: "wayne_" + resourceType,
|
ResourceType: "wayne_" + resourceType,
|
||||||
ResourceID: strconv.FormatUint(resourceID, 10),
|
ResourceID: strconv.FormatUint(resourceID, 10),
|
||||||
Decision: decision,
|
Decision: decision,
|
||||||
Reason: reason,
|
Reason: truncateAuditReason(reason),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func truncateAuditReason(reason string) string {
|
||||||
|
const maxReasonBytes = 512
|
||||||
|
if len(reason) <= maxReasonBytes {
|
||||||
|
return reason
|
||||||
|
}
|
||||||
|
return reason[:maxReasonBytes]
|
||||||
|
}
|
||||||
|
|||||||
@@ -115,7 +115,7 @@ func registerAuthServerRoutes(r *gin.Engine, deps Dependencies) {
|
|||||||
protected.PUT("/wayen/credential", wayenHandler.SaveCredential)
|
protected.PUT("/wayen/credential", wayenHandler.SaveCredential)
|
||||||
protected.GET("/wayne/namespaces", wayneRoleBindingHandler.ListNamespaces)
|
protected.GET("/wayne/namespaces", wayneRoleBindingHandler.ListNamespaces)
|
||||||
protected.GET("/wayne/groups", wayneRoleBindingHandler.ListGroups)
|
protected.GET("/wayne/groups", wayneRoleBindingHandler.ListGroups)
|
||||||
protected.GET("/wayne/users/me/roles", wayneRoleBindingHandler.GetCurrentUserRoles)
|
protected.GET("/wayne/users/:userid/roles", wayneRoleBindingHandler.GetCurrentUserRoles)
|
||||||
protected.GET("/wayne/namespaces/:namespaceid/operator-permissions", wayneRoleBindingHandler.NamespaceOperatorPermissions)
|
protected.GET("/wayne/namespaces/:namespaceid/operator-permissions", wayneRoleBindingHandler.NamespaceOperatorPermissions)
|
||||||
protected.GET("/wayne/apps/:appid/operator-permissions", wayneRoleBindingHandler.AppOperatorPermissions)
|
protected.GET("/wayne/apps/:appid/operator-permissions", wayneRoleBindingHandler.AppOperatorPermissions)
|
||||||
protected.PUT("/wayne/namespaces/:namespaceid/roles", wayneRoleBindingHandler.BindNamespace)
|
protected.PUT("/wayne/namespaces/:namespaceid/roles", wayneRoleBindingHandler.BindNamespace)
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ var (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type WayneRoleBindingRequest struct {
|
type WayneRoleBindingRequest struct {
|
||||||
|
UserID *uint64 `json:"userId,omitempty"`
|
||||||
GroupIDs []uint64 `json:"groupIds,omitempty"`
|
GroupIDs []uint64 `json:"groupIds,omitempty"`
|
||||||
OperatorUserID *uint64 `json:"operatorUserId,omitempty"`
|
OperatorUserID *uint64 `json:"operatorUserId,omitempty"`
|
||||||
OperatorName string `json:"operatorName,omitempty"`
|
OperatorName string `json:"operatorName,omitempty"`
|
||||||
@@ -71,20 +72,20 @@ func NewWayneRoleBindingService(cfg config.Config) *WayneRoleBindingService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *WayneRoleBindingService) BindNamespace(ctx context.Context, namespaceID uint64, username string, req WayneRoleBindingRequest) (*WayneRoleBindingResult, error) {
|
func (s *WayneRoleBindingService) BindNamespace(ctx context.Context, namespaceID uint64, userID uint64, operatorEmail string, req WayneRoleBindingRequest) (*WayneRoleBindingResult, error) {
|
||||||
return s.call(ctx, http.MethodPut, fmt.Sprintf("/api/v1/internal/namespaces/%d/users/%s/roles", namespaceID, url.PathEscape(username)), username, req)
|
return s.call(ctx, http.MethodPut, fmt.Sprintf("/api/v1/internal/namespaces/%d/users/%d/roles", namespaceID, userID), operatorEmail, req)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *WayneRoleBindingService) UnbindNamespace(ctx context.Context, namespaceID uint64, username string, req WayneRoleBindingRequest) (*WayneRoleBindingResult, error) {
|
func (s *WayneRoleBindingService) UnbindNamespace(ctx context.Context, namespaceID uint64, userID uint64, operatorEmail string, req WayneRoleBindingRequest) (*WayneRoleBindingResult, error) {
|
||||||
return s.call(ctx, http.MethodDelete, fmt.Sprintf("/api/v1/internal/namespaces/%d/users/%s/roles", namespaceID, url.PathEscape(username)), username, req)
|
return s.call(ctx, http.MethodDelete, fmt.Sprintf("/api/v1/internal/namespaces/%d/users/%d/roles", namespaceID, userID), operatorEmail, req)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *WayneRoleBindingService) BindApp(ctx context.Context, appID uint64, username string, req WayneRoleBindingRequest) (*WayneRoleBindingResult, error) {
|
func (s *WayneRoleBindingService) BindApp(ctx context.Context, appID uint64, userID uint64, operatorEmail string, req WayneRoleBindingRequest) (*WayneRoleBindingResult, error) {
|
||||||
return s.call(ctx, http.MethodPut, fmt.Sprintf("/api/v1/internal/apps/%d/users/%s/roles", appID, url.PathEscape(username)), username, req)
|
return s.call(ctx, http.MethodPut, fmt.Sprintf("/api/v1/internal/apps/%d/users/%d/roles", appID, userID), operatorEmail, req)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *WayneRoleBindingService) UnbindApp(ctx context.Context, appID uint64, username string, req WayneRoleBindingRequest) (*WayneRoleBindingResult, error) {
|
func (s *WayneRoleBindingService) UnbindApp(ctx context.Context, appID uint64, userID uint64, operatorEmail string, req WayneRoleBindingRequest) (*WayneRoleBindingResult, error) {
|
||||||
return s.call(ctx, http.MethodDelete, fmt.Sprintf("/api/v1/internal/apps/%d/users/%s/roles", appID, url.PathEscape(username)), username, req)
|
return s.call(ctx, http.MethodDelete, fmt.Sprintf("/api/v1/internal/apps/%d/users/%d/roles", appID, userID), operatorEmail, req)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *WayneRoleBindingService) ListNamespaces(ctx context.Context) (*WayneRoleBindingResult, error) {
|
func (s *WayneRoleBindingService) ListNamespaces(ctx context.Context) (*WayneRoleBindingResult, error) {
|
||||||
@@ -101,12 +102,11 @@ func (s *WayneRoleBindingService) ListGroups(ctx context.Context, groupType *int
|
|||||||
return s.callRaw(ctx, http.MethodGet, internalPath, nil)
|
return s.callRaw(ctx, http.MethodGet, internalPath, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *WayneRoleBindingService) GetUserRoles(ctx context.Context, username string) (*WayneRoleBindingResult, error) {
|
func (s *WayneRoleBindingService) GetUserRoles(ctx context.Context, userID uint64) (*WayneRoleBindingResult, error) {
|
||||||
username = strings.TrimSpace(username)
|
if userID == 0 {
|
||||||
if username == "" {
|
return nil, ErrWayneRoleBindingRequestFailed
|
||||||
return nil, ErrWayenEmailMissing
|
|
||||||
}
|
}
|
||||||
return s.callRaw(ctx, http.MethodGet, fmt.Sprintf("/api/v1/internal/users/%s/roles", url.PathEscape(username)), nil)
|
return s.callRaw(ctx, http.MethodGet, fmt.Sprintf("/api/v1/internal/users/%d/roles", userID), nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *WayneRoleBindingService) NamespaceOperatorPermissions(ctx context.Context, namespaceID uint64, operatorEmail string) (*WayneRoleBindingResult, error) {
|
func (s *WayneRoleBindingService) NamespaceOperatorPermissions(ctx context.Context, namespaceID uint64, operatorEmail string) (*WayneRoleBindingResult, error) {
|
||||||
@@ -128,6 +128,7 @@ func (s *WayneRoleBindingService) call(ctx context.Context, method, internalPath
|
|||||||
|
|
||||||
req.OperatorUserID = nil
|
req.OperatorUserID = nil
|
||||||
req.OperatorName = operatorEmail
|
req.OperatorName = operatorEmail
|
||||||
|
req.UserID = nil
|
||||||
|
|
||||||
body, err := json.Marshal(req)
|
body, err := json.Marshal(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -40,7 +40,9 @@ func TestWayneRoleBindingServiceBindNamespaceSignsAndOverridesOperator(t *testin
|
|||||||
|
|
||||||
operatorUserID := uint64(123)
|
operatorUserID := uint64(123)
|
||||||
replace := false
|
replace := false
|
||||||
result, err := svc.BindNamespace(context.Background(), 1, "eastsales@qiniu.com", WayneRoleBindingRequest{
|
targetUserID := uint64(2001)
|
||||||
|
result, err := svc.BindNamespace(context.Background(), 1, targetUserID, "eastsales@qiniu.com", WayneRoleBindingRequest{
|
||||||
|
UserID: &targetUserID,
|
||||||
GroupIDs: []uint64{10, 11},
|
GroupIDs: []uint64{10, 11},
|
||||||
OperatorUserID: &operatorUserID,
|
OperatorUserID: &operatorUserID,
|
||||||
OperatorName: "attacker@example.com",
|
OperatorName: "attacker@example.com",
|
||||||
@@ -54,7 +56,7 @@ func TestWayneRoleBindingServiceBindNamespaceSignsAndOverridesOperator(t *testin
|
|||||||
if result.StatusCode != http.StatusOK {
|
if result.StatusCode != http.StatusOK {
|
||||||
t.Fatalf("StatusCode = %d, want 200", result.StatusCode)
|
t.Fatalf("StatusCode = %d, want 200", result.StatusCode)
|
||||||
}
|
}
|
||||||
if requestPath != "/api/v1/internal/namespaces/1/users/eastsales@qiniu.com/roles" {
|
if requestPath != "/api/v1/internal/namespaces/1/users/2001/roles" {
|
||||||
t.Fatalf("requestPath = %q", requestPath)
|
t.Fatalf("requestPath = %q", requestPath)
|
||||||
}
|
}
|
||||||
if payload.OperatorName != "eastsales@qiniu.com" {
|
if payload.OperatorName != "eastsales@qiniu.com" {
|
||||||
@@ -63,6 +65,9 @@ func TestWayneRoleBindingServiceBindNamespaceSignsAndOverridesOperator(t *testin
|
|||||||
if payload.OperatorUserID != nil {
|
if payload.OperatorUserID != nil {
|
||||||
t.Fatalf("OperatorUserID should be omitted, got %v", *payload.OperatorUserID)
|
t.Fatalf("OperatorUserID should be omitted, got %v", *payload.OperatorUserID)
|
||||||
}
|
}
|
||||||
|
if payload.UserID != nil {
|
||||||
|
t.Fatalf("UserID should be omitted from Wayne body, got %v", *payload.UserID)
|
||||||
|
}
|
||||||
if payload.Replace == nil || *payload.Replace {
|
if payload.Replace == nil || *payload.Replace {
|
||||||
t.Fatalf("Replace = %v, want false", payload.Replace)
|
t.Fatalf("Replace = %v, want false", payload.Replace)
|
||||||
}
|
}
|
||||||
@@ -77,23 +82,23 @@ func TestWayneRoleBindingServiceCallsAllDocumentedEndpoints(t *testing.T) {
|
|||||||
{
|
{
|
||||||
name: "unbind namespace",
|
name: "unbind namespace",
|
||||||
call: func(s *WayneRoleBindingService) (*WayneRoleBindingResult, error) {
|
call: func(s *WayneRoleBindingService) (*WayneRoleBindingResult, error) {
|
||||||
return s.UnbindNamespace(context.Background(), 1, "eastsales@qiniu.com", WayneRoleBindingRequest{GroupIDs: []uint64{10}})
|
return s.UnbindNamespace(context.Background(), 1, 2001, "eastsales@qiniu.com", WayneRoleBindingRequest{GroupIDs: []uint64{10}})
|
||||||
},
|
},
|
||||||
want: "DELETE /api/v1/internal/namespaces/1/users/eastsales@qiniu.com/roles",
|
want: "DELETE /api/v1/internal/namespaces/1/users/2001/roles",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "bind app",
|
name: "bind app",
|
||||||
call: func(s *WayneRoleBindingService) (*WayneRoleBindingResult, error) {
|
call: func(s *WayneRoleBindingService) (*WayneRoleBindingResult, error) {
|
||||||
return s.BindApp(context.Background(), 3, "eastsales@qiniu.com", WayneRoleBindingRequest{GroupIDs: []uint64{20}})
|
return s.BindApp(context.Background(), 3, 2001, "eastsales@qiniu.com", WayneRoleBindingRequest{GroupIDs: []uint64{20}})
|
||||||
},
|
},
|
||||||
want: "PUT /api/v1/internal/apps/3/users/eastsales@qiniu.com/roles",
|
want: "PUT /api/v1/internal/apps/3/users/2001/roles",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "unbind app",
|
name: "unbind app",
|
||||||
call: func(s *WayneRoleBindingService) (*WayneRoleBindingResult, error) {
|
call: func(s *WayneRoleBindingService) (*WayneRoleBindingResult, error) {
|
||||||
return s.UnbindApp(context.Background(), 3, "eastsales@qiniu.com", WayneRoleBindingRequest{GroupIDs: []uint64{20}})
|
return s.UnbindApp(context.Background(), 3, 2001, "eastsales@qiniu.com", WayneRoleBindingRequest{GroupIDs: []uint64{20}})
|
||||||
},
|
},
|
||||||
want: "DELETE /api/v1/internal/apps/3/users/eastsales@qiniu.com/roles",
|
want: "DELETE /api/v1/internal/apps/3/users/2001/roles",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "list namespaces",
|
name: "list namespaces",
|
||||||
@@ -120,9 +125,9 @@ func TestWayneRoleBindingServiceCallsAllDocumentedEndpoints(t *testing.T) {
|
|||||||
{
|
{
|
||||||
name: "get user roles",
|
name: "get user roles",
|
||||||
call: func(s *WayneRoleBindingService) (*WayneRoleBindingResult, error) {
|
call: func(s *WayneRoleBindingService) (*WayneRoleBindingResult, error) {
|
||||||
return s.GetUserRoles(context.Background(), "eastsales@qiniu.com")
|
return s.GetUserRoles(context.Background(), 2001)
|
||||||
},
|
},
|
||||||
want: "GET /api/v1/internal/users/eastsales@qiniu.com/roles",
|
want: "GET /api/v1/internal/users/2001/roles",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "namespace operator permissions",
|
name: "namespace operator permissions",
|
||||||
@@ -226,7 +231,7 @@ func TestWayneRoleBindingServiceHTTPError(t *testing.T) {
|
|||||||
WayneServiceName: "xinfra",
|
WayneServiceName: "xinfra",
|
||||||
WayneServiceAPISecretKey: "service-secret",
|
WayneServiceAPISecretKey: "service-secret",
|
||||||
})
|
})
|
||||||
result, err := svc.BindApp(context.Background(), 3, "eastsales@qiniu.com", WayneRoleBindingRequest{GroupIDs: []uint64{20}})
|
result, err := svc.BindApp(context.Background(), 3, 2001, "eastsales@qiniu.com", WayneRoleBindingRequest{GroupIDs: []uint64{20}})
|
||||||
if err == nil {
|
if err == nil {
|
||||||
t.Fatal("expected error")
|
t.Fatal("expected error")
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user