Merge pull request #2357 from swordqiu/hotfix/qj-new-apis-for-project-user-group-roles

fix: deprecate old user/group joint project API, create new action apis
This commit is contained in:
yunion-ci-robot
2019-08-17 21:35:08 +08:00
committed by GitHub
27 changed files with 851 additions and 29 deletions
+58
View File
@@ -17,6 +17,7 @@ package shell
import (
"yunion.io/x/jsonutils"
api "yunion.io/x/onecloud/pkg/apis/identity"
"yunion.io/x/onecloud/pkg/mcclient"
"yunion.io/x/onecloud/pkg/mcclient/modules"
"yunion.io/x/onecloud/pkg/mcclient/options"
@@ -133,4 +134,61 @@ func init() {
return nil
})
R(&GroupShowOptions{}, "group-project-list", "List projects of group", func(s *mcclient.ClientSession, args *GroupShowOptions) error {
query := jsonutils.NewDict()
if len(args.Domain) > 0 {
domainId, err := modules.Domains.GetId(s, args.Domain, nil)
if err != nil {
return err
}
query.Add(jsonutils.NewString(domainId), "domain_id")
}
uid, err := modules.Groups.GetId(s, args.ID, query)
if err != nil {
return err
}
projects, e := modules.Groups.GetProjects(s, uid)
if e != nil {
return e
}
printList(projects, modules.Projects.GetColumns(s))
return nil
})
type GroupJoinProjectOptions struct {
Group string `help:"Group Id or name" optional:"false" positional:"true"`
Project []string `help:"Projects to join" nargs:"+"`
Role []string `help:"User join project with roles" nargs:"+"`
}
R(&GroupJoinProjectOptions{}, "group-join-project", "Group join projects with roles", func(s *mcclient.ClientSession, args *GroupJoinProjectOptions) error {
input := api.SJoinProjectsInput{}
input.Projects = args.Project
input.Roles = args.Role
result, err := modules.Groups.PerformAction(s, args.Group, "join", jsonutils.Marshal(input))
if err != nil {
return err
}
printObject(result)
return nil
})
type GroupLeaveProjectsOptions struct {
Group string `help:"group id or name" optional:"false" positional:"true"`
Project string `help:"project id or name" optional:"false" positional:"true"`
Role []string `help:"roles to remove" nargs:"+"`
}
R(&GroupLeaveProjectsOptions{}, "group-leave-project", "Leave a group from projects", func(s *mcclient.ClientSession, args *GroupLeaveProjectsOptions) error {
input := api.SLeaveProjectsInput{}
input.ProjectRoles = make([]api.SProjectRole, len(args.Role))
for i := range args.Role {
input.ProjectRoles[i].Project = args.Project
input.ProjectRoles[i].Role = args.Role[i]
}
result, err := modules.Groups.PerformAction(s, args.Group, "leave", jsonutils.Marshal(input))
if err != nil {
return err
}
printObject(result)
return nil
})
}
+53
View File
@@ -17,6 +17,7 @@ package shell
import (
"yunion.io/x/jsonutils"
api "yunion.io/x/onecloud/pkg/apis/identity"
"yunion.io/x/onecloud/pkg/mcclient"
"yunion.io/x/onecloud/pkg/mcclient/modules"
"yunion.io/x/onecloud/pkg/mcclient/options"
@@ -364,6 +365,7 @@ func init() {
return nil
})*/
// Deprecated
type ProjectBatchJoinOptions struct {
Ids []string `help:"user ids or group ids"`
Resource string `help:"resource type" choices:"users|groups"`
@@ -378,4 +380,55 @@ func init() {
}
return nil
})
type ProjectAddUserGroupOptions struct {
Project string `help:"ID or name of project to add users/groups" positional:"true" optional:"false"`
User []string `help:"ID of user to add"`
Group []string `help:"ID of group to add"`
Role []string `help:"ID of role to add"`
}
R(&ProjectAddUserGroupOptions{}, "project-add-user-group", "Batch add users/groups to project", func(s *mcclient.ClientSession, args *ProjectAddUserGroupOptions) error {
input := api.SProjectAddUserGroupInput{}
input.Users = args.User
input.Groups = args.Group
input.Roles = args.Role
err := input.Validate()
if err != nil {
return err
}
result, err := modules.Projects.PerformAction(s, args.Project, "join", jsonutils.Marshal(input))
if err != nil {
return err
}
printObject(result)
return nil
})
type ProjectRemoveUserGroup struct {
Project string `help:"ID or name of project to remove user/group" optional:"false" positional:"true"`
User string `help:"user to remove"`
Group string `help:"group to remove"`
Role []string `help:"roles to remove"`
}
R(&ProjectRemoveUserGroup{}, "project-remove-user-group", "Remove users/groups from project", func(s *mcclient.ClientSession, args *ProjectRemoveUserGroup) error {
input := api.SProjectRemoveUserGroupInput{}
input.UserRoles = make([]api.SUserRole, len(args.Role))
input.GroupRoles = make([]api.SGroupRole, len(args.Role))
for i := range args.Role {
input.UserRoles[i].User = args.User
input.UserRoles[i].Role = args.Role[i]
input.GroupRoles[i].Group = args.Group
input.GroupRoles[i].Role = args.Role[i]
}
err := input.Validate()
if err != nil {
return err
}
result, err := modules.Projects.PerformAction(s, args.Project, "leave", jsonutils.Marshal(input))
if err != nil {
return err
}
printObject(result)
return nil
})
}
+38
View File
@@ -17,6 +17,7 @@ package shell
import (
"yunion.io/x/jsonutils"
api "yunion.io/x/onecloud/pkg/apis/identity"
"yunion.io/x/onecloud/pkg/mcclient"
"yunion.io/x/onecloud/pkg/mcclient/modules"
"yunion.io/x/onecloud/pkg/mcclient/options"
@@ -361,4 +362,41 @@ func init() {
return nil
})
type UserJoinProjectOptions struct {
User string `help:"User Id or name" optional:"false" positional:"true"`
Project []string `help:"Projects to join" nargs:"+"`
Role []string `help:"User join project with roles" nargs:"+"`
}
R(&UserJoinProjectOptions{}, "user-join-project", "User join projects with roles", func(s *mcclient.ClientSession, args *UserJoinProjectOptions) error {
input := api.SJoinProjectsInput{}
input.Projects = args.Project
input.Roles = args.Role
result, err := modules.UsersV3.PerformAction(s, args.User, "join", jsonutils.Marshal(input))
if err != nil {
return err
}
printObject(result)
return nil
})
type UserLeaveProjectsOptions struct {
User string `help:"user id or name" optional:"false" positional:"true"`
Project string `help:"project id or name" optional:"false" positional:"true"`
Role []string `help:"roles to remove" nargs:"+"`
}
R(&UserLeaveProjectsOptions{}, "user-leave-project", "Leave a user from projects", func(s *mcclient.ClientSession, args *UserLeaveProjectsOptions) error {
input := api.SLeaveProjectsInput{}
input.ProjectRoles = make([]api.SProjectRole, len(args.Role))
for i := range args.Role {
input.ProjectRoles[i].Project = args.Project
input.ProjectRoles[i].Role = args.Role[i]
}
result, err := modules.UsersV3.PerformAction(s, args.User, "leave", jsonutils.Marshal(input))
if err != nil {
return err
}
printObject(result)
return nil
})
}
+16
View File
@@ -0,0 +1,16 @@
post:
summary: 将组以多个角色加入多个项目
parameters:
- $ref: '../parameters/group.yaml#/group_id'
- name: group
in: body
required: true
schema:
$ref: "../schemas/project.yaml#/ProjectJoinRequestInput"
responses:
200:
description: 组信息
schema:
$ref: "../schemas/group.yaml#/GroupGetResponse"
tags:
- groups
+16
View File
@@ -0,0 +1,16 @@
post:
summary: 将组的多个角色从多个项目中删除
parameters:
- $ref: '../parameters/group.yaml#/group_id'
- name: group
in: body
required: true
schema:
$ref: "../schemas/project.yaml#/ProjectLeaveRequestInput"
responses:
200:
description: 组信息
schema:
$ref: "../schemas/group.yaml#/GroupGetResponse"
tags:
- groups
+16
View File
@@ -0,0 +1,16 @@
post:
summary: 将多个用户和组以多个角色加入指定项目
parameters:
- $ref: '../parameters/project.yaml#/project_id'
- name: project
in: body
required: true
schema:
$ref: "../schemas/project.yaml#/ProjectJoinUserGroupRequestInput"
responses:
200:
description: 项目信息
schema:
$ref: "../schemas/project.yaml#/ProjectGetResponse"
tags:
- projects
+16
View File
@@ -0,0 +1,16 @@
post:
summary: 将多个用户和组以多个角色从指定项目删除
parameters:
- $ref: '../parameters/project.yaml#/project_id'
- name: project
in: body
required: true
schema:
$ref: "../schemas/project.yaml#/ProjectRemoveUserGroupRequestInput"
responses:
200:
description: 项目信息
schema:
$ref: "../schemas/project.yaml#/ProjectGetResponse"
tags:
- projects
+2
View File
@@ -1,4 +1,5 @@
put:
deprecated: true
summary: 将组以指定角色加入项目
parameters:
- $ref: '../parameters/identity.yaml#/project_id'
@@ -11,6 +12,7 @@ put:
- roles
delete:
deprecated: true
summary: 将组在项目中的角色删除
parameters:
- $ref: '../parameters/identity.yaml#/project_id'
+2
View File
@@ -1,4 +1,5 @@
put:
deprecated: true
summary: 将用户以指定角色加入项目
parameters:
- $ref: '../parameters/identity.yaml#/project_id'
@@ -11,6 +12,7 @@ put:
- roles
delete:
deprecated: true
summary: 将用户在项目中的角色删除
parameters:
- $ref: '../parameters/identity.yaml#/project_id'
+16
View File
@@ -0,0 +1,16 @@
post:
summary: 将用户以多个角色加入多个项目
parameters:
- $ref: '../parameters/user.yaml#/user_id'
- name: user
in: body
required: true
schema:
$ref: "../schemas/project.yaml#/ProjectJoinRequestInput"
responses:
200:
description: 用户信息
schema:
$ref: "../schemas/user.yaml#/UserGetResponse"
tags:
- users
+16
View File
@@ -0,0 +1,16 @@
post:
summary: 将用户的多个角色从多个项目中删除
parameters:
- $ref: '../parameters/user.yaml#/user_id'
- name: user
in: body
required: true
schema:
$ref: "../schemas/project.yaml#/ProjectLeaveRequestInput"
responses:
200:
description: 用户信息
schema:
$ref: "../schemas/user.yaml#/UserGetResponse"
tags:
- users
+12
View File
@@ -312,11 +312,19 @@ paths:
$ref: "./identity/users.yaml"
/users/{user_id}:
$ref: "./identity/user.yaml"
/users/{user_id}/join:
$ref: "./identity/user_join.yaml"
/users/{user_id}/leave:
$ref: "./identity/user_leave.yaml"
/groups:
$ref: "./identity/groups.yaml"
/groups/{group_id}:
$ref: "./identity/group.yaml"
/groups/{group_id}/join:
$ref: "./identity/group_join.yaml"
/groups/{group_id}/leave:
$ref: "./identity/group_leave.yaml"
/groups/{group_id}/users/{user_id}:
$ref: "./identity/groupuser.yaml"
@@ -324,6 +332,10 @@ paths:
$ref: "./identity/projects.yaml"
/projects/{project_id}:
$ref: "./identity/project.yaml"
/projects/{project_id}/join:
$ref: "./identity/project_join.yaml"
/projects/{project_id}/leave:
$ref: "./identity/project_leave.yaml"
/roles:
$ref: "./identity/roles.yaml"
+81
View File
@@ -57,3 +57,84 @@ Project:
can_delete:
type: boolean
description: 是否可以删除
ProjectJoinRequestInput:
type: object
description: 用户或组批量加入项目的请求body
properties:
projects:
type: array
description: 项目列表
items:
type: string
roles:
type: array
description: 角色列表
items:
type: string
ProjectLeaveRequestInput:
type: object
description: 用户或组批量移除项目的请求body
properties:
project_roles:
type: array
description: 移除的项目和角色列表
items:
type: object
properties:
project:
type: string
description: 项目ID或名称
role:
type: string
description: 角色ID或名称
ProjectJoinUserGroupRequestInput:
type: object
description: 将多个用户或组批量加入指定项目的请求body
properties:
users:
type: array
description: 加入的用户列表
items:
type: string
groups:
type: array
description: 加入的组列表
items:
type: string
roles:
type: array
description: 加入的角色列表
items:
type: string
ProjectRemoveUserGroupRequestInput:
type: object
description: 将多个用户或组从指定项目移除的请求body
properties:
user_roles:
type: array
description: 用户和角色列表
items:
type: object
properties:
user:
type: string
description: 用户ID或名称
role:
type: string
description: 角色ID或名称
group_roles:
type: array
description: 组和角色列表
items:
type: object
properties:
group:
type: string
description: 组ID或名称
role:
type: string
description: 角色ID或名称
+1 -1
View File
@@ -153,6 +153,6 @@ require (
yunion.io/x/log v0.0.0-20190629062853-9f6483a7103d
yunion.io/x/pkg v0.0.0-20190726033806-b564cfdcc224
yunion.io/x/s3cli v0.0.0-20190812034537-1e65a6651a3e
yunion.io/x/sqlchemy v0.0.0-20190813100902-cfa59aeabbfe
yunion.io/x/sqlchemy v0.0.0-20190817082003-905772542cba
yunion.io/x/structarg v0.0.0-20190809075558-115bed041de3
)
+2 -2
View File
@@ -587,7 +587,7 @@ yunion.io/x/pkg v0.0.0-20190726033806-b564cfdcc224 h1:dAeUov/CtKcPaOapGVG7+NRqmU
yunion.io/x/pkg v0.0.0-20190726033806-b564cfdcc224/go.mod h1:t6rEGG2sQ4J7DhFxSZVOTjNd0YO/KlfWQyK1W4tog+E=
yunion.io/x/s3cli v0.0.0-20190812034537-1e65a6651a3e h1:Jk82txl4vaL/MoVV3+GweEcCmLOcqo5XYF8tlBD/1hY=
yunion.io/x/s3cli v0.0.0-20190812034537-1e65a6651a3e/go.mod h1:0iFKpOs1y4lbCxeOmq3Xx/0AcQoewVPwj62eRluioEo=
yunion.io/x/sqlchemy v0.0.0-20190813100902-cfa59aeabbfe h1:gslRYwVFAQI29PZL56mfBe+zpgbtIMSL1zSEnBbF1bI=
yunion.io/x/sqlchemy v0.0.0-20190813100902-cfa59aeabbfe/go.mod h1:FTdwPdGhMgh4E+UFXc9klI1Ok34fMuybTT+jLhOaIjI=
yunion.io/x/sqlchemy v0.0.0-20190817082003-905772542cba h1:vPCRA59Kq9Hv24ef/G92sCgqmBYmZyLSVP902EUDimw=
yunion.io/x/sqlchemy v0.0.0-20190817082003-905772542cba/go.mod h1:FTdwPdGhMgh4E+UFXc9klI1Ok34fMuybTT+jLhOaIjI=
yunion.io/x/structarg v0.0.0-20190809075558-115bed041de3 h1:bfC8EhXYvyGYldRWlzxiCM39Zfj3s3+zham9mW2h2LE=
yunion.io/x/structarg v0.0.0-20190809075558-115bed041de3/go.mod h1:EP6NSv2C0zzqBDTKumv8hPWLb3XvgMZDHQRfyuOrQng=
+110
View File
@@ -0,0 +1,110 @@
// Copyright 2019 Yunion
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package identity
import (
"yunion.io/x/pkg/errors"
)
type SJoinProjectsInput struct {
Projects []string
Roles []string
}
func (input SJoinProjectsInput) Validate() error {
if len(input.Projects) == 0 {
return errors.Error("empty projects")
}
if len(input.Roles) == 0 {
return errors.Error("empty roles")
}
return nil
}
type SProjectRole struct {
Project string
Role string
}
type SLeaveProjectsInput struct {
ProjectRoles []SProjectRole
}
func (input SLeaveProjectsInput) Validate() error {
if len(input.ProjectRoles) == 0 {
return errors.Error("empty project_roles")
}
for i := range input.ProjectRoles {
if len(input.ProjectRoles[i].Project) == 0 {
return errors.Error("no project in project_roles")
}
if len(input.ProjectRoles[i].Role) == 0 {
return errors.Error("no role in project_roles")
}
}
return nil
}
type SProjectAddUserGroupInput struct {
Users []string
Groups []string
Roles []string
}
func (input SProjectAddUserGroupInput) Validate() error {
if len(input.Users) == 0 && len(input.Groups) == 0 {
return errors.Error("empty user and group")
}
if len(input.Roles) == 0 {
return errors.Error("invalid roles")
}
return nil
}
type SUserRole struct {
User string
Role string
}
type SGroupRole struct {
Group string
Role string
}
type SProjectRemoveUserGroupInput struct {
UserRoles []SUserRole
GroupRoles []SGroupRole
}
func (input SProjectRemoveUserGroupInput) Validate() error {
if len(input.UserRoles) == 0 && len(input.GroupRoles) == 0 {
return errors.Error("empty input")
}
for i := range input.UserRoles {
if len(input.UserRoles[i].User) == 0 {
return errors.Error("empty user")
}
if len(input.UserRoles[i].Role) == 0 {
return errors.Error("empty role")
}
}
for i := range input.GroupRoles {
if len(input.GroupRoles[i].Group) == 0 {
return errors.Error("empty group")
}
if len(input.GroupRoles[i].Role) == 0 {
return errors.Error("empty role")
}
}
return nil
}
+1 -1
View File
@@ -417,7 +417,7 @@ func fetchContextObject(manager IModelManager, ctx context.Context, userCred mcc
return nil, httperrors.NewInternalServerError("No context manager")
}
for i := 0; i < len(ctxMans); i += 1 {
for j := 0; j < len(ctxMans); j += 1 {
for j := 0; j < len(ctxMans[i]); j += 1 {
if ctxMans[i][j].KeywordPlural() == ctxId.Type {
ctxObj, err := fetchItem(ctxMans[i][j], ctx, userCred, ctxId.Id, nil)
if err != nil {
@@ -1,3 +1,17 @@
// Copyright 2019 Yunion
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package tasks
import (
+14
View File
@@ -1,3 +1,17 @@
// Copyright 2019 Yunion
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package tasks
import (
+25 -17
View File
@@ -259,11 +259,12 @@ func (manager *SAssignmentManager) projectAddUser(ctx context.Context, userCred
}
}
err = manager.add(api.AssignmentUserProject, user.Id, project.Id, role.Id)
if err == nil {
db.OpsLog.LogEvent(user, db.ACT_ATTACH, project.GetShortDesc(ctx), userCred)
db.OpsLog.LogEvent(project, db.ACT_ATTACH, user.GetShortDesc(ctx), userCred)
if err != nil {
return errors.Wrap(err, "manager.add")
}
return err
db.OpsLog.LogEvent(user, db.ACT_ATTACH, project.GetShortDesc(ctx), userCred)
db.OpsLog.LogEvent(project, db.ACT_ATTACH, user.GetShortDesc(ctx), userCred)
return nil
}
func (manager *SAssignmentManager) batchRemove(actorId string, typeStrs []string) error {
@@ -333,11 +334,12 @@ func (manager *SAssignmentManager) projectRemoveUser(ctx context.Context, userCr
}
}
err := manager.remove(api.AssignmentUserProject, user.Id, project.Id, role.Id)
if err == nil {
db.OpsLog.LogEvent(user, db.ACT_DETACH, project.GetShortDesc(ctx), userCred)
db.OpsLog.LogEvent(project, db.ACT_DETACH, user.GetShortDesc(ctx), userCred)
if err != nil {
return errors.Wrap(err, "manager.remove")
}
return err
db.OpsLog.LogEvent(user, db.ACT_DETACH, project.GetShortDesc(ctx), userCred)
db.OpsLog.LogEvent(project, db.ACT_DETACH, user.GetShortDesc(ctx), userCred)
return nil
}
func (manager *SAssignmentManager) projectAddGroup(ctx context.Context, userCred mcclient.TokenCredential, project *SProject, group *SGroup, role *SRole) error {
@@ -357,11 +359,12 @@ func (manager *SAssignmentManager) projectAddGroup(ctx context.Context, userCred
}
}
err = manager.add(api.AssignmentGroupProject, group.Id, project.Id, role.Id)
if err == nil {
db.OpsLog.LogEvent(group, db.ACT_ATTACH, project.GetShortDesc(ctx), userCred)
db.OpsLog.LogEvent(project, db.ACT_ATTACH, group.GetShortDesc(ctx), userCred)
if err != nil {
return errors.Wrap(err, "manager.add")
}
return err
db.OpsLog.LogEvent(group, db.ACT_ATTACH, project.GetShortDesc(ctx), userCred)
db.OpsLog.LogEvent(project, db.ACT_ATTACH, group.GetShortDesc(ctx), userCred)
return nil
}
func (manager *SAssignmentManager) projectRemoveGroup(ctx context.Context, userCred mcclient.TokenCredential, project *SProject, group *SGroup, role *SRole) error {
@@ -378,11 +381,12 @@ func (manager *SAssignmentManager) projectRemoveGroup(ctx context.Context, userC
}
}
err := manager.remove(api.AssignmentGroupProject, group.Id, project.Id, role.Id)
if err == nil {
db.OpsLog.LogEvent(group, db.ACT_DETACH, project.GetShortDesc(ctx), userCred)
db.OpsLog.LogEvent(project, db.ACT_DETACH, group.GetShortDesc(ctx), userCred)
if err != nil {
return errors.Wrap(err, "manager.remove")
}
return err
db.OpsLog.LogEvent(group, db.ACT_DETACH, project.GetShortDesc(ctx), userCred)
db.OpsLog.LogEvent(project, db.ACT_DETACH, group.GetShortDesc(ctx), userCred)
return nil
}
func (manager *SAssignmentManager) remove(typeStr, actorId, projectId, roleId string) error {
@@ -412,7 +416,11 @@ func (manager *SAssignmentManager) add(typeStr, actorId, projectId, roleId strin
Inherited: tristate.False,
}
assign.SetModelManager(manager, &assign)
return manager.TableSpec().InsertOrUpdate(&assign)
err := manager.TableSpec().InsertOrUpdate(&assign)
if err != nil {
return errors.Wrap(err, "InsertOrUpdate")
}
return nil
}
func AddAdhocHandlers(version string, app *appsrv.Application) {
+42
View File
@@ -278,3 +278,45 @@ func (manager *SGroupManager) FetchGroupsInDomain(domainId string, excludes []st
func (group *SGroup) UnlinkIdp(idpId string) error {
return IdmappingManager.deleteAny(idpId, api.IdMappingEntityGroup, group.Id)
}
func (group *SGroup) AllowPerformJoin(ctx context.Context,
userCred mcclient.TokenCredential,
query jsonutils.JSONObject,
data jsonutils.JSONObject,
) bool {
return db.IsAdminAllowPerform(userCred, group, "join")
}
func (group *SGroup) PerformJoin(
ctx context.Context,
userCred mcclient.TokenCredential,
query jsonutils.JSONObject,
data jsonutils.JSONObject,
) (jsonutils.JSONObject, error) {
err := joinProjects(group, false, ctx, userCred, data)
if err != nil {
return nil, err
}
return nil, nil
}
func (group *SGroup) AllowPerformLeave(ctx context.Context,
userCred mcclient.TokenCredential,
query jsonutils.JSONObject,
data jsonutils.JSONObject,
) bool {
return db.IsAdminAllowPerform(userCred, group, "leave")
}
func (group *SGroup) PerformLeave(
ctx context.Context,
userCred mcclient.TokenCredential,
query jsonutils.JSONObject,
data jsonutils.JSONObject,
) (jsonutils.JSONObject, error) {
err := leaveProjects(group, false, ctx, userCred, data)
if err != nil {
return nil, err
}
return nil, nil
}
+5 -5
View File
@@ -89,9 +89,9 @@ func (model *SIdentityBaseResource) GetIIdentityModel() IIdentityModel {
return model.GetVirtualObject().(IIdentityModel)
}
func (model *SIdentityBaseResource) IsOwner(userCred mcclient.TokenCredential) bool {
return userCred.GetProjectDomainId() == model.DomainId
}
// func (model *SIdentityBaseResource) IsOwner(userCred mcclient.TokenCredential) bool {
// return userCred.GetProjectDomainId() == model.DomainId
// }
func (model *SIdentityBaseResource) GetDomain() *SDomain {
if len(model.DomainId) > 0 && model.DomainId != api.KeystoneDomainRoot {
@@ -109,11 +109,11 @@ func (manager *SIdentityBaseResourceManager) GetIIdentityModelManager() IIdentit
}
func (manager *SIdentityBaseResourceManager) FetchByName(userCred mcclient.IIdentityProvider, idStr string) (db.IModel, error) {
return db.FetchByName(manager, userCred, idStr)
return db.FetchByName(manager.GetIIdentityModelManager(), userCred, idStr)
}
func (manager *SIdentityBaseResourceManager) FetchByIdOrName(userCred mcclient.IIdentityProvider, idStr string) (db.IModel, error) {
return db.FetchByIdOrName(manager, userCred, idStr)
return db.FetchByIdOrName(manager.GetIIdentityModelManager(), userCred, idStr)
}
func (manager *SIdentityBaseResourceManager) ListItemFilter(ctx context.Context, q *sqlchemy.SQuery, userCred mcclient.TokenCredential, query jsonutils.JSONObject) (*sqlchemy.SQuery, error) {
+151
View File
@@ -361,3 +361,154 @@ func (manager *SProjectManager) ValidateCreateData(ctx context.Context, userCred
}
return manager.SIdentityBaseResourceManager.ValidateCreateData(ctx, userCred, ownerId, query, data)
}
func (project *SProject) AllowPerformJoin(ctx context.Context,
userCred mcclient.TokenCredential,
query jsonutils.JSONObject,
data jsonutils.JSONObject,
) bool {
return db.IsAdminAllowPerform(userCred, project, "join")
}
func (project *SProject) PerformJoin(
ctx context.Context,
userCred mcclient.TokenCredential,
query jsonutils.JSONObject,
data jsonutils.JSONObject,
) (jsonutils.JSONObject, error) {
input := api.SProjectAddUserGroupInput{}
err := data.Unmarshal(&input)
if err != nil {
return nil, httperrors.NewInputParameterError("unmarshal project add user group input error %s", err)
}
err = input.Validate()
if err != nil {
return nil, httperrors.NewInputParameterError(err.Error())
}
roles := make([]*SRole, 0)
for i := range input.Roles {
obj, err := RoleManager.FetchByIdOrName(userCred, input.Roles[i])
if err != nil {
if err == sql.ErrNoRows {
return nil, httperrors.NewResourceNotFoundError2(RoleManager.Keyword(), input.Roles[i])
} else {
return nil, httperrors.NewGeneralError(err)
}
}
roles = append(roles, obj.(*SRole))
}
users := make([]*SUser, 0)
for i := range input.Users {
obj, err := UserManager.FetchByIdOrName(userCred, input.Users[i])
if err != nil {
if err == sql.ErrNoRows {
return nil, httperrors.NewResourceNotFoundError2(UserManager.Keyword(), input.Users[i])
} else {
return nil, httperrors.NewGeneralError(err)
}
}
users = append(users, obj.(*SUser))
}
groups := make([]*SGroup, 0)
for i := range input.Groups {
obj, err := GroupManager.FetchByIdOrName(userCred, input.Groups[i])
if err != nil {
if err == sql.ErrNoRows {
return nil, httperrors.NewResourceNotFoundError2(GroupManager.Keyword(), input.Groups[i])
} else {
return nil, httperrors.NewGeneralError(err)
}
}
groups = append(groups, obj.(*SGroup))
}
for i := range users {
for j := range roles {
err = AssignmentManager.projectAddUser(ctx, userCred, project, users[i], roles[j])
if err != nil {
return nil, httperrors.NewGeneralError(err)
}
}
}
for i := range groups {
for j := range roles {
err = AssignmentManager.projectAddGroup(ctx, userCred, project, groups[i], roles[j])
if err != nil {
return nil, httperrors.NewGeneralError(err)
}
}
}
return nil, nil
}
func (project *SProject) AllowPerformLeave(ctx context.Context,
userCred mcclient.TokenCredential,
query jsonutils.JSONObject,
data jsonutils.JSONObject,
) bool {
return db.IsAdminAllowPerform(userCred, project, "leave")
}
func (project *SProject) PerformLeave(
ctx context.Context,
userCred mcclient.TokenCredential,
query jsonutils.JSONObject,
data jsonutils.JSONObject,
) (jsonutils.JSONObject, error) {
input := api.SProjectRemoveUserGroupInput{}
err := data.Unmarshal(&input)
if err != nil {
return nil, httperrors.NewInputParameterError("unmarshal project remove usergroup input error %s", err)
}
err = input.Validate()
if err != nil {
return nil, httperrors.NewInputParameterError(err.Error())
}
for i := range input.UserRoles {
userObj, err := UserManager.FetchByIdOrName(userCred, input.UserRoles[i].User)
if err != nil {
if err == sql.ErrNoRows {
return nil, httperrors.NewResourceNotFoundError2(UserManager.Keyword(), input.UserRoles[i].User)
} else {
return nil, httperrors.NewGeneralError(err)
}
}
roleObj, err := RoleManager.FetchByIdOrName(userCred, input.UserRoles[i].Role)
if err != nil {
if err == sql.ErrNoRows {
return nil, httperrors.NewResourceNotFoundError2(RoleManager.Keyword(), input.UserRoles[i].Role)
} else {
return nil, httperrors.NewGeneralError(err)
}
}
err = AssignmentManager.projectRemoveUser(ctx, userCred, project, userObj.(*SUser), roleObj.(*SRole))
if err != nil {
return nil, httperrors.NewGeneralError(err)
}
}
for i := range input.GroupRoles {
groupObj, err := GroupManager.FetchByIdOrName(userCred, input.GroupRoles[i].Group)
if err != nil {
if err == sql.ErrNoRows {
return nil, httperrors.NewResourceNotFoundError2(GroupManager.Keyword(), input.GroupRoles[i].Group)
} else {
return nil, httperrors.NewGeneralError(err)
}
}
roleObj, err := RoleManager.FetchByIdOrName(userCred, input.GroupRoles[i].Role)
if err != nil {
if err == sql.ErrNoRows {
return nil, httperrors.NewResourceNotFoundError2(RoleManager.Keyword(), input.GroupRoles[i].Role)
} else {
return nil, httperrors.NewGeneralError(err)
}
}
err = AssignmentManager.projectRemoveGroup(ctx, userCred, project, groupObj.(*SGroup), roleObj.(*SRole))
if err != nil {
return nil, httperrors.NewGeneralError(err)
}
}
return nil, nil
}
+131
View File
@@ -682,3 +682,134 @@ func (manager *SUserManager) FetchUsersInDomain(domainId string, excludes []stri
func (user *SUser) UnlinkIdp(idpId string) error {
return IdmappingManager.deleteAny(idpId, api.IdMappingEntityUser, user.Id)
}
func (user *SUser) AllowPerformJoin(ctx context.Context,
userCred mcclient.TokenCredential,
query jsonutils.JSONObject,
data jsonutils.JSONObject,
) bool {
return db.IsAdminAllowPerform(userCred, user, "join")
}
func (user *SUser) PerformJoin(
ctx context.Context,
userCred mcclient.TokenCredential,
query jsonutils.JSONObject,
data jsonutils.JSONObject,
) (jsonutils.JSONObject, error) {
err := joinProjects(user, true, ctx, userCred, data)
if err != nil {
return nil, err
}
return nil, nil
}
func joinProjects(ident db.IModel, isUser bool, ctx context.Context, userCred mcclient.TokenCredential, data jsonutils.JSONObject) error {
input := api.SJoinProjectsInput{}
err := data.Unmarshal(&input)
if err != nil {
return httperrors.NewInputParameterError("unmarshal input error %s", err)
}
err = input.Validate()
if err != nil {
return httperrors.NewInputParameterError(err.Error())
}
projects := make([]*SProject, 0)
roles := make([]*SRole, 0)
for i := range input.Projects {
obj, err := ProjectManager.FetchByIdOrName(userCred, input.Projects[i])
if err != nil {
if err == sql.ErrNoRows {
return httperrors.NewResourceNotFoundError2(ProjectManager.Keyword(), input.Projects[i])
} else {
return httperrors.NewGeneralError(err)
}
}
projects = append(projects, obj.(*SProject))
}
for i := range input.Roles {
obj, err := RoleManager.FetchByIdOrName(userCred, input.Roles[i])
if err != nil {
if err == sql.ErrNoRows {
return httperrors.NewResourceNotFoundError2(RoleManager.Keyword(), input.Roles[i])
} else {
return httperrors.NewGeneralError(err)
}
}
roles = append(roles, obj.(*SRole))
}
for i := range projects {
for j := range roles {
if isUser {
err = AssignmentManager.projectAddUser(ctx, userCred, projects[i], ident.(*SUser), roles[j])
} else {
err = AssignmentManager.projectAddGroup(ctx, userCred, projects[i], ident.(*SGroup), roles[j])
}
if err != nil {
return httperrors.NewGeneralError(err)
}
}
}
return nil
}
func (user *SUser) AllowPerformLeave(ctx context.Context,
userCred mcclient.TokenCredential,
query jsonutils.JSONObject,
data jsonutils.JSONObject,
) bool {
return db.IsAdminAllowPerform(userCred, user, "leave")
}
func (user *SUser) PerformLeave(
ctx context.Context,
userCred mcclient.TokenCredential,
query jsonutils.JSONObject,
data jsonutils.JSONObject,
) (jsonutils.JSONObject, error) {
err := leaveProjects(user, true, ctx, userCred, data)
if err != nil {
return nil, err
}
return nil, nil
}
func leaveProjects(ident db.IModel, isUser bool, ctx context.Context, userCred mcclient.TokenCredential, data jsonutils.JSONObject) error {
input := api.SLeaveProjectsInput{}
err := data.Unmarshal(&input)
if err != nil {
return httperrors.NewInputParameterError("unmarshal leave porject input error: %s", err)
}
for i := range input.ProjectRoles {
projObj, err := ProjectManager.FetchByIdOrName(userCred, input.ProjectRoles[i].Project)
if err != nil {
if err == sql.ErrNoRows {
return httperrors.NewResourceNotFoundError2(ProjectManager.Keyword(), input.ProjectRoles[i].Project)
} else {
return httperrors.NewGeneralError(err)
}
}
roleObj, err := RoleManager.FetchByIdOrName(userCred, input.ProjectRoles[i].Role)
if err != nil {
if err == sql.ErrNoRows {
return httperrors.NewResourceNotFoundError2(RoleManager.Keyword(), input.ProjectRoles[i].Role)
} else {
return httperrors.NewGeneralError(err)
}
}
if isUser {
err = AssignmentManager.projectRemoveUser(ctx, userCred, projObj.(*SProject), ident.(*SUser), roleObj.(*SRole))
} else {
err = AssignmentManager.projectRemoveGroup(ctx, userCred, projObj.(*SProject), ident.(*SGroup), roleObj.(*SRole))
}
if err != nil {
return httperrors.NewGeneralError(err)
}
}
return nil
}
+5
View File
@@ -33,6 +33,11 @@ var (
Groups GroupManager
)
func (this *GroupManager) GetProjects(session *mcclient.ClientSession, uid string) (*ListResult, error) {
url := fmt.Sprintf("/groups/%s/projects?admin=true", uid)
return this._list(session, url, "projects")
}
func init() {
Groups = GroupManager{NewIdentityV3Manager("group", "groups",
[]string{},
+2 -2
View File
@@ -775,6 +775,7 @@ yunion.io/x/pkg/util/regutils
yunion.io/x/pkg/util/signalutils
yunion.io/x/pkg/util/timeutils
yunion.io/x/pkg/util/sets
yunion.io/x/pkg/errors
yunion.io/x/pkg/trace
yunion.io/x/pkg/util/errors
yunion.io/x/pkg/util/netutils
@@ -784,7 +785,6 @@ yunion.io/x/pkg/tristate
yunion.io/x/pkg/util/stringutils
yunion.io/x/pkg/util/fileutils
yunion.io/x/pkg/util/osprofile
yunion.io/x/pkg/errors
yunion.io/x/pkg/gotypes
yunion.io/x/pkg/util/filterclause
yunion.io/x/pkg/util/reflectutils
@@ -800,7 +800,7 @@ yunion.io/x/pkg/util/runtime
yunion.io/x/pkg/util/clock
# yunion.io/x/s3cli v0.0.0-20190812034537-1e65a6651a3e
yunion.io/x/s3cli
# yunion.io/x/sqlchemy v0.0.0-20190813100902-cfa59aeabbfe
# yunion.io/x/sqlchemy v0.0.0-20190817082003-905772542cba
yunion.io/x/sqlchemy
# yunion.io/x/structarg v0.0.0-20190809075558-115bed041de3
yunion.io/x/structarg
+6 -1
View File
@@ -16,6 +16,7 @@ package sqlchemy
import (
"bytes"
"database/sql"
"fmt"
"reflect"
"strings"
@@ -191,7 +192,11 @@ func (us *SUpdateSession) saveUpdate(dt interface{}) (UpdateDiffs, error) {
return nil, err
}
if aCnt != 1 {
return nil, fmt.Errorf("affected rows %d != 1", aCnt)
if aCnt == 0 {
return nil, sql.ErrNoRows
} else {
return nil, fmt.Errorf("affected rows %d != 1", aCnt)
}
}
q := us.tableSpec.Query()
for k, v := range primaries {