From b533e995105d0d8552c3c49a337d51d166578313 Mon Sep 17 00:00:00 2001 From: inatchi Date: Thu, 24 Apr 2025 19:59:18 +0900 Subject: [PATCH 1/3] Fix CreateUser request format to match OneLogin API requirements --- cmd/user.go | 33 +++++++++++++++++++ onelogin/client.go | 1 + onelogin/user.go | 23 ++++++++++++++ onelogin/user_test.go | 74 +++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 131 insertions(+) diff --git a/cmd/user.go b/cmd/user.go index 55ac4c3..43301c6 100644 --- a/cmd/user.go +++ b/cmd/user.go @@ -4,6 +4,7 @@ import ( "fmt" "os" + "github.com/onelogin/onelogin-go-sdk/v4/pkg/onelogin/models" "github.com/pepabo/onecli/onelogin" "github.com/pepabo/onecli/utils" "github.com/spf13/cobra" @@ -109,10 +110,42 @@ var modifyEmailCmd = &cobra.Command{ }, } +var addCmd = &cobra.Command{ + Use: "add ", + Short: "Add a new user", + Long: `Add a new user to your OneLogin organization`, + Args: cobra.ExactArgs(3), + RunE: func(cmd *cobra.Command, args []string) error { + firstName := args[0] + lastName := args[1] + email := args[2] + + client, err := initClient() + if err != nil { + return fmt.Errorf("error initializing OneLogin client: %v", err) + } + + newUser := models.User{ + Firstname: firstName, + Lastname: lastName, + Email: email, + } + + createdUser, err := client.CreateUser(newUser) + if err != nil { + return fmt.Errorf("error creating user: %v", err) + } + + fmt.Printf("Successfully added user: %s %s with email: %s\n", createdUser.Firstname, createdUser.Lastname, createdUser.Email) + return nil + }, +} + func init() { userCmd.AddCommand(listCmd) userCmd.AddCommand(modifyCmd) modifyCmd.AddCommand(modifyEmailCmd) + userCmd.AddCommand(addCmd) listCmd.Flags().StringVarP(&output, "output", "o", "yaml", "Output format (yaml, json)") listCmd.Flags().StringVar(&queryParams.Email, "email", "", "Filter users by email") diff --git a/onelogin/client.go b/onelogin/client.go index c432977..d72f142 100644 --- a/onelogin/client.go +++ b/onelogin/client.go @@ -14,6 +14,7 @@ const ( type OneloginClient interface { GetUsers(query models.Queryable) (interface{}, error) UpdateUser(userID int, user models.User) (interface{}, error) + CreateUser(user models.User) (interface{}, error) } // Onelogin represents the Onelogin client diff --git a/onelogin/user.go b/onelogin/user.go index e5ae638..e97bf05 100644 --- a/onelogin/user.go +++ b/onelogin/user.go @@ -1,6 +1,7 @@ package onelogin import ( + "fmt" "strconv" "github.com/onelogin/onelogin-go-sdk/v4/pkg/onelogin/models" @@ -55,3 +56,25 @@ func (o *Onelogin) GetUsers(query UserQuery) ([]models.User, error) { func (o *Onelogin) UpdateUser(userID int, user models.User) (interface{}, error) { return o.client.UpdateUser(userID, user) } + +// CreateUser creates a new user in Onelogin +func (o *Onelogin) CreateUser(user models.User) (models.User, error) { + createdUserInterface, err := o.client.CreateUser(user) + if err != nil { + return models.User{}, fmt.Errorf("error creating user: %v", err) + } + + createdUserMap, ok := createdUserInterface.(map[string]interface{}) + if !ok { + return models.User{}, fmt.Errorf("error asserting created user to map[string]interface{}") + } + + createdUser := models.User{ + ID: int32(createdUserMap["id"].(float64)), + Email: createdUserMap["email"].(string), + Firstname: createdUserMap["firstname"].(string), + Lastname: createdUserMap["lastname"].(string), + } + + return createdUser, nil +} diff --git a/onelogin/user_test.go b/onelogin/user_test.go index ebf2d67..6ccb6e3 100644 --- a/onelogin/user_test.go +++ b/onelogin/user_test.go @@ -24,6 +24,11 @@ func (m *MockClient) UpdateUser(userID int, user models.User) (interface{}, erro return args.Get(0), args.Error(1) } +func (m *MockClient) CreateUser(user models.User) (interface{}, error) { + args := m.Called(user) + return args.Get(0), args.Error(1) +} + func TestGetUsers(t *testing.T) { tests := []struct { name string @@ -149,3 +154,72 @@ func TestGetUsers(t *testing.T) { }) } } + +func TestCreateUser(t *testing.T) { + tests := []struct { + name string + inputUser models.User + mockResponse interface{} + mockError error + expectedUser models.User + expectedError error + }{ + { + name: "successful user creation", + inputUser: models.User{ + Email: "newuser@example.com", + Username: "newuser", + Firstname: "New", + Lastname: "User", + }, + mockResponse: map[string]interface{}{ + "id": 3, + "email": "newuser@example.com", + "username": "newuser", + "firstname": "New", + "lastname": "User", + }, + expectedUser: models.User{ + ID: 3, + Email: "newuser@example.com", + Username: "newuser", + Firstname: "New", + Lastname: "User", + }, + }, + { + name: "error creating user", + inputUser: models.User{ + Email: "erroruser@example.com", + Username: "erroruser", + Firstname: "Error", + Lastname: "User", + }, + mockError: assert.AnError, + expectedError: assert.AnError, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + mockClient := new(MockClient) + o := &Onelogin{ + client: mockClient, + } + + mockClient.On("CreateUser", tt.inputUser).Return(tt.mockResponse, tt.mockError) + + createdUser, err := o.CreateUser(tt.inputUser) + + if tt.expectedError != nil { + assert.Error(t, err) + assert.Equal(t, tt.expectedError, err) + } else { + assert.NoError(t, err) + assert.Equal(t, tt.expectedUser, createdUser) + } + + mockClient.AssertExpectations(t) + }) + } +} From c15db9a4f1fd53c9f63a37890408501cea40ee34 Mon Sep 17 00:00:00 2001 From: inatchi Date: Thu, 24 Apr 2025 20:04:34 +0900 Subject: [PATCH 2/3] Set user status to active and last login to current time in CreateUser method --- onelogin/user.go | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/onelogin/user.go b/onelogin/user.go index e97bf05..3f83342 100644 --- a/onelogin/user.go +++ b/onelogin/user.go @@ -3,6 +3,7 @@ package onelogin import ( "fmt" "strconv" + "time" "github.com/onelogin/onelogin-go-sdk/v4/pkg/onelogin/models" "github.com/pepabo/onecli/utils" @@ -76,5 +77,11 @@ func (o *Onelogin) CreateUser(user models.User) (models.User, error) { Lastname: createdUserMap["lastname"].(string), } + // ユーザーのステータスをアクティブに設定 + createdUser.Status = 1 // 1はアクティブを示す + + // 最終ログイン日時を現在の日時に設定 + createdUser.LastLogin = time.Now() + return createdUser, nil } From 85f3183f6123f679722262c48d2c11fefaa28bbd Mon Sep 17 00:00:00 2001 From: inatchi Date: Thu, 24 Apr 2025 20:10:07 +0900 Subject: [PATCH 3/3] Add SetUserState method to activate user and update last login on creation --- onelogin/user.go | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/onelogin/user.go b/onelogin/user.go index 3f83342..4bfc003 100644 --- a/onelogin/user.go +++ b/onelogin/user.go @@ -58,6 +58,19 @@ func (o *Onelogin) UpdateUser(userID int, user models.User) (interface{}, error) return o.client.UpdateUser(userID, user) } +// SetUserState sets the user state to active and updates the last login time +func (o *Onelogin) SetUserState(userID int) error { + user := models.User{ + Status: 1, // 1はアクティブを示す + LastLogin: time.Now(), + } + _, err := o.UpdateUser(userID, user) + if err != nil { + return fmt.Errorf("error setting user state: %v", err) + } + return nil +} + // CreateUser creates a new user in Onelogin func (o *Onelogin) CreateUser(user models.User) (models.User, error) { createdUserInterface, err := o.client.CreateUser(user) @@ -77,11 +90,10 @@ func (o *Onelogin) CreateUser(user models.User) (models.User, error) { Lastname: createdUserMap["lastname"].(string), } - // ユーザーのステータスをアクティブに設定 - createdUser.Status = 1 // 1はアクティブを示す - - // 最終ログイン日時を現在の日時に設定 - createdUser.LastLogin = time.Now() + // ユーザーのステータスをアクティブに設定し、最終ログイン日時を更新 + if err := o.SetUserState(int(createdUser.ID)); err != nil { + return models.User{}, err + } return createdUser, nil }