Skip to content

Commit

Permalink
import: create or merge user, wip
Browse files Browse the repository at this point in the history
  • Loading branch information
wilsonehusin committed May 1, 2024
1 parent 3a0a78d commit 53cb647
Show file tree
Hide file tree
Showing 4 changed files with 82 additions and 26 deletions.
84 changes: 58 additions & 26 deletions cmd/import.go
Original file line number Diff line number Diff line change
Expand Up @@ -264,39 +264,71 @@ func importUsers(ctx context.Context, provider pager.Pager, fh *firehydrant.Clie
return fmt.Errorf("unable to match users to FireHydrant: %w", err)
}

// Manually link users which do not have matching email addresses
// Find out which users should be pre-created in FireHydrant via SCIM
unmatched, err := store.UseQueries(ctx).ListUnmatchedExtUsers(ctx)
if err != nil {
return fmt.Errorf("unable to list unmatched users: %w", err)
}
if len(unmatched) > 0 {
console.Warnf("Please match the following users to their FireHydrant account.\n")
fhUsers, err := fh.ListUsers(ctx)
if err != nil {
return fmt.Errorf("unable to list FireHydrant users: %w", err)
if len(unmatched) == 0 {
console.Successf("All users are already matched to FireHydrant.\n")
return nil
}

// Get padding number to pretty print the information in table-like view.
idPad := console.PadStrings(unmatched, func(u store.ExtUser) int { return len(u.ID) })
emailPad := console.PadStrings(unmatched, func(u store.ExtUser) int { return len(u.Email) })

importOpts := []store.ExtUser{{ID: "[+] IMPORT ALL"}, {ID: "[<] SKIP ALL"}}
importOpts = append(importOpts, unmatched...)
selected, toImport, err := console.MultiSelectf(importOpts, func(u store.ExtUser) string {
return fmt.Sprintf("%*s %-*s %s", idPad, u.ID, emailPad, u.Email, u.Name)
}, "These users do not have a FireHydrant account. Which users should be created / merged in FireHydrant?")
if err != nil {
return fmt.Errorf("selecting users to import: %w", err)
}
switch selected[0] {
case 0:
console.Successf("[+] All users will be created in FireHydrant.\n")
case 1:
console.Warnf("[<] No users will be created in FireHydrant.\n")
if err := store.UseQueries(ctx).DeleteUnmatchedExtUsers(ctx); err != nil {
return fmt.Errorf("unable to delete unmatched users: %w", err)
}
options := []store.FhUser{{Name: "[<] SKIP"}}
options = append(options, fhUsers...)
return nil
default:
console.Warnf("Selected %d users to be imported to FireHydrant.\n", len(toImport))
}

for _, u := range unmatched {
selected, fhUser, err := console.Selectf(options, func(u store.FhUser) string {
return fmt.Sprintf("%s %s", u.Name, u.Email)
}, fmt.Sprintf("Which FireHydrant user should '%s' be imported to?", u.Name))
if err != nil {
return fmt.Errorf("selecting FireHydrant user for '%s': %w", u.Name, err)
}
if selected == 0 {
console.Infof("[<] User '%s' will not be imported to FireHydrant.\n", u.Name)
continue
}
if err := store.UseQueries(ctx).LinkExtUser(ctx, store.LinkExtUserParams{
ID: u.ID,
FhUserID: sql.NullString{String: fhUser.ID, Valid: true},
}); err != nil {
return fmt.Errorf("linking user '%s': %w", u.Name, err)
}
console.Successf("[=] User '%s' linked to FireHydrant user '%s'.\n", u.Email, fhUser.Email)
// We now ask if all of them are to be created as new users, or if they should be matched to existing FireHydrant users.
console.Warnf("Please match the following users to a FireHydrant account.\n")
fhUsers, err := fh.ListUsers(ctx)
if err != nil {
return fmt.Errorf("unable to list FireHydrant users: %w", err)
}

namePad := console.PadStrings(fhUsers, func(u store.FhUser) int { return len(u.Name) })

matchOpts := []store.FhUser{{Name: "[+] CREATE NEW"}}
matchOpts = append(matchOpts, fhUsers...)
for _, u := range unmatched {
selected, fhUser, err := console.Selectf(matchOpts, func(u store.FhUser) string {
return fmt.Sprintf("%*s %s", namePad, u.Name, u.Email)
}, fmt.Sprintf("Which FireHydrant user should '%s' be imported to?", u.Name))
if err != nil {
return fmt.Errorf("selecting FireHydrant user for '%s': %w", u.Name, err)
}
if selected == 0 {
console.Infof("[+] User '%s (%s)' will be created in FireHydrant.\n", u.Name, u.Email)
// TODO: Create user in FireHydrant, then link below
continue
}
if err := store.UseQueries(ctx).LinkExtUser(ctx, store.LinkExtUserParams{
ID: u.ID,
FhUserID: sql.NullString{String: fhUser.ID, Valid: true},
}); err != nil {
return fmt.Errorf("linking user '%s': %w", u.Name, err)
}
console.Successf("[=] User '%s' linked to FireHydrant user '%s'.\n", u.Email, fhUser.Email)
}
return nil
}
10 changes: 10 additions & 0 deletions console/print.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,13 @@ var (
Errorf = color.New(color.FgHiRed).Add(color.Underline).PrintfFunc()
Warnf = color.New(color.FgHiYellow).Add(color.Bold).PrintfFunc()
)

func PadStrings[T any](elems []T, intFn func(T) int) int {
max := 0
for _, elem := range elems {
if l := intFn(elem); l > max {
max = l
}
}
return max
}
4 changes: 4 additions & 0 deletions store/queries.sql
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,10 @@ SELECT * FROM ext_users;
SELECT * FROM ext_users
WHERE fh_user_id IS NULL;

-- name: DeleteUnmatchedExtUsers :exec
DELETE FROM ext_users
WHERE fh_user_id IS NULL;

-- name: InsertExtUser :exec
INSERT INTO ext_users (id, name, email, fh_user_id) VALUES (?, ?, ?, ?);

Expand Down
10 changes: 10 additions & 0 deletions store/queries.sql.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 53cb647

Please sign in to comment.