Add some user related commands

This commit is contained in:
Miguel de la Cruz 2021-09-13 12:16:25 +02:00
parent d5a297cb86
commit 83a2d2a31f
8 changed files with 223 additions and 11 deletions

View file

@ -1,13 +1,13 @@
package api
import (
"git.ctrlz.es/mgdelacroix/craban/services/store"
"git.ctrlz.es/mgdelacroix/craban/app"
)
type API struct {
store *store.Store
App *app.App
}
func NewAPI(store *store.Store) (*API, error) {
return &API{store: store}, nil
func NewAPI(app *app.App) *API {
return &API{App: app}
}

18
server/app/app.go Normal file
View file

@ -0,0 +1,18 @@
package app
import (
"git.ctrlz.es/mgdelacroix/craban/model"
"git.ctrlz.es/mgdelacroix/craban/services/store"
)
type App struct {
config *model.Config
store *store.Store
}
func NewApp(config *model.Config, store *store.Store) *App {
return &App{
config: config,
store: store,
}
}

36
server/app/user.go Normal file
View file

@ -0,0 +1,36 @@
package app
import (
"fmt"
"git.ctrlz.es/mgdelacroix/craban/model"
"git.ctrlz.es/mgdelacroix/craban/utils"
)
func (a *App) CreateUser(username, password, name, mail string) (*model.User, error) {
hashedPassword, err := utils.Encrypt(password)
if err != nil {
return nil, fmt.Errorf("cannot create user: %w", err)
}
newUser := &model.User{
Username: username,
Password: hashedPassword,
Name: name,
Mail: mail,
}
if err := newUser.IsValid(); err != nil {
return nil, fmt.Errorf("invalid user for creation: %w", err)
}
return a.store.User().Create(newUser)
}
func (a *App) ListUsers() ([]*model.User, error) {
return a.store.User().List()
}
func (a *App) DeleteUserByUsername(username string) error {
return a.store.User().DeleteByUsername(username)
}

View file

@ -16,6 +16,7 @@ func RootCmd() *cobra.Command {
cmd.AddCommand(
ServeCmd(),
UserCmd(),
)
return cmd

View file

@ -14,14 +14,15 @@ func ServeCmd() *cobra.Command {
return &cobra.Command{
Use: "serve",
Short: "Starts the craban server",
Args: cobra.NoArgs,
Run: serveCmdF,
}
}
func serveCmdF(cmd *cobra.Command, _ []string) {
configPath, _ := cmd.Flags().GetString("config")
config, _ := cmd.Flags().GetString("config")
srv, err := server.NewServerWithConfigPath(configPath)
srv, err := server.NewServerWithConfigPath(config)
if err != nil {
log.Error().Err(err).Msg("cannot create server")
os.Exit(1)

View file

@ -0,0 +1,123 @@
package commands
import (
"os"
"git.ctrlz.es/mgdelacroix/craban/server"
"github.com/rs/zerolog/log"
"github.com/spf13/cobra"
)
func UserCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "user",
Short: "User related commands",
}
cmd.AddCommand(
CreateUserCmd(),
ListUserCmd(),
DeleteUserCmd(),
)
return cmd
}
func CreateUserCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "create",
Short: "Create a new user",
Args: cobra.NoArgs,
Run: createUserCmdF,
}
cmd.Flags().StringP("username", "u", "", "the username of the new user")
cmd.MarkFlagRequired("username")
cmd.Flags().StringP("password", "p", "", "the password of the new user")
cmd.MarkFlagRequired("password")
cmd.Flags().StringP("name", "n", "", "the name of the new user")
cmd.MarkFlagRequired("name")
cmd.Flags().StringP("mail", "m", "", "the mail of the new user")
cmd.MarkFlagRequired("mail")
return cmd
}
func ListUserCmd() *cobra.Command {
return &cobra.Command{
Use: "list",
Short: "List the users in the system",
Args: cobra.NoArgs,
Run: listUserCmdF,
}
}
func DeleteUserCmd() *cobra.Command {
return &cobra.Command{
Use: "delete <username>",
Short: "Delete a user by username",
Args: cobra.ExactArgs(1),
Run: deleteUserCmdF,
}
}
func createUserCmdF(cmd *cobra.Command, _ []string) {
username, _ := cmd.Flags().GetString("username")
password, _ := cmd.Flags().GetString("password")
name, _ := cmd.Flags().GetString("name")
mail, _ := cmd.Flags().GetString("mail")
config, _ := cmd.Flags().GetString("config")
srv, err := server.NewServerWithConfigPath(config)
if err != nil {
log.Error().Err(err).Msg("cannot create server")
os.Exit(1)
}
defer srv.Store.Close()
user, err := srv.App.CreateUser(username, password, name, mail)
if err != nil {
log.Error().Err(err).Msg("user couldn't be created")
os.Exit(1)
}
log.Info().Str("username", user.Username).Msg("user successfully created")
}
func listUserCmdF(cmd *cobra.Command, _ []string) {
config, _ := cmd.Flags().GetString("config")
srv, err := server.NewServerWithConfigPath(config)
if err != nil {
log.Error().Err(err).Msg("cannot create server")
os.Exit(1)
}
defer srv.Store.Close()
users, err := srv.App.ListUsers()
if err != nil {
log.Error().Err(err).Msg("cannot get user list")
os.Exit(1)
}
for _, user := range users {
log.Info().Str("username", user.Username).Msg("")
}
}
func deleteUserCmdF(cmd *cobra.Command, args []string) {
config, _ := cmd.Flags().GetString("config")
srv, err := server.NewServerWithConfigPath(config)
if err != nil {
log.Error().Err(err).Msg("cannot create server")
os.Exit(1)
}
defer srv.Store.Close()
if err := srv.App.DeleteUserByUsername(args[0]); err != nil {
log.Error().Err(err).Str("username", args[0]).Msg("cannot delete user")
os.Exit(1)
}
log.Info().Str("username", args[0]).Msg("user successfully deleted")
}

