Skip to content

Commit

Permalink
Feat: Support local password for users (#145)
Browse files Browse the repository at this point in the history
## What

## Why

## Notes
to unset password at least version `21.253.9` of cf-api is required 

## Checklist

* [ ] _I have read
[CONTRIBUTING.md](https://github.com/codefresh-io/terraform-provider-codefresh/blob/master/CONTRIBUTING.md)._
* [ ] _I have [allowed changes to my fork to be
made](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/working-with-forks/allowing-changes-to-a-pull-request-branch-created-from-a-fork)._
* [ ] _I have added tests, assuming new tests are warranted_.
* [ ] _I understand that the `/test` comment will be ignored by the CI
trigger [unless it is made by a repo admin or
collaborator](https://codefresh.io/docs/docs/pipelines/triggers/git-triggers/#support-for-building-pull-requests-from-forks)._
  • Loading branch information
ilia-medvedev-codefresh authored May 21, 2024
1 parent 1877a9d commit 55e3ef2
Show file tree
Hide file tree
Showing 3 changed files with 103 additions and 2 deletions.
44 changes: 44 additions & 0 deletions codefresh/cfclient/user.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@ type ShortProfile struct {
UserName string `json:"userName,omitempty"`
}

type PublicProfile struct {
HasPassword bool `json:"hasPassword,omitempty"`
}

type Personal struct {
FirstName string `json:"firstName,omitempty"`
LastName string `json:"lastName,omitempty"`
Expand All @@ -44,6 +48,7 @@ type User struct {
HasPassword bool `json:"hasPassword,omitempty"`
Notifications []NotificationEvent `json:"notifications,omitempty"`
ShortProfile ShortProfile `json:"shortProfile,omitempty"`
PublicProfile PublicProfile `json:"publicProfile,omitempty"`
Logins []Login `json:"logins,omitempty"`
InviteURL string `json:"inviteUrl,omitempty"`
}
Expand Down Expand Up @@ -368,3 +373,42 @@ func (client *Client) UpdateUserDetails(accountId, userId, userName, userEmail s

return &respUser, nil
}

func (client *Client) UpdateLocalUserPassword(userName, password string) (error) {

fullPath := "/admin/user/localProvider"

requestBody := fmt.Sprintf(`{"userName": "%s","password": "%s"}`, userName, password)

opts := RequestOptions{
Path: fullPath,
Method: "POST",
Body: []byte(requestBody),
}

_, err := client.RequestAPI(&opts)

if err != nil {
return err
}

return nil
}

func (client *Client) DeleteLocalUserPassword(userName string) (error) {

fullPath := fmt.Sprintf("/admin/user/localProvider?userName=%s", userName)

opts := RequestOptions{
Path: fullPath,
Method: "DELETE",
}

_, err := client.RequestAPI(&opts)

if err != nil {
return err
}

return nil
}
59 changes: 57 additions & 2 deletions codefresh/resource_user.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package codefresh

import (
"errors"
"log"

"github.com/codefresh-io/terraform-provider-codefresh/codefresh/cfclient"
Expand All @@ -24,6 +25,17 @@ func resourceUser() *schema.Resource {
Type: schema.TypeString,
Required: true,
},
"password": {
Description: "Password - for users without SSO.",
Type: schema.TypeString,
Optional: true,
Sensitive: true,
},
"has_password" : {
Description: "Whether the user has a local password.",
Type: schema.TypeBool,
Computed: true,
},
"email": {
Description: "The email of the user.",
Type: schema.TypeString,
Expand Down Expand Up @@ -148,7 +160,11 @@ func resourceUsersCreate(d *schema.ResourceData, meta interface{}) error {
client.ActivateUser(d.Id())
}

return nil
if d.Get("password") != "" {
client.UpdateLocalUserPassword(d.Get("user_name").(string), d.Get("password").(string))
}

return resourceUsersRead(d, meta)
}

func resourceUsersRead(d *schema.ResourceData, meta interface{}) error {
Expand Down Expand Up @@ -198,7 +214,15 @@ func resourceUsersUpdate(d *schema.ResourceData, meta interface{}) error {
for _, account := range *accounts {
_ = client.AddUserToTeamByAdmin(userId, account.ID, "users")
}
return nil

// Update local password
err = updateUserLocalPassword(d, client)

if err != nil {
return err
}

return resourceUsersRead(d, meta)
}

func resourceUsersDelete(d *schema.ResourceData, meta interface{}) error {
Expand Down Expand Up @@ -231,6 +255,7 @@ func mapUserToResource(user cfclient.User, d *schema.ResourceData) error {
[]map[string]interface{}{
{"user_name": user.ShortProfile.UserName},
})
d.Set("has_password", user.PublicProfile.HasPassword)
d.Set("roles", user.Roles)
d.Set("login", flattenUserLogins(&user.Logins))

Expand Down Expand Up @@ -325,3 +350,33 @@ func mapResourceToNewUser(d *schema.ResourceData) *cfclient.NewUser {

return user
}

func updateUserLocalPassword(d *schema.ResourceData, client *cfclient.Client) error {

if (d.HasChange("password")) {
hasPassword := d.Get("has_password").(bool)

if _, ok := d.GetOk("user_name"); !ok {
return errors.New("cannot update password as username attribute is not set")
}

userName := d.Get("user_name").(string)

if password := d.Get("password"); password != "" {
err := client.UpdateLocalUserPassword(userName, password.(string))

if err != nil {
return err
}
// If password is not set but has_password returns true, it means that it was removed
} else if hasPassword {
err := client.DeleteLocalUserPassword(userName)

if err != nil {
return err
}
}
}

return nil
}
2 changes: 2 additions & 0 deletions docs/resources/user.md
Original file line number Diff line number Diff line change
Expand Up @@ -75,11 +75,13 @@ resource "codefresh_user" "new" {

- `activate` (Boolean) Whether to activate the user or to leave it as `pending`.
- `login` (Block Set) Login settings for the user. (see [below for nested schema](#nestedblock--login))
- `password` (String, Sensitive) Password - for users without SSO.
- `personal` (Block List, Max: 1) Personal information about the user. (see [below for nested schema](#nestedblock--personal))
- `roles` (Set of String) The roles of the user.

### Read-Only

- `has_password` (Boolean) Whether the user has a local password.
- `id` (String) The ID of this resource.
- `short_profile` (List of Object) The computed short profile of the user. (see [below for nested schema](#nestedatt--short_profile))
- `status` (String) The status of the user (e.g. `new`, `pending`).
Expand Down

0 comments on commit 55e3ef2

Please sign in to comment.