From 8438c4bc1aab1408a8df3c5c136c8a40be713761 Mon Sep 17 00:00:00 2001 From: William Petit Date: Tue, 27 Feb 2024 15:30:21 +0100 Subject: [PATCH] feat: add delete tenant command --- internal/command/client/tenant/delete.go | 56 +++++++++++++++++++ internal/command/client/tenant/root.go | 1 + internal/datastore/sqlite/agent_repository.go | 4 +- internal/server/api/authorization.go | 6 +- pkg/client/delete_tenant.go | 26 +++++++++ 5 files changed, 88 insertions(+), 5 deletions(-) create mode 100644 internal/command/client/tenant/delete.go create mode 100644 pkg/client/delete_tenant.go diff --git a/internal/command/client/tenant/delete.go b/internal/command/client/tenant/delete.go new file mode 100644 index 0000000..c99554c --- /dev/null +++ b/internal/command/client/tenant/delete.go @@ -0,0 +1,56 @@ +package tenant + +import ( + "os" + + "forge.cadoles.com/Cadoles/emissary/internal/command/client/apierr" + clientFlag "forge.cadoles.com/Cadoles/emissary/internal/command/client/flag" + tenantFlag "forge.cadoles.com/Cadoles/emissary/internal/command/client/tenant/flag" + "forge.cadoles.com/Cadoles/emissary/internal/datastore" + "forge.cadoles.com/Cadoles/emissary/pkg/client" + "github.com/pkg/errors" + "github.com/urfave/cli/v2" + "gitlab.com/wpetit/goweb/cli/format" +) + +func DeleteCommand() *cli.Command { + return &cli.Command{ + Name: "delete", + Usage: "Delete tenant", + Flags: tenantFlag.WithTenantFlags(), + Action: func(ctx *cli.Context) error { + baseFlags := clientFlag.GetBaseFlags(ctx) + + token, err := clientFlag.GetToken(baseFlags) + if err != nil { + return errors.WithStack(apierr.Wrap(err)) + } + + tenantID, err := tenantFlag.AssertTenantID(ctx) + if err != nil { + return errors.WithStack(err) + } + + client := client.New(baseFlags.ServerURL, client.WithToken(token)) + + tenantID, err = client.DeleteTenant(ctx.Context, tenantID) + if err != nil { + return errors.WithStack(apierr.Wrap(err)) + } + + hints := format.Hints{ + OutputMode: baseFlags.OutputMode, + } + + if err := format.Write(baseFlags.Format, os.Stdout, hints, struct { + ID datastore.TenantID `json:"id"` + }{ + ID: tenantID, + }); err != nil { + return errors.WithStack(err) + } + + return nil + }, + } +} diff --git a/internal/command/client/tenant/root.go b/internal/command/client/tenant/root.go index 1ee1923..45d0f26 100644 --- a/internal/command/client/tenant/root.go +++ b/internal/command/client/tenant/root.go @@ -12,6 +12,7 @@ func Root() *cli.Command { CreateCommand(), GetCommand(), UpdateCommand(), + DeleteCommand(), }, } } diff --git a/internal/datastore/sqlite/agent_repository.go b/internal/datastore/sqlite/agent_repository.go index f9c58b4..cc8ba50 100644 --- a/internal/datastore/sqlite/agent_repository.go +++ b/internal/datastore/sqlite/agent_repository.go @@ -230,8 +230,8 @@ func (r *AgentRepository) UpdateSpec(ctx context.Context, agentID datastore.Agen now := time.Now().UTC() query := ` - INSERT INTO specs (agent_id, name, revision, data, created_at, updated_at) - VALUES($1, $2, $3, $4, $5, $5) + INSERT INTO specs (agent_id, name, revision, data, created_at, updated_at, tenant_id) + VALUES($1, $2, $3, $4, $5, $5, ( SELECT tenant_id FROM agents WHERE id = $1 )) ON CONFLICT (agent_id, name) DO UPDATE SET data = $4, updated_at = $5, revision = specs.revision + 1 WHERE revision = $3 diff --git a/internal/server/api/authorization.go b/internal/server/api/authorization.go index 6b7f498..db08329 100644 --- a/internal/server/api/authorization.go +++ b/internal/server/api/authorization.go @@ -63,7 +63,7 @@ func assertAdminOrTenantReadAccess(h http.Handler) http.Handler { assertOneOfRoles(user.RoleAdmin), assertAllOfUser( assertOneOfRoles(user.RoleReader, user.RoleWriter), - assertTenant(), + assertSameTenant(), ), ), nil, @@ -77,7 +77,7 @@ func assertAdminOrTenantWriteAccess(h http.Handler) http.Handler { assertOneOfRoles(user.RoleAdmin), assertAllOfUser( assertOneOfRoles(user.RoleWriter), - assertTenant(), + assertSameTenant(), ), ), nil, @@ -147,7 +147,7 @@ func assertOneOfUser(funcs ...assertUser) assertUser { } } -func assertTenant() assertUser { +func assertSameTenant() assertUser { return func(w http.ResponseWriter, r *http.Request, u *user.User) bool { tenantID, ok := getTenantID(w, r) if !ok { diff --git a/pkg/client/delete_tenant.go b/pkg/client/delete_tenant.go new file mode 100644 index 0000000..66a736a --- /dev/null +++ b/pkg/client/delete_tenant.go @@ -0,0 +1,26 @@ +package client + +import ( + "context" + "fmt" + + "github.com/pkg/errors" +) + +func (c *Client) DeleteTenant(ctx context.Context, tenantID TenantID, funcs ...OptionFunc) (TenantID, error) { + response := withResponse[struct { + TenantID string `json:"tenantId"` + }]() + + path := fmt.Sprintf("/api/v1/tenants/%s", tenantID) + + if err := c.apiDelete(ctx, path, nil, &response, funcs...); err != nil { + return "", errors.WithStack(err) + } + + if response.Error != nil { + return "", errors.WithStack(response.Error) + } + + return TenantID(response.Data.TenantID), nil +}