Skip to content

Commit

Permalink
feat: eng-441-auth-migration-des-scopes-des-clients-actuelle (#1079)
Browse files Browse the repository at this point in the history
Co-authored-by: David Ragot <[email protected]>
  • Loading branch information
Dav-14 and David Ragot authored Dec 23, 2023
1 parent 0c271f0 commit 5aac996
Show file tree
Hide file tree
Showing 12 changed files with 156 additions and 36 deletions.
19 changes: 13 additions & 6 deletions components/fctl/cmd/auth/clients/create.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,13 @@ import (
)

type CreateClient struct {
ID string `json:"id"`
Name string `json:"name"`
Description string `json:"description"`
IsPublic string `json:"isPublic"`
RedirectUri string `json:"redirectUri"`
PostLogoutRedirectUri string `json:"postLogoutRedirectUri"`
ID string `json:"id"`
Name string `json:"name"`
Description string `json:"description"`
IsPublic string `json:"isPublic"`
RedirectUri string `json:"redirectUri"`
PostLogoutRedirectUri string `json:"postLogoutRedirectUri"`
Scopes []string `json:"scopes"`
}

type CreateStore struct {
Expand All @@ -29,6 +30,7 @@ type CreateController struct {
descriptionFlag string
redirectUriFlag string
postLogoutRedirectUriFlag string
scopes string
}

var _ fctl.Controller[*CreateStore] = (*CreateController)(nil)
Expand All @@ -45,6 +47,7 @@ func NewCreateController() *CreateController {
descriptionFlag: "description",
redirectUriFlag: "redirect-uri",
postLogoutRedirectUriFlag: "post-logout-redirect-uri",
scopes: "scopes",
}
}

Expand All @@ -59,6 +62,7 @@ func NewCreateCommand() *cobra.Command {
fctl.WithStringFlag(c.descriptionFlag, "", "Client description"),
fctl.WithStringSliceFlag(c.redirectUriFlag, []string{}, "Redirect URIS"),
fctl.WithStringSliceFlag(c.postLogoutRedirectUriFlag, []string{}, "Post logout redirect uris"),
fctl.WithStringSliceFlag(c.scopes, []string{""}, "Scopes"),
fctl.WithShortDescription("Create client"),
fctl.WithController[*CreateStore](c),
)
Expand Down Expand Up @@ -104,6 +108,7 @@ func (c *CreateController) Run(cmd *cobra.Command, args []string) (fctl.Renderab
Name: args[0],
Trusted: &trusted,
PostLogoutRedirectUris: fctl.GetStringSlice(cmd, c.postLogoutRedirectUriFlag),
Scopes: fctl.GetStringSlice(cmd, c.scopes),
}
response, err := authClient.Auth.CreateClient(cmd.Context(), &request)
if err != nil {
Expand All @@ -121,6 +126,7 @@ func (c *CreateController) Run(cmd *cobra.Command, args []string) (fctl.Renderab
IsPublic: fctl.BoolPointerToString(response.CreateClientResponse.Data.Public),
RedirectUri: strings.Join(response.CreateClientResponse.Data.RedirectUris, ","),
PostLogoutRedirectUri: strings.Join(response.CreateClientResponse.Data.PostLogoutRedirectUris, ","),
Scopes: response.CreateClientResponse.Data.Scopes,
}

return c, nil
Expand All @@ -134,6 +140,7 @@ func (c *CreateController) Render(cmd *cobra.Command, args []string) error {
tableData = append(tableData, []string{pterm.LightCyan("Public"), c.store.Client.IsPublic})
tableData = append(tableData, []string{pterm.LightCyan("Redirect URIs"), c.store.Client.RedirectUri})
tableData = append(tableData, []string{pterm.LightCyan("Post logout redirect URIs"), c.store.Client.PostLogoutRedirectUri})
tableData = append(tableData, []string{pterm.LightCyan("Scopes"), strings.Join(c.store.Client.Scopes, " ")})
return pterm.DefaultTable.
WithWriter(cmd.OutOrStdout()).
WithData(tableData).
Expand Down
17 changes: 8 additions & 9 deletions components/fctl/cmd/auth/clients/list.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package clients

import (
"fmt"
"strings"

fctl "github.com/formancehq/fctl/pkg"
"github.com/formancehq/formance-sdk-go/pkg/models/shared"
Expand All @@ -11,11 +10,11 @@ import (
)

type Client struct {
ID string `json:"id"`
Name string `json:"name"`
Description string `json:"description"`
Scope string `json:"scope"`
IsPublic string `json:"isPublic"`
ID string `json:"id"`
Name string `json:"name"`
Description string `json:"description"`
IsPublic string `json:"isPublic"`
Scopes []string `json:"scopes"`
}

type ListStore struct {
Expand Down Expand Up @@ -90,7 +89,7 @@ func (c *ListController) Run(cmd *cobra.Command, args []string) (fctl.Renderable
}
return ""
}(),
Scope: strings.Join(o.Scopes, ","),
Scopes: o.Scopes,
IsPublic: fctl.BoolPointerToString(o.Public),
}
})
Expand All @@ -104,12 +103,12 @@ func (c *ListController) Render(cmd *cobra.Command, args []string) error {
o.ID,
o.Name,
o.Description,
o.Scope,
o.IsPublic,
fmt.Sprintf("%d", len(o.Scopes)),
}
})