View file

@ -6,6 +6,7 @@ import (
"time"
"git.ctrlz.es/mgdelacroix/craban/api"
"git.ctrlz.es/mgdelacroix/craban/app"
"git.ctrlz.es/mgdelacroix/craban/model"
"git.ctrlz.es/mgdelacroix/craban/services/store"
"git.ctrlz.es/mgdelacroix/craban/web"
@ -22,6 +23,8 @@ func init() {
type Server struct {
Config *model.Config
App *app.App
API *api.API
Store *store.Store
WebServer *web.WebServer
}
@ -43,17 +46,18 @@ func NewServer(config *model.Config) (*Server, error) {
}
log.Debug().Msg("store created")
webAPI, err := api.NewAPI(store)
if err != nil {
return nil, fmt.Errorf("cannot create API: %w", err)
}
app := app.NewApp(config, store)
log.Debug().Msg("app created")
api := api.NewAPI(app)
log.Debug().Msg("API created")
webserver.RegisterRoutes(webAPI)
webserver.RegisterRoutes(api)
log.Debug().Msg("webserver routes registered with the API")
return &Server{
Config: config,
WebServer: webserver,
App: app,
API: api,
Store: store,
}, err
}

View file

@ -85,3 +85,32 @@ func (us *UserStore) Create(user *model.User) (*model.User, error) {
return us.GetByID(int(id))
}
// ToDo: add pagination and filtering
func (us *UserStore) List() ([]*model.User, error) {
rows, err := us.Q().Select(userColumns...).
From("users").
Query()
if err != nil {
return nil, err
}
defer rows.Close()
users, err := us.usersFromRows(rows)
if err != nil {
return nil, err
}
if len(users) == 0 {
return nil, sql.ErrNoRows
}
return users, nil
}
func (us *UserStore) DeleteByUsername(username string) error {
_, err := us.Q().Delete("users").
Where(sq.Eq{"username": username}).
Exec()
return err
}