Resources segregation by tenant #20
|
@ -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
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
|
@ -12,6 +12,7 @@ func Root() *cli.Command {
|
||||||
CreateCommand(),
|
CreateCommand(),
|
||||||
GetCommand(),
|
GetCommand(),
|
||||||
UpdateCommand(),
|
UpdateCommand(),
|
||||||
|
DeleteCommand(),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -230,8 +230,8 @@ func (r *AgentRepository) UpdateSpec(ctx context.Context, agentID datastore.Agen
|
||||||
now := time.Now().UTC()
|
now := time.Now().UTC()
|
||||||
|
|
||||||
query := `
|
query := `
|
||||||
INSERT INTO specs (agent_id, name, revision, data, created_at, updated_at)
|
INSERT INTO specs (agent_id, name, revision, data, created_at, updated_at, tenant_id)
|
||||||
VALUES($1, $2, $3, $4, $5, $5)
|
VALUES($1, $2, $3, $4, $5, $5, ( SELECT tenant_id FROM agents WHERE id = $1 ))
|
||||||
ON CONFLICT (agent_id, name) DO UPDATE SET
|
ON CONFLICT (agent_id, name) DO UPDATE SET
|
||||||
data = $4, updated_at = $5, revision = specs.revision + 1
|
data = $4, updated_at = $5, revision = specs.revision + 1
|
||||||
WHERE revision = $3
|
WHERE revision = $3
|
||||||
|
|
|
@ -63,7 +63,7 @@ func assertAdminOrTenantReadAccess(h http.Handler) http.Handler {
|
||||||
assertOneOfRoles(user.RoleAdmin),
|
assertOneOfRoles(user.RoleAdmin),
|
||||||
assertAllOfUser(
|
assertAllOfUser(
|
||||||
assertOneOfRoles(user.RoleReader, user.RoleWriter),
|
assertOneOfRoles(user.RoleReader, user.RoleWriter),
|
||||||
assertTenant(),
|
assertSameTenant(),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
nil,
|
nil,
|
||||||
|
@ -77,7 +77,7 @@ func assertAdminOrTenantWriteAccess(h http.Handler) http.Handler {
|
||||||
assertOneOfRoles(user.RoleAdmin),
|
assertOneOfRoles(user.RoleAdmin),
|
||||||
assertAllOfUser(
|
assertAllOfUser(
|
||||||
assertOneOfRoles(user.RoleWriter),
|
assertOneOfRoles(user.RoleWriter),
|
||||||
assertTenant(),
|
assertSameTenant(),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
nil,
|
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 {
|
return func(w http.ResponseWriter, r *http.Request, u *user.User) bool {
|
||||||
tenantID, ok := getTenantID(w, r)
|
tenantID, ok := getTenantID(w, r)
|
||||||
if !ok {
|
if !ok {
|
||||||
|
|
|
@ -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
|
||||||
|
}
|
Loading…
Reference in New Issue