tableData = fctl.Prepend(tableData, []string{"ID", "Name", "Description", "Scopes", "Public"})
tableData = fctl.Prepend(tableData, []string{"ID", "Name", "Description", "Public", "Permissions"})
return pterm.DefaultTable.
WithHasHeader().
WithWriter(cmd.OutOrStdout()).
Expand Down
19 changes: 13 additions & 6 deletions components/fctl/cmd/auth/clients/update.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,13 @@ import (
// We should get the client before updating it to get replace informations

type UpdateClient struct {
ID string `json:"id"`
Name string `json:"name"`
Description string `json:"description"`
IsPublic string `json:"isPublic"`
RedirectUri string `json:"redirectUri"`
PostLogoutRedirectUri string `json:"postLogoutRedirectUri"`
ID string `json:"id"`
Name string `json:"name"`
Description string `json:"description"`
IsPublic string `json:"isPublic"`
RedirectUri string `json:"redirectUri"`
PostLogoutRedirectUri string `json:"postLogoutRedirectUri"`
Scopes []string `json:"scopes"`
}

type UpdateStore struct {
Expand All @@ -34,6 +35,7 @@ type UpdateController struct {
descriptionFlag string
redirectUriFlag string
postLogoutRedirectUriFlag string
scopes string
}

var _ fctl.Controller[*UpdateStore] = (*UpdateController)(nil)
Expand All @@ -52,6 +54,7 @@ func NewUpdateController() *UpdateController {
descriptionFlag: "description",
redirectUriFlag: "redirect-uri",
postLogoutRedirectUriFlag: "post-logout-redirect-uri",
scopes: "scopes",
}
}

Expand All @@ -67,6 +70,7 @@ func NewUpdateCommand() *cobra.Command {
fctl.WithStringFlag(c.descriptionFlag, "", "Client description"),
fctl.WithStringSliceFlag(c.redirectUriFlag, []string{}, "Redirect URIS"),
fctl.WithStringSliceFlag(c.postLogoutRedirectUriFlag, []string{}, "Post logout redirect uris"),
fctl.WithStringSliceFlag(c.scopes, []string{}, "Scopes"),
fctl.WithController[*UpdateStore](c),
)
}
Expand Down Expand Up @@ -114,6 +118,7 @@ func (c *UpdateController) Run(cmd *cobra.Command, args []string) (fctl.Renderab
Name: args[0],
Trusted: &trusted,
PostLogoutRedirectUris: fctl.GetStringSlice(cmd, c.postLogoutRedirectUriFlag),
Scopes: fctl.GetStringSlice(cmd, c.scopes),
},
}
response, err := authClient.Auth.UpdateClient(cmd.Context(), request)
Expand All @@ -131,6 +136,7 @@ func (c *UpdateController) Run(cmd *cobra.Command, args []string) (fctl.Renderab
c.store.Client.IsPublic = fctl.BoolPointerToString(response.UpdateClientResponse.Data.Public)
c.store.Client.RedirectUri = strings.Join(response.UpdateClientResponse.Data.RedirectUris, ",")
c.store.Client.PostLogoutRedirectUri = strings.Join(response.UpdateClientResponse.Data.PostLogoutRedirectUris, ",")
c.store.Client.Scopes = response.UpdateClientResponse.Data.Scopes

return c, nil
}
Expand All @@ -143,6 +149,7 @@ func (c *UpdateController) Render(cmd *cobra.Command, args []string) error {
tableData = append(tableData, []string{pterm.LightCyan("Public"), c.store.Client.IsPublic})
tableData = append(tableData, []string{pterm.LightCyan("Redirect URIs"), c.store.Client.RedirectUri})
tableData = append(tableData, []string{pterm.LightCyan("Post logout redirect URIs"), c.store.Client.PostLogoutRedirectUri})
tableData = append(tableData, []string{pterm.LightCyan("Scopes"), strings.Join(c.store.Client.Scopes, " ")})
return pterm.DefaultTable.
WithWriter(cmd.OutOrStdout()).
WithData(tableData).
Expand Down
4 changes: 4 additions & 0 deletions components/fctl/cmd/auth/clients/views/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package views
import (
"fmt"
"io"
"strings"

fctl "github.com/formancehq/fctl/pkg"
"github.com/formancehq/formance-sdk-go/pkg/models/shared"
Expand All @@ -15,6 +16,9 @@ func PrintClient(out io.Writer, client *shared.Client) error {
tableData = append(tableData, []string{pterm.LightCyan("Name"), client.Name})
tableData = append(tableData, []string{pterm.LightCyan("Description"), fctl.StringPointerToString(client.Description)})
tableData = append(tableData, []string{pterm.LightCyan("Public"), fctl.BoolPointerToString(client.Public)})
if len(client.Scopes) > 0 {
tableData = append(tableData, []string{pterm.LightCyan("Scopes"), strings.Join(client.Scopes, " ")})
}

fctl.Section.WithWriter(out).Println("Information :")
if err := pterm.DefaultTable.
Expand Down
3 changes: 2 additions & 1 deletion ee/auth/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ require (
golang.org/x/text v0.12.0
gopkg.in/square/go-jose.v2 v2.6.0
gorm.io/driver/postgres v1.4.8
gorm.io/gorm v1.24.5
gorm.io/gorm v1.25.4
)

require (
Expand All @@ -40,6 +40,7 @@ require (
github.com/docker/go-units v0.4.0 // indirect
github.com/felixge/httpsnoop v1.0.3 // indirect
github.com/fsnotify/fsnotify v1.6.0 // indirect
github.com/go-gormigrate/gormigrate/v2 v2.1.1
github.com/go-logr/logr v1.2.4 // indirect
github.com/go-logr/stdr v1.2.2 // indirect
github.com/gogo/protobuf v1.3.2 // indirect
Expand Down
6 changes: 4 additions & 2 deletions ee/auth/go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,8 @@ github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeME
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
github.com/go-gormigrate/gormigrate/v2 v2.1.1 h1:eGS0WTFRV30r103lU8JNXY27KbviRnqqIDobW3EV3iY=
github.com/go-gormigrate/gormigrate/v2 v2.1.1/go.mod h1:L7nJ620PFDKei9QOhJzqA8kRCk+E3UbV2f5gv+1ndLc=
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ=
github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
Expand Down Expand Up @@ -750,8 +752,8 @@ gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gorm.io/driver/postgres v1.4.8 h1:NDWizaclb7Q2aupT0jkwK8jx1HVCNzt+PQ8v/VnxviA=
gorm.io/driver/postgres v1.4.8/go.mod h1:O9MruWGNLUBUWVYfWuBClpf3HeGjOoybY0SNmCs3wsw=
gorm.io/gorm v1.24.2/go.mod h1:DVrVomtaYTbqs7gB/x2uVvqnXzv0nqjB396B8cG4dBA=
gorm.io/gorm v1.24.5 h1:g6OPREKqqlWq4kh/3MCQbZKImeB9e6Xgc4zD+JgNZGE=
gorm.io/gorm v1.24.5/go.mod h1:DVrVomtaYTbqs7gB/x2uVvqnXzv0nqjB396B8cG4dBA=
gorm.io/gorm v1.25.4 h1:iyNd8fNAe8W9dvtlgeRI5zSVZPsq3OpcTu37cYcpCmw=
gorm.io/gorm v1.25.4/go.mod h1:L4uxeKpfBml98NYqVqwAdmV1a2nBtAec/cf3fpucW/k=
gotest.tools/v3 v3.0.2/go.mod h1:3SzNCllyD9/Y+b5r9JIKQ474KzkZyqLqEfYqMsX94Bk=
gotest.tools/v3 v3.2.0 h1:I0DwBVMGAx26dttAj1BtJLAkVGncrkkUXfJLC4Flt/I=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
Expand Down
5 changes: 2 additions & 3 deletions ee/auth/pkg/api/clients.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ type clientSecretView struct {
type clientView struct {
auth.ClientOptions
ID string `json:"id"`
Scopes []string `json:"scopes"`
Secrets auth.Array[clientSecretView] `json:"secrets" gorm:"type:text"`
}

Expand All @@ -40,9 +39,9 @@ func mapBusinessClient(c auth.Client) clientView {
Name: c.Name,
PostLogoutRedirectUris: c.PostLogoutRedirectUris,
Metadata: c.Metadata,
Scopes: c.Scopes,
},
ID: c.Id,
Scopes: c.Scopes,
ID: c.Id,
Secrets: mapList(c.Secrets, func(i auth.ClientSecret) clientSecretView {
return clientSecretView{
ClientSecret: i,
Expand Down
45 changes: 40 additions & 5 deletions ee/auth/pkg/api/clients_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (

auth "github.com/formancehq/auth/pkg"
"github.com/formancehq/auth/pkg/storage/sqlstorage"
"github.com/formancehq/stack/libs/go-libs/collectionutils"
"github.com/formancehq/stack/libs/go-libs/pgtesting"
"github.com/gorilla/mux"
"github.com/stretchr/testify/require"
Expand All @@ -29,6 +30,7 @@ func withDbAndClientRouter(t *testing.T, callback func(router *mux.Router, db *g
defer sqlDB.Close()

require.NoError(t, sqlstorage.MigrateTables(context.Background(), db))
require.NoError(t, sqlstorage.MigrateData(context.Background(), db))

router := mux.NewRouter()
addClientRoutes(db, router)
Expand Down Expand Up @@ -63,6 +65,19 @@ func TestCreateClient(t *testing.T) {
Public: true,
},
},
{
name: "confidential client",
options: auth.ClientOptions{
Name: "confidential client",
RedirectURIs: []string{"http://localhost:8080"},
Description: "abc",
PostLogoutRedirectUris: []string{"http://localhost:8080/logout"},
Metadata: map[string]string{
"foo": "bar",
},
Scopes: []string{"ledger:read", "ledger:write", "formance:test"},
},
},
} {
tc := tc
t.Run(tc.name, func(t *testing.T) {
Expand All @@ -78,9 +93,18 @@ func TestCreateClient(t *testing.T) {
createdClient := readTestResponse[clientView](t, res)
require.NotEmpty(t, createdClient.ID)
require.Equal(t, tc.options, createdClient.ClientOptions)

require.True(t, func() bool {
for _, scope := range tc.options.Scopes {
contain := collectionutils.Contains[string](createdClient.Scopes, scope)
if !contain {
t.Logf("scope %s not found in created client scopes", scope)
return false
}
}

return true
}())
tc.options.Id = createdClient.ID

clientFromDatabase := auth.Client{}
require.NoError(t, db.Find(&clientFromDatabase, "id = ?", createdClient.ID).Error)
require.Equal(t, auth.Client{
Expand Down Expand Up @@ -119,6 +143,19 @@ func TestUpdateClient(t *testing.T) {
Public: true,
},
},
{
name: "confidential client",
options: auth.ClientOptions{
Name: "confidential client",
RedirectURIs: []string{"http://localhost:8080"},
Description: "abc",
PostLogoutRedirectUris: []string{"http://localhost:8080/logout"},
Metadata: map[string]string{
"foo": "bar",
},
Scopes: []string{"ledger:read", "ledger:write", "formance:test"},
},
},
} {
tc := tc
t.Run(tc.name, func(t *testing.T) {
Expand All @@ -139,7 +176,6 @@ func TestUpdateClient(t *testing.T) {
require.Equal(t, tc.options, updatedClient.ClientOptions)

tc.options.Id = updatedClient.ID

clientFromDatabase := auth.Client{}
require.NoError(t, db.Find(&clientFromDatabase, "id = ?", updatedClient.ID).Error)
require.Equal(t, auth.Client{
Expand Down Expand Up @@ -183,9 +219,9 @@ func TestReadClient(t *testing.T) {
Metadata: map[string]string{
"foo": "bar",
},
Scopes: []string{"XXX"},
}
client1 := auth.NewClient(opts)
client1.Scopes = append(client1.Scopes, "XXX")
secret, _ := client1.GenerateNewSecret(auth.SecretCreate{
Name: "testing",
})
Expand All @@ -202,7 +238,6 @@ func TestReadClient(t *testing.T) {
require.Equal(t, clientView{
ClientOptions: opts,
ID: client1.Id,
Scopes: []string{"XXX"},
Secrets: []clientSecretView{{
ClientSecret: secret,
}},
Expand Down
1 change: 1 addition & 0 deletions ee/auth/pkg/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ func (c *Client) Update(opts ClientOptions) {
c.Metadata = opts.Metadata
c.Trusted = opts.Trusted
c.Public = opts.Public
c.Scopes = opts.Scopes
}

func (c *Client) GenerateNewSecret(opts SecretCreate) (ClientSecret, string) {
Expand Down
Loading

0 comments on commit 5aac996

Please sign in to comment.