From 23927840b14f4397fbbc5b6e78688c0e08b0839d Mon Sep 17 00:00:00 2001 From: Max Kuznetsov Date: Fri, 1 Mar 2024 17:21:05 +0300 Subject: [PATCH] Change roles to one format (#4) --- .../serviceuser-create-update-delete/main.go | 3 +- examples/transfer-role/main.go | 7 +- examples/user-create-delete/main.go | 4 +- service/roles/schemas.go | 46 +++++++++++++ service/serviceusers/requests.go | 7 +- service/serviceusers/requests_test.go | 47 ++++++------- service/serviceusers/schemas.go | 61 +++------------- service/users/requests.go | 7 +- service/users/requests_test.go | 43 ++++++------ service/users/schemas.go | 69 ++++++------------- 10 files changed, 139 insertions(+), 155 deletions(-) create mode 100644 service/roles/schemas.go diff --git a/examples/serviceuser-create-update-delete/main.go b/examples/serviceuser-create-update-delete/main.go index c8b3059..8bcd33a 100644 --- a/examples/serviceuser-create-update-delete/main.go +++ b/examples/serviceuser-create-update-delete/main.go @@ -5,6 +5,7 @@ import ( "fmt" "github.com/selectel/iam-go" + "github.com/selectel/iam-go/service/roles" "github.com/selectel/iam-go/service/serviceusers" ) @@ -43,7 +44,7 @@ func main() { Enabled: true, Name: name, Password: password, - Roles: []serviceusers.Role{{Scope: serviceusers.Account, RoleName: serviceusers.Billing}}, + Roles: []roles.Role{{Scope: roles.Account, RoleName: roles.Billing}}, }) // Handle the error. if err != nil { diff --git a/examples/transfer-role/main.go b/examples/transfer-role/main.go index d52c40e..f97e5a4 100644 --- a/examples/transfer-role/main.go +++ b/examples/transfer-role/main.go @@ -5,6 +5,7 @@ import ( "fmt" "github.com/selectel/iam-go" + "github.com/selectel/iam-go/service/roles" "github.com/selectel/iam-go/service/users" ) @@ -45,7 +46,7 @@ func main() { var chosenUser *users.User for _, user := range allUsers { for _, role := range user.Roles { - if role.RoleName == users.Billing && user.ID != "account_root" { + if role.RoleName == roles.Billing && user.ID != "account_root" { chosenUser = &user break } @@ -67,7 +68,7 @@ func main() { err = usersAPI.UnassignRoles( ctx, chosenUser.ID, - []users.Role{{Scope: users.Account, RoleName: users.Billing}}, + []roles.Role{{Scope: roles.Account, RoleName: roles.Billing}}, ) // Handle the error. @@ -83,7 +84,7 @@ func main() { err = usersAPI.AssignRoles( ctx, userID, - []users.Role{{Scope: users.Account, RoleName: users.Billing}}, + []roles.Role{{Scope: roles.Account, RoleName: roles.Billing}}, ) // Handle the error. diff --git a/examples/user-create-delete/main.go b/examples/user-create-delete/main.go index 4c6bb6e..253fd2c 100644 --- a/examples/user-create-delete/main.go +++ b/examples/user-create-delete/main.go @@ -5,6 +5,7 @@ import ( "fmt" "github.com/selectel/iam-go" + "github.com/selectel/iam-go/service/roles" "github.com/selectel/iam-go/service/users" ) @@ -23,7 +24,6 @@ func main() { iam.WithAuthOpts(&iam.AuthOpts{KeystoneToken: token}), iam.WithUserAgentPrefix(prefix), ) - // Handle the error. if err != nil { fmt.Println(err) @@ -41,7 +41,7 @@ func main() { AuthType: users.Local, Email: email, Federation: nil, - Roles: []users.Role{{Scope: users.Account, RoleName: users.Billing}}, + Roles: []roles.Role{{Scope: roles.Account, RoleName: roles.Billing}}, }) // Handle the error. if err != nil { diff --git a/service/roles/schemas.go b/service/roles/schemas.go new file mode 100644 index 0000000..a67c56c --- /dev/null +++ b/service/roles/schemas.go @@ -0,0 +1,46 @@ +package roles + +// Name represents a role, which can be assigned to a user or a service user. +// For additional information, see +// https://docs.selectel.ru/control-panel-actions/users-and-roles/user-types-and-roles/#user-roles. +type Name string + +const ( + // Account owner. + AccountOwner Name = "account_owner" + + // User administrator. + IAMAdmin Name = "iam_admin" + + // Account/Project administrator. + Member Name = "member" + + // Account/Project reader. + Reader Name = "reader" + + // Billing administrator. + Billing Name = "billing" + + // Object storage administrator. Can be assigned only to a service user. + ObjectStorageAdmin Name = "object_storage:admin" + + // Object storage user. Can be assigned only to a service user. + ObjectStorageUser Name = "object_storage_user" +) + +// Scope represents a scope of a role. +type Scope string + +const ( + // Project scope. + Project Scope = "project" + + // Account scope. + Account Scope = "account" +) + +type Role struct { + ProjectID string `json:"project_id,omitempty"` + RoleName Name `json:"role_name"` + Scope Scope `json:"scope"` +} diff --git a/service/serviceusers/requests.go b/service/serviceusers/requests.go index 2da6735..ccdaa75 100644 --- a/service/serviceusers/requests.go +++ b/service/serviceusers/requests.go @@ -9,6 +9,7 @@ import ( "github.com/selectel/iam-go/iamerrors" "github.com/selectel/iam-go/internal/client" + "github.com/selectel/iam-go/service/roles" ) const apiVersion = "iam/v1" @@ -187,7 +188,7 @@ func (su *ServiceUsers) Update(ctx context.Context, userID string, input UpdateR } // AssignRoles adds new roles for a Service User with the given userID. -func (su *ServiceUsers) AssignRoles(ctx context.Context, userID string, roles []Role) error { +func (su *ServiceUsers) AssignRoles(ctx context.Context, userID string, roles []roles.Role) error { if userID == "" { return iamerrors.Error{Err: iamerrors.ErrUserIDRequired, Desc: "No userID was provided."} } @@ -202,7 +203,7 @@ func (su *ServiceUsers) AssignRoles(ctx context.Context, userID string, roles [] } // UnassignRoles removes roles from a Service User with the given userID. -func (su *ServiceUsers) UnassignRoles(ctx context.Context, userID string, roles []Role) error { +func (su *ServiceUsers) UnassignRoles(ctx context.Context, userID string, roles []roles.Role) error { if userID == "" { return iamerrors.Error{Err: iamerrors.ErrUserIDRequired, Desc: "No userID was provided."} } @@ -216,7 +217,7 @@ func (su *ServiceUsers) UnassignRoles(ctx context.Context, userID string, roles return su.manageRoles(ctx, http.MethodDelete, userID, roles) } -func (su *ServiceUsers) manageRoles(ctx context.Context, method string, userID string, roles []Role) error { +func (su *ServiceUsers) manageRoles(ctx context.Context, method string, userID string, roles []roles.Role) error { path, err := url.JoinPath(apiVersion, "service_users", userID, "roles") if err != nil { return iamerrors.Error{Err: iamerrors.ErrInternalAppError, Desc: err.Error()} diff --git a/service/serviceusers/requests_test.go b/service/serviceusers/requests_test.go index f0d0d7a..ba77539 100644 --- a/service/serviceusers/requests_test.go +++ b/service/serviceusers/requests_test.go @@ -11,6 +11,7 @@ import ( "github.com/selectel/iam-go/iamerrors" "github.com/selectel/iam-go/internal/client" + "github.com/selectel/iam-go/service/roles" "github.com/selectel/iam-go/service/serviceusers/testdata" ) @@ -41,8 +42,8 @@ func TestList(t *testing.T) { Name: "test", Enabled: true, ID: "123", - Roles: []Role{ - {Scope: Account, RoleName: Member}, + Roles: []roles.Role{ + {Scope: roles.Account, RoleName: roles.Member}, }, }, }, @@ -115,8 +116,8 @@ func TestGet(t *testing.T) { Name: "test", Enabled: true, ID: "123", - Roles: []Role{ - {Scope: Account, RoleName: Member}, + Roles: []roles.Role{ + {Scope: roles.Account, RoleName: roles.Member}, }, }, expectedError: nil, @@ -235,7 +236,7 @@ func TestCreate(t *testing.T) { enabled bool name string password string - roles []Role + roles []roles.Role } tests := []struct { name string @@ -250,8 +251,8 @@ func TestCreate(t *testing.T) { enabled: true, name: "test", password: "Qazwsxedc123", - roles: []Role{ - {Scope: Account, RoleName: Member}, + roles: []roles.Role{ + {Scope: roles.Account, RoleName: roles.Member}, }, }, prepare: func() { @@ -265,8 +266,8 @@ func TestCreate(t *testing.T) { Name: "test", Enabled: true, ID: "123", - Roles: []Role{ - {Scope: Account, RoleName: Member}, + Roles: []roles.Role{ + {Scope: roles.Account, RoleName: roles.Member}, }, }, expectedError: nil, @@ -277,8 +278,8 @@ func TestCreate(t *testing.T) { enabled: true, name: "test", password: "123", - roles: []Role{ - {Scope: Account, RoleName: Member}, + roles: []roles.Role{ + {Scope: roles.Account, RoleName: roles.Member}, }, }, prepare: func() { @@ -300,8 +301,8 @@ func TestCreate(t *testing.T) { enabled: true, name: "test", password: "123", - roles: []Role{ - {Scope: Account, RoleName: Member}, + roles: []roles.Role{ + {Scope: roles.Account, RoleName: roles.Member}, }, }, prepare: func() { @@ -434,7 +435,7 @@ func TestUpdate(t *testing.T) { func TestAssignRoles(t *testing.T) { type args struct { userID string - roles []Role + roles []roles.Role } tests := []struct { name string @@ -446,8 +447,8 @@ func TestAssignRoles(t *testing.T) { name: "Test AssignRoles return output", args: args{ userID: "123", - roles: []Role{ - {Scope: Account, RoleName: Member}, + roles: []roles.Role{ + {Scope: roles.Account, RoleName: roles.Member}, }, }, prepare: func() { @@ -464,8 +465,8 @@ func TestAssignRoles(t *testing.T) { name: "Test AssignRoles return error", args: args{ userID: "123", - roles: []Role{ - {Scope: Account, RoleName: Member}, + roles: []roles.Role{ + {Scope: roles.Account, RoleName: roles.Member}, }, }, prepare: func() { @@ -506,7 +507,7 @@ func TestAssignRoles(t *testing.T) { func TestUnassignRoles(t *testing.T) { type args struct { userID string - roles []Role + roles []roles.Role } tests := []struct { name string @@ -518,8 +519,8 @@ func TestUnassignRoles(t *testing.T) { name: "Test UnassignRoles return output", args: args{ userID: "123", - roles: []Role{ - {Scope: Account, RoleName: Member}, + roles: []roles.Role{ + {Scope: roles.Account, RoleName: roles.Member}, }, }, prepare: func() { @@ -536,8 +537,8 @@ func TestUnassignRoles(t *testing.T) { name: "Test UnassignRoles return error", args: args{ userID: "123", - roles: []Role{ - {Scope: Account, RoleName: Member}, + roles: []roles.Role{ + {Scope: roles.Account, RoleName: roles.Member}, }, }, prepare: func() { diff --git a/service/serviceusers/schemas.go b/service/serviceusers/schemas.go index 092c49d..5b297c5 100644 --- a/service/serviceusers/schemas.go +++ b/service/serviceusers/schemas.go @@ -1,52 +1,13 @@ package serviceusers -type RoleName string - -const ( - // Account owner. - AccountOwner RoleName = "account_owner" - - // User administrator. - IAMAdmin RoleName = "iam_admin" - - // Account/Project administrator. - Member RoleName = "member" - - // Account/Project reader. - Reader RoleName = "reader" - - // Billing administrator. - Billing RoleName = "billing" - - // Object storage administrator. - ObjectStorageAdmin RoleName = "object_storage:admin" - - // Object storage user. - ObjectStorageUser RoleName = "object_storage_user" -) - -type Scope string - -const ( - // Project scope. - Project Scope = "project" - - // Account scope. - Account Scope = "account" -) +import "github.com/selectel/iam-go/service/roles" // ServiceUser represents a Selectel Service User. type ServiceUser struct { - ID string `json:"id"` - Enabled bool `json:"enabled"` - Name string `json:"name"` - Roles []Role `json:"roles"` -} - -type Role struct { - ProjectID string `json:"project_id,omitempty"` - RoleName RoleName `json:"role_name"` - Scope Scope `json:"scope"` + ID string `json:"id"` + Enabled bool `json:"enabled"` + Name string `json:"name"` + Roles []roles.Role `json:"roles"` } // CreateRequest is used to set options for Create method. @@ -54,7 +15,7 @@ type CreateRequest struct { Enabled bool Name string Password string - Roles []Role + Roles []roles.Role } // UpdateRequest is used to set options for Update method. @@ -65,10 +26,10 @@ type UpdateRequest struct { } type createRequest struct { - Enabled bool `json:"enabled,omitempty"` - Name string `json:"name,omitempty"` - Password string `json:"password,omitempty"` - Roles []Role `json:"roles,omitempty"` + Enabled bool `json:"enabled,omitempty"` + Name string `json:"name,omitempty"` + Password string `json:"password,omitempty"` + Roles []roles.Role `json:"roles,omitempty"` } type updateRequest struct { @@ -78,7 +39,7 @@ type updateRequest struct { } type manageRolesRequest struct { - Roles []Role `json:"roles"` + Roles []roles.Role `json:"roles"` } type listResponse struct { diff --git a/service/users/requests.go b/service/users/requests.go index a696571..7c6420a 100644 --- a/service/users/requests.go +++ b/service/users/requests.go @@ -9,6 +9,7 @@ import ( "github.com/selectel/iam-go/iamerrors" "github.com/selectel/iam-go/internal/client" + "github.com/selectel/iam-go/service/roles" ) const apiVersion = "iam/v1" @@ -169,7 +170,7 @@ func (u *Users) ResendInvite(ctx context.Context, userID string) error { } // AssignRoles adds new roles for a User with the given userID. -func (u *Users) AssignRoles(ctx context.Context, userID string, roles []Role) error { +func (u *Users) AssignRoles(ctx context.Context, userID string, roles []roles.Role) error { if userID == "" { return iamerrors.Error{Err: iamerrors.ErrUserIDRequired, Desc: "No userID was provided."} } @@ -182,7 +183,7 @@ func (u *Users) AssignRoles(ctx context.Context, userID string, roles []Role) er } // UnassignRoles removes roles from a User with the given userID. -func (u *Users) UnassignRoles(ctx context.Context, userID string, roles []Role) error { +func (u *Users) UnassignRoles(ctx context.Context, userID string, roles []roles.Role) error { if userID == "" { return iamerrors.Error{Err: iamerrors.ErrUserIDRequired, Desc: "No userID was provided."} } @@ -193,7 +194,7 @@ func (u *Users) UnassignRoles(ctx context.Context, userID string, roles []Role) return u.manageRoles(ctx, http.MethodDelete, userID, roles) } -func (u *Users) manageRoles(ctx context.Context, method string, userID string, roles []Role) error { +func (u *Users) manageRoles(ctx context.Context, method string, userID string, roles []roles.Role) error { path, err := url.JoinPath(apiVersion, "users", userID, "roles") if err != nil { return iamerrors.Error{Err: iamerrors.ErrInternalAppError, Desc: err.Error()} diff --git a/service/users/requests_test.go b/service/users/requests_test.go index fcf1130..966a4a5 100644 --- a/service/users/requests_test.go +++ b/service/users/requests_test.go @@ -11,6 +11,7 @@ import ( "github.com/selectel/iam-go/iamerrors" "github.com/selectel/iam-go/internal/client" + "github.com/selectel/iam-go/service/roles" "github.com/selectel/iam-go/service/users/testdata" ) @@ -42,8 +43,8 @@ func TestList(t *testing.T) { AuthType: "local", KeystoneID: "123", ID: "123", - Roles: []Role{ - {Scope: Account, RoleName: Member}, + Roles: []roles.Role{ + {Scope: roles.Account, RoleName: roles.Member}, }, }, }, @@ -116,8 +117,8 @@ func TestGet(t *testing.T) { AuthType: "local", KeystoneID: "123", ID: "123", - Roles: []Role{ - {Scope: Account, RoleName: Member}, + Roles: []roles.Role{ + {Scope: roles.Account, RoleName: roles.Member}, }, }, expectedError: nil, @@ -233,7 +234,7 @@ func TestCreate(t *testing.T) { authType AuthType email string federation Federation - roles []Role + roles []roles.Role } tests := []struct { name string @@ -251,8 +252,8 @@ func TestCreate(t *testing.T) { ExternalID: "123", ID: "123", }, - roles: []Role{ - {Scope: Account, RoleName: Member}, + roles: []roles.Role{ + {Scope: roles.Account, RoleName: roles.Member}, }, }, prepare: func() { @@ -270,8 +271,8 @@ func TestCreate(t *testing.T) { }, ID: "123", KeystoneID: "123", - Roles: []Role{ - {Scope: Account, RoleName: Member}, + Roles: []roles.Role{ + {Scope: roles.Account, RoleName: roles.Member}, }, }, expectedError: nil, @@ -285,8 +286,8 @@ func TestCreate(t *testing.T) { ExternalID: "123", ID: "123", }, - roles: []Role{ - {Scope: Account, RoleName: Member}, + roles: []roles.Role{ + {Scope: roles.Account, RoleName: roles.Member}, }, }, prepare: func() { @@ -397,7 +398,7 @@ func TestResendInvite(t *testing.T) { func TestAssignRoles(t *testing.T) { type args struct { userID string - roles []Role + roles []roles.Role } tests := []struct { name string @@ -409,8 +410,8 @@ func TestAssignRoles(t *testing.T) { name: "Test AssignRoles return output", args: args{ userID: "123", - roles: []Role{ - {Scope: Account, RoleName: Member}, + roles: []roles.Role{ + {Scope: roles.Account, RoleName: roles.Member}, }, }, prepare: func() { @@ -426,8 +427,8 @@ func TestAssignRoles(t *testing.T) { name: "Test AssignRoles return error", args: args{ userID: "123", - roles: []Role{ - {Scope: Account, RoleName: Member}, + roles: []roles.Role{ + {Scope: roles.Account, RoleName: roles.Member}, }, }, prepare: func() { @@ -467,7 +468,7 @@ func TestAssignRoles(t *testing.T) { func TestUnassignRoles(t *testing.T) { type args struct { userID string - roles []Role + roles []roles.Role } tests := []struct { name string @@ -479,8 +480,8 @@ func TestUnassignRoles(t *testing.T) { name: "Test UnassignRoles return output", args: args{ userID: "123", - roles: []Role{ - {Scope: Account, RoleName: Member}, + roles: []roles.Role{ + {Scope: roles.Account, RoleName: roles.Member}, }, }, prepare: func() { @@ -496,8 +497,8 @@ func TestUnassignRoles(t *testing.T) { name: "Test UnassignRoles return error", args: args{ userID: "123", - roles: []Role{ - {Scope: Account, RoleName: Member}, + roles: []roles.Role{ + {Scope: roles.Account, RoleName: roles.Member}, }, }, prepare: func() { diff --git a/service/users/schemas.go b/service/users/schemas.go index 3f44782..007d14b 100644 --- a/service/users/schemas.go +++ b/service/users/schemas.go @@ -1,48 +1,25 @@ package users -type AuthType string - -const ( - Local AuthType = "local" - Federated AuthType = "federated" -) - -type RoleName string - -const ( - // Account owner. - AccountOwner RoleName = "account_owner" - - // User administrator. - IAMAdmin RoleName = "iam_admin" +import "github.com/selectel/iam-go/service/roles" - // Account/Project administrator. - Member RoleName = "member" - - // Account/Project reader. - Reader RoleName = "reader" - - // Billing administrator. - Billing RoleName = "billing" -) - -type Scope string +// AuthType represents a type of authentication of a User. +type AuthType string const ( - // Project scope. - Project Scope = "project" + // Local authentication. Set by default. + Local AuthType = "local" - // Account scope. - Account Scope = "account" + // Federated authentication. If set, the `federation` field is also has to be specified. + Federated AuthType = "federated" ) // User represents a Selectel Panel User. type User struct { - AuthType AuthType `json:"auth_type"` - Federation *Federation `json:"federation,omitempty"` - Roles []Role `json:"roles"` - ID string `json:"id"` - KeystoneID string `json:"keystone_id"` + AuthType AuthType `json:"auth_type"` + Federation *Federation `json:"federation,omitempty"` + Roles []roles.Role `json:"roles"` + ID string `json:"id"` + KeystoneID string `json:"keystone_id"` } type Federation struct { @@ -50,31 +27,25 @@ type Federation struct { ID string `json:"id"` } -type Role struct { - ProjectID string `json:"project_id,omitempty"` - RoleName RoleName `json:"role_name"` - Scope Scope `json:"scope"` -} - // CreateRequest is used to set options for Create method. type CreateRequest struct { AuthType AuthType Email string Federation *Federation - Roles []Role + Roles []roles.Role } type createRequest struct { - AuthType AuthType `json:"auth_type,omitempty"` - Email string `json:"email,omitempty"` - Federation *Federation `json:"federation,omitempty"` - Roles []Role `json:"roles,omitempty"` - SubscriptionsOnly bool `json:"subscriptions_only"` // Issue, should be hardcoded to `false` - Subscriptions []string `json:"subscriptions"` // Issue, should be hardcoded to `[]` + AuthType AuthType `json:"auth_type,omitempty"` + Email string `json:"email,omitempty"` + Federation *Federation `json:"federation,omitempty"` + Roles []roles.Role `json:"roles,omitempty"` + SubscriptionsOnly bool `json:"subscriptions_only"` // Issue, should be hardcoded to `false` + Subscriptions []string `json:"subscriptions"` // Issue, should be hardcoded to `[]` } type manageRolesRequest struct { - Roles []Role `json:"roles"` + Roles []roles.Role `json:"roles"` } type listResponse struct {