3
0

Refactor "roles" CLI command

This commit is contained in:
Denis Arh
2019-04-03 23:49:03 +02:00
parent 375e155f9c
commit 32e2069c45
2 changed files with 186 additions and 192 deletions
+3 -39
View File
@@ -14,8 +14,9 @@ import (
func Init(ctx context.Context) {
// Main command.
rootCmd := &cobra.Command{Use: "system-cli"}
db := repository.DB(ctx)
settingsService := settings.NewService(settings.NewRepository(repository.DB(ctx), "sys_settings"))
settingsService := settings.NewService(settings.NewRepository(db, "sys_settings"))
Settings(rootCmd, settingsService)
@@ -40,44 +41,7 @@ func Init(ctx context.Context) {
}
cmdUsers.AddCommand(cmdUsersList)
// Assign role to user.
var cmdUserAssignRole = &cobra.Command{
Use: "roleadd [userID] [roleID]",
Short: "Assign role to user",
Args: cobra.ExactArgs(2),
Run: func(cmd *cobra.Command, args []string) {
RoleAssignUser(args[1], args[0])
},
}
cmdUsers.AddCommand(cmdUserAssignRole)
// Role management commands.
var cmdRole = &cobra.Command{
Use: "roles",
Short: "Role management",
}
rootCmd.AddCommand(cmdRole)
// Reset roles.
var cmdRolesReset = &cobra.Command{
Use: "reset",
Short: "Reset roles",
Run: func(cmd *cobra.Command, args []string) {
RolesReset()
},
}
cmdRole.AddCommand(cmdRolesReset)
// Add user to role.
var cmdRoleAddUser = &cobra.Command{
Use: "useradd [roleID] [userID]",
Short: "Add user to role",
Args: cobra.ExactArgs(2),
Run: func(cmd *cobra.Command, args []string) {
RoleAssignUser(args[0], args[1])
},
}
cmdRole.AddCommand(cmdRoleAddUser)
roles(ctx, rootCmd, db)
err := rootCmd.Execute()
if err != nil {
+183 -153
View File
@@ -3,179 +3,209 @@ package cli
import (
"context"
"fmt"
"os"
"strconv"
"time"
"github.com/pkg/errors"
"github.com/spf13/cobra"
"github.com/titpetric/factory"
"github.com/crusttech/crust/internal/rules"
"github.com/crusttech/crust/system/internal/repository"
"github.com/crusttech/crust/system/types"
)
func RolesReset() {
var (
err error
ctx = context.Background()
db = repository.DB(ctx)
roleRepo = repository.Role(ctx, db)
ruleRepo = rules.NewResources(ctx, db)
)
// Recreates core roles (will not reset memberships!)
err = types.RoleSet{
&types.Role{ID: 1, Handle: "everyone", Name: "Everyone"},
&types.Role{ID: 2, Handle: "admins", Name: "Administrators"},
}.Walk(func(r *types.Role) error {
// Update will exec REPLACE and take care of creation as well
r.CreatedAt = time.Now()
_, err := roleRepo.Update(r)
return err
})
if err != nil {
fmt.Printf("could not reset roles: %v", err)
return
func roles(ctx context.Context, rootCmd *cobra.Command, db *factory.DB) {
resetCmd := &cobra.Command{
Use: "reset",
Short: "Reset roles",
Run: rolesReset(ctx, db),
}
rules := []rules.Rule{
{1, "system", "user.create", 2},
{1, "compose", "access", 2},
{1, "messaging", "access", 2},
{2, "compose", "namespace.create", 2},
{2, "compose", "access", 2},
{2, "compose", "grant", 2},
{2, "compose:namespace:*", "page.create", 2},
{2, "compose:namespace:*", "read", 2},
{2, "compose:namespace:*", "update", 2},
{2, "compose:namespace:*", "delete", 2},
{2, "compose:namespace:*", "module.create", 2},
{2, "compose:namespace:*", "chart.create", 2},
{2, "compose:namespace:*", "trigger.create", 2},
{2, "compose:chart:*", "read", 2},
{2, "compose:chart:*", "update", 2},
{2, "compose:chart:*", "delete", 2},
{2, "compose:trigger:*", "read", 2},
{2, "compose:trigger:*", "update", 2},
{2, "compose:trigger:*", "delete", 2},
{2, "compose:page:*", "read", 2},
{2, "compose:page:*", "update", 2},
{2, "compose:page:*", "delete", 2},
{2, "system", "access", 2},
{2, "system", "grant", 2},
{2, "system", "settings.read", 2},
{2, "system", "settings.manage", 2},
{2, "system", "organisation.create", 2},
{2, "system", "user.create", 2},
{2, "system", "role.create", 2},
{2, "system:organisation:*", "access", 2},
{2, "system:user:*", "read", 2},
{2, "system:user:*", "update", 2},
{2, "system:user:*", "suspend", 2},
{2, "system:user:*", "unsuspend", 2},
{2, "system:user:*", "delete", 2},
{2, "system:role:*", "read", 2},
{2, "system:role:*", "update", 2},
{2, "system:role:*", "delete", 2},
{2, "system:role:*", "members.manage", 2},
{2, "messaging", "access", 2},
{2, "messaging", "grant", 2},
{2, "messaging", "channel.public.create", 2},
{2, "messaging", "channel.private.create", 2},
{2, "messaging", "channel.group.create", 2},
{2, "messaging:channel:*", "update", 2},
{2, "messaging:channel:*", "leave", 2},
{2, "messaging:channel:*", "read", 2},
{2, "messaging:channel:*", "join", 2},
{2, "messaging:channel:*", "delete", 2},
{2, "messaging:channel:*", "undelete", 2},
{2, "messaging:channel:*", "archive", 2},
{2, "messaging:channel:*", "unarchive", 2},
{2, "messaging:channel:*", "members.manage", 2},
{2, "messaging:channel:*", "webhooks.manage", 2},
{2, "messaging:channel:*", "attachments.manage", 2},
{2, "messaging:channel:*", "message.attach", 2},
{2, "messaging:channel:*", "message.update.all", 2},
{2, "messaging:channel:*", "message.update.own", 2},
{2, "messaging:channel:*", "message.delete.all", 2},
{2, "messaging:channel:*", "message.delete.own", 2},
{2, "messaging:channel:*", "message.embed", 2},
{2, "messaging:channel:*", "message.send", 2},
{2, "messaging:channel:*", "message.reply", 2},
{2, "messaging:channel:*", "message.react", 2},
{2, "compose:module:*", "read", 2},
{2, "compose:module:*", "update", 2},
{2, "compose:module:*", "delete", 2},
{2, "compose:module:*", "record.create", 2},
{2, "compose:module:*", "record.read", 2},
{2, "compose:module:*", "record.update", 2},
{2, "compose:module:*", "record.delete", 2},
addUserCmd := &cobra.Command{
Use: "useradd [role-ID-or-name-or-handle] [user-ID-or-email]",
Short: "Add user to role",
Args: cobra.ExactArgs(2),
Run: rolesUserAdd(ctx, db),
}
var purgedRoles = map[uint64]bool{}
for _, r := range rules {
if !purgedRoles[r.RoleID] {
if err = ruleRepo.Delete(r.RoleID); err != nil {
fmt.Printf("could not reset rules: %v", err)
return
// Role management commands.
var cmdRole = &cobra.Command{
Use: "roles",
Short: "Role management",
}
cmdRole.AddCommand(resetCmd, addUserCmd)
rootCmd.AddCommand(cmdRole)
}
func rolesReset(ctx context.Context, db *factory.DB) func(cmd *cobra.Command, args []string) {
return func(cmd *cobra.Command, args []string) {
var (
err error
roleRepo = repository.Role(ctx, db)
ruleRepo = rules.NewResources(ctx, db)
)
// Recreates core roles (will not reset memberships!)
err = types.RoleSet{
&types.Role{ID: 1, Handle: "everyone", Name: "Everyone"},
&types.Role{ID: 2, Handle: "admins", Name: "Administrators"},
}.Walk(func(r *types.Role) error {
// Update will exec REPLACE and take care of creation as well
r.CreatedAt = time.Now()
_, err := roleRepo.Update(r)
return err
})
if err != nil {
fmt.Printf("could not reset roles: %v", err)
return
}
rules := []rules.Rule{
{1, "system", "user.create", 2},
{1, "compose", "access", 2},
{1, "messaging", "access", 2},
{2, "compose", "namespace.create", 2},
{2, "compose", "access", 2},
{2, "compose", "grant", 2},
{2, "compose:namespace:*", "page.create", 2},
{2, "compose:namespace:*", "read", 2},
{2, "compose:namespace:*", "update", 2},
{2, "compose:namespace:*", "delete", 2},
{2, "compose:namespace:*", "module.create", 2},
{2, "compose:namespace:*", "chart.create", 2},
{2, "compose:namespace:*", "trigger.create", 2},
{2, "compose:chart:*", "read", 2},
{2, "compose:chart:*", "update", 2},
{2, "compose:chart:*", "delete", 2},
{2, "compose:trigger:*", "read", 2},
{2, "compose:trigger:*", "update", 2},
{2, "compose:trigger:*", "delete", 2},
{2, "compose:page:*", "read", 2},
{2, "compose:page:*", "update", 2},
{2, "compose:page:*", "delete", 2},
{2, "system", "access", 2},
{2, "system", "grant", 2},
{2, "system", "settings.read", 2},
{2, "system", "settings.manage", 2},
{2, "system", "organisation.create", 2},
{2, "system", "user.create", 2},
{2, "system", "role.create", 2},
{2, "system:organisation:*", "access", 2},
{2, "system:user:*", "read", 2},
{2, "system:user:*", "update", 2},
{2, "system:user:*", "suspend", 2},
{2, "system:user:*", "unsuspend", 2},
{2, "system:user:*", "delete", 2},
{2, "system:role:*", "read", 2},
{2, "system:role:*", "update", 2},
{2, "system:role:*", "delete", 2},
{2, "system:role:*", "members.manage", 2},
{2, "messaging", "access", 2},
{2, "messaging", "grant", 2},
{2, "messaging", "channel.public.create", 2},
{2, "messaging", "channel.private.create", 2},
{2, "messaging", "channel.group.create", 2},
{2, "messaging:channel:*", "update", 2},
{2, "messaging:channel:*", "leave", 2},
{2, "messaging:channel:*", "read", 2},
{2, "messaging:channel:*", "join", 2},
{2, "messaging:channel:*", "delete", 2},
{2, "messaging:channel:*", "undelete", 2},
{2, "messaging:channel:*", "archive", 2},
{2, "messaging:channel:*", "unarchive", 2},
{2, "messaging:channel:*", "members.manage", 2},
{2, "messaging:channel:*", "webhooks.manage", 2},
{2, "messaging:channel:*", "attachments.manage", 2},
{2, "messaging:channel:*", "message.attach", 2},
{2, "messaging:channel:*", "message.update.all", 2},
{2, "messaging:channel:*", "message.update.own", 2},
{2, "messaging:channel:*", "message.delete.all", 2},
{2, "messaging:channel:*", "message.delete.own", 2},
{2, "messaging:channel:*", "message.embed", 2},
{2, "messaging:channel:*", "message.send", 2},
{2, "messaging:channel:*", "message.reply", 2},
{2, "messaging:channel:*", "message.react", 2},
{2, "compose:module:*", "read", 2},
{2, "compose:module:*", "update", 2},
{2, "compose:module:*", "delete", 2},
{2, "compose:module:*", "record.create", 2},
{2, "compose:module:*", "record.read", 2},
{2, "compose:module:*", "record.update", 2},
{2, "compose:module:*", "record.delete", 2},
}
var purgedRoles = map[uint64]bool{}
for _, r := range rules {
if !purgedRoles[r.RoleID] {
if err = ruleRepo.Delete(r.RoleID); err != nil {
fmt.Printf("could not reset rules: %v", err)
return
}
purgedRoles[r.RoleID] = true
}
}
purgedRoles[r.RoleID] = true
// Recreates rules for core roles
err = ruleRepo.Reset(rules)
if err != nil {
fmt.Printf("could not reset rules: %v", err)
}
}
// Recreates rules for core roles
err = ruleRepo.Reset(rules)
if err != nil {
fmt.Printf("could not reset rules: %v", err)
}
}
func RoleAssignUser(roleStr string, userStr string) {
ctx := context.Background()
db := repository.DB(ctx)
func rolesUserAdd(ctx context.Context, db *factory.DB) func(cmd *cobra.Command, args []string) {
return func(cmd *cobra.Command, args []string) {
// Create role and user repository.
var (
roleStr, userStr = args[0], args[1]
// Create role and user repository.
roleRepo := repository.Role(ctx, db)
userRepo := repository.User(ctx, db)
roleRepo = repository.Role(ctx, db)
userRepo = repository.User(ctx, db)
var err error
rr []*types.Role
role *types.Role
user *types.User
ID uint64
// Try to parse roleID.
roleID, err := strconv.ParseUint(roleStr, 10, 64)
if err != nil {
fmt.Printf("Error: %v\n", err)
os.Exit(1)
err error
)
// Try to find role by name and by ID
if rr, err = roleRepo.Find(&types.RoleFilter{Query: roleStr}); err != nil {
exit(cmd, err)
} else if len(rr) == 1 {
role = rr[0]
} else if len(rr) > 1 {
exit(cmd, errors.Errorf("too many roles found with name %q", roleStr))
} else if role == nil {
if ID, err = strconv.ParseUint(roleStr, 10, 64); err != nil {
// Could not parse ID out of role string
return
} else if role, err = roleRepo.FindByID(ID); err != nil {
return
}
}
if user, err = userRepo.FindByEmail(userStr); err != nil && err != repository.ErrUserNotFound {
exit(cmd, err)
} else if user == nil || user.ID == 0 {
if ID, err = strconv.ParseUint(userStr, 10, 64); err != nil {
exit(cmd, err)
} else if user, err = userRepo.FindByID(ID); err != nil {
exit(cmd, err)
}
}
// Add user to role.
if err = roleRepo.MemberAddByID(role.ID, user.ID); err != nil {
exit(cmd, err)
}
cmd.Printf("Added user [%d] %q to [%d] %q role\n", user.ID, user.Email, role.ID, role.Name)
}
// Check if role ID exists.
role, err := roleRepo.FindByID(roleID)
if err != nil {
fmt.Printf("Error: %v\n", err)
os.Exit(1)
}
var userID uint64
var user *types.User
// Try to parse userID.
userID, err = strconv.ParseUint(userStr, 10, 64)
if err != nil {
user, err = userRepo.FindByEmail(userStr)
} else {
user, err = userRepo.FindByID(userID)
}
if err != nil {
fmt.Printf("Error: %v\n", err)
os.Exit(1)
}
// Add user to role.
err = roleRepo.MemberAddByID(role.ID, user.ID)
if err != nil {
fmt.Printf("Error: %v\n", err)
os.Exit(1)
}
fmt.Printf("Added user: %d %s to role: %s\n", user.ID, user.Email, role.Name)
}