Skip to content

Commit

Permalink
updated instance admin feature
Browse files Browse the repository at this point in the history
  • Loading branch information
mekilis committed Jan 21, 2025
1 parent 1db2a22 commit ccc494f
Show file tree
Hide file tree
Showing 31 changed files with 636 additions and 699 deletions.
9 changes: 0 additions & 9 deletions api/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -269,15 +269,6 @@ func (a *ApplicationHandler) BuildControlPlaneRoutes() *chi.Mux {
uiRouter.Route("/god-mode/configs", func(godModeRouter chi.Router) {
godModeRouter.Use(middleware.RequireInstanceAdmin(handler.A))

godModeRouter.Route("/defaults", func(defaultsRouter chi.Router) {
defaultsRouter.With(middleware.Pagination).Get("/", handler.GetInstanceDefaultsPaged)
defaultsRouter.Post("/", handler.CreateInstanceDefaults)
defaultsRouter.Route("/{configID}", func(configSubRouter chi.Router) {
configSubRouter.Get("/", handler.GetInstanceDefaults)
configSubRouter.Put("/", handler.UpdateInstanceDefaults)
})
})

godModeRouter.Route("/overrides", func(overridesRouter chi.Router) {
overridesRouter.With(middleware.Pagination).Get("/", handler.GetInstanceOverridesPaged)
overridesRouter.Post("/", handler.CreateInstanceOverrides)
Expand Down
105 changes: 0 additions & 105 deletions api/handlers/instance_defaults.go

This file was deleted.

20 changes: 11 additions & 9 deletions api/handlers/organisation.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,11 +68,12 @@ func (h *Handler) CreateOrganisation(w http.ResponseWriter, r *http.Request) {
}

co := services.CreateOrganisationService{
OrgRepo: postgres.NewOrgRepo(h.A.DB),
OrgMemberRepo: postgres.NewOrgMemberRepo(h.A.DB),
NewOrg: &newOrg,
User: user,
Licenser: h.A.Licenser,
OrgRepo: postgres.NewOrgRepo(h.A.DB),
OrgMemberRepo: postgres.NewOrgMemberRepo(h.A.DB),
InstanceOverridesRepo: postgres.NewInstanceOverridesRepo(h.A.DB),
NewOrg: &newOrg,
User: user,
Licenser: h.A.Licenser,
}

organisation, err := co.Run(r.Context())
Expand Down Expand Up @@ -104,10 +105,11 @@ func (h *Handler) UpdateOrganisation(w http.ResponseWriter, r *http.Request) {
}

us := services.UpdateOrganisationService{
OrgRepo: postgres.NewOrgRepo(h.A.DB),
OrgMemberRepo: postgres.NewOrgMemberRepo(h.A.DB),
Org: org,
Update: &orgUpdate,
OrgRepo: postgres.NewOrgRepo(h.A.DB),
OrgMemberRepo: postgres.NewOrgMemberRepo(h.A.DB),
InstanceOverridesRepo: postgres.NewInstanceOverridesRepo(h.A.DB),
Org: org,
Update: &orgUpdate,
}

org, err = us.Run(r.Context())
Expand Down
15 changes: 8 additions & 7 deletions api/handlers/user.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,13 +42,14 @@ func (h *Handler) RegisterUser(w http.ResponseWriter, r *http.Request) {
}

rs := services.RegisterUserService{
UserRepo: postgres.NewUserRepo(h.A.DB),
OrgRepo: postgres.NewOrgRepo(h.A.DB),
OrgMemberRepo: postgres.NewOrgMemberRepo(h.A.DB),
Queue: h.A.Queue,
JWT: jwt.NewJwt(&config.Auth.Jwt, h.A.Cache),
ConfigRepo: postgres.NewConfigRepo(h.A.DB),
Licenser: h.A.Licenser,
UserRepo: postgres.NewUserRepo(h.A.DB),
OrgRepo: postgres.NewOrgRepo(h.A.DB),
OrgMemberRepo: postgres.NewOrgMemberRepo(h.A.DB),
InstanceOverridesRepo: postgres.NewInstanceOverridesRepo(h.A.DB),
Queue: h.A.Queue,
JWT: jwt.NewJwt(&config.Auth.Jwt, h.A.Cache),
ConfigRepo: postgres.NewConfigRepo(h.A.DB),
Licenser: h.A.Licenser,

BaseURL: baseUrl,
Data: &newUser,
Expand Down
21 changes: 0 additions & 21 deletions api/ingest_cfg_integration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,27 +41,8 @@ func TestIngestCfg_GetInstanceRateLimit(t *testing.T) {

ctx := context.Background()

instanceDefaultsRepo := postgres.NewInstanceDefaultsRepo(db)
instanceOverridesRepo := postgres.NewInstanceOverridesRepo(db)

t.Run("Default Found", func(t *testing.T) {
_, err := instanceDefaultsRepo.Create(ctx, &datastore.InstanceDefaults{
UID: "default1",
ScopeType: instance.OrganisationScope,
Key: instance.KeyInstanceIngestRate,
DefaultValue: "{\"value\": 150}",
})
assert.NoError(t, err)

cacheKey := fmt.Sprintf("rate_limit:%s:%s:%s", instance.KeyInstanceIngestRate, projectID, organisationID)
err = memoryCache.Delete(ctx, cacheKey)
require.NoError(t, err)

rateLimit, err := ingestCfg.GetInstanceRateLimitWithCache(ctx)
assert.NoError(t, err)
assert.Equal(t, 150, rateLimit)
})

t.Run("Override Found", func(t *testing.T) {
_, err := instanceOverridesRepo.Create(ctx, &datastore.InstanceOverrides{
UID: "override1",
Expand All @@ -84,8 +65,6 @@ func TestIngestCfg_GetInstanceRateLimit(t *testing.T) {
t.Run("Fallback to Default Rate", func(t *testing.T) {
_, err := db.GetDB().ExecContext(ctx, `DELETE FROM convoy.instance_overrides WHERE key = $1`, instance.KeyInstanceIngestRate)
assert.NoError(t, err)
_, err = db.GetDB().ExecContext(ctx, `DELETE FROM convoy.instance_defaults WHERE key = $1`, instance.KeyInstanceIngestRate)
assert.NoError(t, err)

cacheKey := fmt.Sprintf("rate_limit:%s:%s:%s", instance.KeyInstanceIngestRate, projectID, organisationID)
err = memoryCache.Delete(ctx, cacheKey)
Expand Down
17 changes: 15 additions & 2 deletions api/models/models.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package models

import (
"encoding/json"
"github.com/frain-dev/convoy/config"
"time"

"github.com/frain-dev/convoy/auth"
Expand All @@ -15,8 +16,20 @@ type PagedResponse struct {
}

type Organisation struct {
Name string `json:"name" bson:"name"`
CustomDomain string `json:"custom_domain" bson:"custom_domain"`
Name string `json:"name" bson:"name"`
CustomDomain string `json:"custom_domain" bson:"custom_domain"`
Config *Config `json:"config" bson:"config"`
}

type Config struct {
StaticIP *bool `json:"static_ip" bson:"static_ip"`
EnterpriseSSO *bool `json:"enterprise_sso" bson:"enterprise_sso"`
ProjectConfig *Project `json:"project" bson:"project"`
}

type Project struct {
RetentionPolicy *config.RetentionPolicyConfiguration `json:"retention_policy" bson:"retention_policy"`
IngestRateLimit *int `json:"ingest_rate_limit" bson:"ingest_rate_limit"`
}

type OrganisationInvite struct {
Expand Down
20 changes: 0 additions & 20 deletions api/retention_cfg_integration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,26 +37,8 @@ func TestRetentionCfg_GetRetentionPolicy(t *testing.T) {

ctx := context.Background()

instanceDefaultsRepo := postgres.NewInstanceDefaultsRepo(db)
instanceOverridesRepo := postgres.NewInstanceOverridesRepo(db)

t.Run("Default Found", func(t *testing.T) {
_, err := instanceDefaultsRepo.Create(ctx, &datastore.InstanceDefaults{
UID: "default2",
ScopeType: instance.OrganisationScope,
Key: instance.KeyRetentionPolicy,
DefaultValue: "{\"policy\": \"36h\", \"enabled\": false}",
})
assert.NoError(t, err)

// Fetch the retention policy
retentionPolicy, err := retentionCfg.GetRetentionPolicy(ctx)
assert.NoError(t, err)
d, err := time.ParseDuration("36h")
require.NoError(t, err)
assert.Equal(t, d, retentionPolicy)
})

t.Run("Override Found", func(t *testing.T) {
_, err := instanceOverridesRepo.Create(ctx, &datastore.InstanceOverrides{
UID: "override2",
Expand All @@ -77,8 +59,6 @@ func TestRetentionCfg_GetRetentionPolicy(t *testing.T) {
t.Run("Fallback to Default Policy", func(t *testing.T) {
_, err := db.GetDB().ExecContext(ctx, `DELETE FROM convoy.instance_overrides WHERE key = $1`, instance.KeyRetentionPolicy)
assert.NoError(t, err)
_, err = db.GetDB().ExecContext(ctx, `DELETE FROM convoy.instance_defaults WHERE key = $1`, instance.KeyRetentionPolicy)
assert.NoError(t, err)

retentionPolicy, err := retentionCfg.GetRetentionPolicy(ctx)
assert.NoError(t, err)
Expand Down
1 change: 0 additions & 1 deletion api/testdb/seed.go
Original file line number Diff line number Diff line change
Expand Up @@ -725,7 +725,6 @@ func truncateTables(db database.Database) error {
convoy.organisations,
convoy.users,
convoy.jobs,
convoy.instance_defaults,
convoy.instance_overrides
`

Expand Down
49 changes: 43 additions & 6 deletions cmd/bootstrap/bootstrap.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"encoding/json"
"errors"
"fmt"
"github.com/frain-dev/convoy/auth"
"time"

"github.com/frain-dev/convoy/api/models"
Expand All @@ -20,11 +21,16 @@ import (
"github.com/spf13/cobra"
)

var (
ErrInstanceAdminOrRootRequired = errors.New("an instance admin or a root user is required")
)

func AddBootstrapCommand(a *cli.App) *cobra.Command {
var firstName string
var lastName string
var format string
var email string
var token string

cmd := &cobra.Command{
Use: "bootstrap",
Expand All @@ -33,19 +39,47 @@ func AddBootstrapCommand(a *cli.App) *cobra.Command {
"ShouldBootstrap": "false",
},
RunE: func(cmd *cobra.Command, args []string) error {
return runBootstrap(a, format, email, firstName, lastName)

orgMemberRepo := postgres.NewOrgMemberRepo(a.DB)

count, err := orgMemberRepo.CountSuperUsers(context.Background())
if err != nil {
return fmt.Errorf("failed to count org admins: %w", err)
}

if count > 0 {
// org admin exists
if token == "" {
return fmt.Errorf("an access token required to proceed")
}
authUser, member, err := getInstanceAdminOrRoot(a, token)
if err != nil {
log.WithError(err).Warn("failed to get instance admin or root")
return fmt.Errorf("failed to get instance admin or root: %w", err)
}
if authUser == nil || member == nil {
return ErrInstanceAdminOrRootRequired
}

if member.Role.Type != auth.RoleRoot && member.Role.Type != auth.RoleInstanceAdmin {
return fmt.Errorf("invalid role %+v", authUser.Role.Type)
}
}

return runBootstrap(a, format, email, firstName, lastName, auth.RoleOrganisationAdmin)
},
}

cmd.Flags().StringVar(&email, "email", "", "Email")
cmd.Flags().StringVar(&firstName, "first-name", "admin", "Email")
cmd.Flags().StringVar(&lastName, "last-name", "admin", "Email")
cmd.Flags().StringVar(&format, "format", "json", "Output Format")
cmd.Flags().StringVar(&token, "token", "", "Root Personal Access Token")

return cmd
}

func runBootstrap(a *cli.App, format string, email string, firstName string, lastName string) error {
func runBootstrap(a *cli.App, format string, email string, firstName string, lastName string, roleType auth.RoleType) error {
ok, err := a.Licenser.CreateUser(context.Background())
if err != nil {
return err
Expand Down Expand Up @@ -97,10 +131,13 @@ func runBootstrap(a *cli.App, format string, email string, firstName string, las
}

co := services.CreateOrganisationService{
OrgRepo: postgres.NewOrgRepo(a.DB),
OrgMemberRepo: postgres.NewOrgMemberRepo(a.DB),
NewOrg: &models.Organisation{Name: "Default Organisation"},
User: user,
OrgRepo: postgres.NewOrgRepo(a.DB),
OrgMemberRepo: postgres.NewOrgMemberRepo(a.DB),
InstanceOverridesRepo: postgres.NewInstanceOverridesRepo(a.DB),
NewOrg: &models.Organisation{Name: "Default Organisation"},
User: user,
Licenser: a.Licenser,
RoleType: roleType,
}

_, err = co.Run(context.Background())
Expand Down
Loading

0 comments on commit ccc494f

Please sign in to comment.