feat(init): First commit
This commit is contained in:
commit
f92368748a
22 changed files with 1298 additions and 0 deletions
417
pkg/cmd/dkimkey.go
Normal file
417
pkg/cmd/dkimkey.go
Normal file
|
@ -0,0 +1,417 @@
|
|||
package cmd
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
|
||||
"git.maurice.fr/thomas/mailout/pkg/crypto"
|
||||
"git.maurice.fr/thomas/mailout/pkg/database"
|
||||
"git.maurice.fr/thomas/mailout/pkg/models"
|
||||
"git.maurice.fr/thomas/mailout/pkg/providers/ovh"
|
||||
"git.maurice.fr/thomas/mailout/pkg/utils"
|
||||
"github.com/google/uuid"
|
||||
"github.com/pterm/pterm"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var (
|
||||
flagDKIMKeyActive bool
|
||||
flagSelector string
|
||||
flagKeyBits int
|
||||
)
|
||||
|
||||
var DKIMKeyCmd = &cobra.Command{
|
||||
Use: "dkimkey",
|
||||
Short: "manages DKIM keys",
|
||||
}
|
||||
|
||||
var DKIMKeyAddCmd = &cobra.Command{
|
||||
Use: "add [domain]",
|
||||
Short: "adds a DKIM signing key",
|
||||
Args: cobra.ExactArgs(1),
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
db, err := database.NewDB(cfg)
|
||||
if err != nil {
|
||||
logrus.WithError(err).Fatal("could not connect to the database")
|
||||
}
|
||||
|
||||
priv, pub, err := crypto.GenerateKeyPair(flagKeyBits)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
selector := flagSelector
|
||||
if selector == "" {
|
||||
b := make([]byte, 8)
|
||||
_, err := rand.Read(b)
|
||||
if err != nil {
|
||||
logrus.Fatal("entropy generator is kill")
|
||||
}
|
||||
|
||||
selector = hex.EncodeToString(b)
|
||||
}
|
||||
|
||||
dkimkey := models.DKIMKey{
|
||||
DomainName: args[0],
|
||||
PublicKey: pub,
|
||||
PrivateKey: priv,
|
||||
Active: flagUserActive,
|
||||
Selector: selector,
|
||||
Record: fmt.Sprintf("%s._domainkey.%s. IN TXT \"v=DKIM1; k=rsa; p=%s\"", selector, args[0], pub),
|
||||
}
|
||||
err = db.Save(&dkimkey).Error
|
||||
|
||||
if err != nil {
|
||||
logrus.WithError(err).Fatal("could not create DKIM key")
|
||||
}
|
||||
|
||||
logrus.Infof("created DKIM key %s", dkimkey.ID)
|
||||
},
|
||||
}
|
||||
|
||||
var DKIMKeyListCmd = &cobra.Command{
|
||||
Use: "list",
|
||||
Short: "list DKIM keys",
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
db, err := database.NewDB(cfg)
|
||||
if err != nil {
|
||||
logrus.WithError(err).Fatal("could not connect to the database")
|
||||
}
|
||||
|
||||
qRes := make([]models.DKIMKey, 0)
|
||||
|
||||
err = db.Find(&qRes).Error
|
||||
if err != nil {
|
||||
logrus.WithError(err).Fatal("could not list keys")
|
||||
}
|
||||
|
||||
tData := pterm.TableData{
|
||||
{"id", "selector", "domain", "active", "created_at", "updated_at"},
|
||||
}
|
||||
for _, k := range qRes {
|
||||
tData = append(tData, []string{k.ID.String(), k.Selector, k.DomainName, fmt.Sprintf("%v", k.Active), k.CreatedAt.String(), k.UpdatedAt.String()})
|
||||
}
|
||||
|
||||
pterm.DefaultTable.WithHasHeader().WithData(tData).Render()
|
||||
},
|
||||
}
|
||||
|
||||
var DKIMKeyRecordCmd = &cobra.Command{
|
||||
Use: "record",
|
||||
Short: "gives the dns record for a key",
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
db, err := database.NewDB(cfg)
|
||||
if err != nil {
|
||||
logrus.WithError(err).Fatal("could not connect to the database")
|
||||
}
|
||||
|
||||
qRes := make([]models.DKIMKey, 0)
|
||||
|
||||
id, err := uuid.Parse(args[0])
|
||||
if err != nil {
|
||||
logrus.WithError(err).Fatal("invalid UUID")
|
||||
}
|
||||
|
||||
err = db.Where(models.DKIMKey{ID: id}).Find(&qRes).Error
|
||||
if err != nil {
|
||||
logrus.WithError(err).Fatal("could not search keys")
|
||||
}
|
||||
if len(qRes) == 0 {
|
||||
logrus.WithError(err).Fatal("No such key")
|
||||
}
|
||||
|
||||
fmt.Println(qRes[0].Record)
|
||||
},
|
||||
}
|
||||
|
||||
var DKIMKeyDeleteCmd = &cobra.Command{
|
||||
Use: "delete",
|
||||
Short: "delete DKIM keys",
|
||||
Args: cobra.ExactArgs(1),
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
db, err := database.NewDB(cfg)
|
||||
if err != nil {
|
||||
logrus.WithError(err).Fatal("could not connect to the database")
|
||||
}
|
||||
|
||||
id, err := uuid.Parse(args[0])
|
||||
if err != nil {
|
||||
logrus.WithError(err).Fatal("invalid UUID")
|
||||
}
|
||||
err = db.Where(&models.DKIMKey{ID: id}).Delete(&models.DKIMKey{}).Error
|
||||
if err != nil {
|
||||
logrus.WithError(err).Fatal("could not delete DKIM key")
|
||||
}
|
||||
|
||||
logrus.Infof("deleted DKIM key %s if it existed", args[0])
|
||||
},
|
||||
}
|
||||
|
||||
var DKIMKeyActivateCmd = &cobra.Command{
|
||||
Use: "activate",
|
||||
Short: "activates a DKIM key",
|
||||
Args: cobra.ExactArgs(1),
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
db, err := database.NewDB(cfg)
|
||||
if err != nil {
|
||||
logrus.WithError(err).Fatal("could not connect to the database")
|
||||
}
|
||||
|
||||
id, err := uuid.Parse(args[0])
|
||||
if err != nil {
|
||||
logrus.WithError(err).Fatal("invalid UUID")
|
||||
}
|
||||
|
||||
err = db.Model(&models.DKIMKey{}).Where(&models.DKIMKey{ID: id}).Update("active", true).Error
|
||||
if err != nil {
|
||||
logrus.WithError(err).Fatal("could not activate DKIM key")
|
||||
}
|
||||
|
||||
logrus.Infof("activated DKIM key %s", args[0])
|
||||
},
|
||||
}
|
||||
|
||||
var DKIMKeyDeactivateCmd = &cobra.Command{
|
||||
Use: "deactivate",
|
||||
Short: "deactivates a DKIM key",
|
||||
Args: cobra.ExactArgs(1),
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
db, err := database.NewDB(cfg)
|
||||
if err != nil {
|
||||
logrus.WithError(err).Fatal("could not connect to the database")
|
||||
}
|
||||
|
||||
id, err := uuid.Parse(args[0])
|
||||
if err != nil {
|
||||
logrus.WithError(err).Fatal("invalid UUID")
|
||||
}
|
||||
|
||||
err = db.Model(&models.DKIMKey{}).Where(&models.DKIMKey{ID: id}).Update("active", false).Error
|
||||
if err != nil {
|
||||
logrus.WithError(err).Fatal("could not deactivate DKIM key")
|
||||
}
|
||||
|
||||
logrus.Infof("deactivated DKIM key %s", args[0])
|
||||
},
|
||||
}
|
||||
|
||||
var DKIMKeyPublishCmd = &cobra.Command{
|
||||
Use: "publish",
|
||||
Short: "publishes a DKIM key onto a DNS provider",
|
||||
Args: cobra.ExactArgs(1),
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
db, err := database.NewDB(cfg)
|
||||
if err != nil {
|
||||
logrus.WithError(err).Fatal("could not connect to the database")
|
||||
}
|
||||
|
||||
qRes := make([]models.DKIMKey, 0)
|
||||
|
||||
id, err := uuid.Parse(args[0])
|
||||
if err != nil {
|
||||
logrus.WithError(err).Fatal("invalid UUID")
|
||||
}
|
||||
|
||||
err = db.Where(models.DKIMKey{ID: id}).Find(&qRes).Error
|
||||
if err != nil {
|
||||
logrus.WithError(err).Fatal("could not get key")
|
||||
}
|
||||
if len(qRes) == 0 {
|
||||
logrus.WithError(err).Fatal("No such key")
|
||||
}
|
||||
|
||||
dkimkey := qRes[0]
|
||||
logger := logrus.WithFields(logrus.Fields{
|
||||
"dkimkey": dkimkey.ID,
|
||||
"selector": dkimkey.Selector,
|
||||
})
|
||||
|
||||
ovhClient, err := ovh.NewOVHProvider(cfg)
|
||||
if err != nil {
|
||||
logger.WithError(err).Fatal("could not get OVH DNS provider")
|
||||
}
|
||||
|
||||
zone, err := utils.GetZone(dkimkey.DomainName)
|
||||
if err != nil {
|
||||
logger.WithError(err).Fatal("could not determine zone")
|
||||
}
|
||||
subdomain, err := utils.GetSubdomain(dkimkey.DomainName)
|
||||
if err != nil {
|
||||
logger.WithError(err).Fatal("could not determine subdomain")
|
||||
}
|
||||
|
||||
if subdomain == "" {
|
||||
subdomain = zone
|
||||
}
|
||||
|
||||
logger = logger.WithFields(logrus.Fields{
|
||||
"zone": zone,
|
||||
"subdomain": subdomain,
|
||||
})
|
||||
|
||||
dkimSub := fmt.Sprintf("%s._domainkey.%s", dkimkey.Selector, subdomain)
|
||||
result := make([]int, 0)
|
||||
|
||||
err = ovhClient.Client.Get(fmt.Sprintf("/domain/zone/%s/record?fieldType=TXT&subDomain=%s", zone, dkimSub), &result)
|
||||
|
||||
if err != nil {
|
||||
logger.WithError(err).Fatal("could not lookup records")
|
||||
}
|
||||
|
||||
type createParams struct {
|
||||
FieldType string `json:"fieldType"`
|
||||
SubDomain string `json:"subDomain"`
|
||||
Target string `json:"target"`
|
||||
TTL int `json:"ttl"`
|
||||
}
|
||||
|
||||
type updateParams struct {
|
||||
SubDomain string `json:"subDomain"`
|
||||
Target string `json:"target"`
|
||||
TTL int `json:"ttl"`
|
||||
}
|
||||
|
||||
if len(result) == 0 {
|
||||
logger.Info("no DKIM records found, creating a new one")
|
||||
|
||||
c := createParams{
|
||||
FieldType: "TXT",
|
||||
SubDomain: fmt.Sprintf("%s._domainkey.%s", dkimkey.Selector, subdomain),
|
||||
Target: fmt.Sprintf("\"v=DKIM1; k=rsa; p=%s\"", dkimkey.PublicKey),
|
||||
TTL: 60,
|
||||
}
|
||||
|
||||
err = ovhClient.Client.Post(fmt.Sprintf("/domain/zone/%s/record", zone), &c, nil)
|
||||
if err != nil {
|
||||
logger.WithError(err).Fatal("could not create new record")
|
||||
}
|
||||
logger.Info("created new DKIM record")
|
||||
|
||||
err = ovhClient.Client.Post(fmt.Sprintf("/domain/zone/%s/refresh", zone), nil, nil)
|
||||
if err != nil {
|
||||
logger.WithError(err).Fatal("could not refresh the zone")
|
||||
}
|
||||
logger.Info("refreshed zone")
|
||||
} else if len(result) == 1 {
|
||||
logger.Info("found one record, updating it")
|
||||
|
||||
u := updateParams{
|
||||
SubDomain: fmt.Sprintf("%s._domainkey.%s", dkimkey.Selector, subdomain),
|
||||
Target: fmt.Sprintf("\"v=DKIM1; k=foo; p=%s\"", dkimkey.PublicKey),
|
||||
TTL: 60,
|
||||
}
|
||||
|
||||
err = ovhClient.Client.Put(fmt.Sprintf("/domain/zone/%s/record/%d", zone, result[0]), &u, nil)
|
||||
if err != nil {
|
||||
logger.WithError(err).Fatal("could not update record")
|
||||
}
|
||||
logger.Info("updated existing record")
|
||||
|
||||
err = ovhClient.Client.Post(fmt.Sprintf("/domain/zone/%s/refresh", zone), nil, nil)
|
||||
if err != nil {
|
||||
logger.WithError(err).Fatal("could not refresh the zone")
|
||||
}
|
||||
logger.Info("refreshed zone")
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
var DKIMKeyUnpublishCmd = &cobra.Command{
|
||||
Use: "unpublish",
|
||||
Short: "removes a DKIM key onto a DNS provider",
|
||||
Args: cobra.ExactArgs(1),
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
db, err := database.NewDB(cfg)
|
||||
if err != nil {
|
||||
logrus.WithError(err).Fatal("could not connect to the database")
|
||||
}
|
||||
|
||||
qRes := make([]models.DKIMKey, 0)
|
||||
|
||||
id, err := uuid.Parse(args[0])
|
||||
if err != nil {
|
||||
logrus.WithError(err).Fatal("invalid UUID")
|
||||
}
|
||||
|
||||
err = db.Where(models.DKIMKey{ID: id}).Find(&qRes).Error
|
||||
if err != nil {
|
||||
logrus.WithError(err).Fatal("could not get key")
|
||||
}
|
||||
if len(qRes) == 0 {
|
||||
logrus.WithError(err).Fatal("No such key")
|
||||
}
|
||||
|
||||
dkimkey := qRes[0]
|
||||
logger := logrus.WithFields(logrus.Fields{
|
||||
"dkimkey": dkimkey.ID,
|
||||
"selector": dkimkey.Selector,
|
||||
})
|
||||
|
||||
ovhClient, err := ovh.NewOVHProvider(cfg)
|
||||
if err != nil {
|
||||
logger.WithError(err).Fatal("could not get OVH DNS provider")
|
||||
}
|
||||
|
||||
zone, err := utils.GetZone(dkimkey.DomainName)
|
||||
if err != nil {
|
||||
logger.WithError(err).Fatal("could not determine zone")
|
||||
}
|
||||
subdomain, err := utils.GetSubdomain(dkimkey.DomainName)
|
||||
if err != nil {
|
||||
logger.WithError(err).Fatal("could not determine subdomain")
|
||||
}
|
||||
|
||||
if subdomain == "" {
|
||||
subdomain = zone
|
||||
}
|
||||
|
||||
logger = logger.WithFields(logrus.Fields{
|
||||
"zone": zone,
|
||||
"subdomain": subdomain,
|
||||
})
|
||||
|
||||
dkimSub := fmt.Sprintf("%s._domainkey.%s", dkimkey.Selector, subdomain)
|
||||
result := make([]int, 0)
|
||||
|
||||
err = ovhClient.Client.Get(fmt.Sprintf("/domain/zone/%s/record?fieldType=TXT&subDomain=%s", zone, dkimSub), &result)
|
||||
|
||||
if err != nil {
|
||||
logger.WithError(err).Fatal("could not lookup records")
|
||||
}
|
||||
|
||||
if len(result) == 0 {
|
||||
logger.Info("no DKIM records found, no need to do anything")
|
||||
} else if len(result) == 1 {
|
||||
logger.Info("found one record, deleting it")
|
||||
|
||||
err = ovhClient.Client.Delete(fmt.Sprintf("/domain/zone/%s/record/%d", zone, result[0]), nil)
|
||||
if err != nil {
|
||||
logger.WithError(err).Fatal("could not delete record")
|
||||
}
|
||||
logger.Info("deleted existing record")
|
||||
|
||||
err = ovhClient.Client.Post(fmt.Sprintf("/domain/zone/%s/refresh", zone), nil, nil)
|
||||
if err != nil {
|
||||
logger.WithError(err).Fatal("could not refresh the zone")
|
||||
}
|
||||
logger.Info("refreshed zone")
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
func InitDKIMKeyCmd() {
|
||||
DKIMKeyCmd.AddCommand(DKIMKeyAddCmd)
|
||||
DKIMKeyCmd.AddCommand(DKIMKeyListCmd)
|
||||
DKIMKeyCmd.AddCommand(DKIMKeyDeleteCmd)
|
||||
DKIMKeyCmd.AddCommand(DKIMKeyActivateCmd)
|
||||
DKIMKeyCmd.AddCommand(DKIMKeyDeactivateCmd)
|
||||
DKIMKeyCmd.AddCommand(DKIMKeyRecordCmd)
|
||||
DKIMKeyCmd.AddCommand(DKIMKeyPublishCmd)
|
||||
DKIMKeyCmd.AddCommand(DKIMKeyUnpublishCmd)
|
||||
|
||||
DKIMKeyAddCmd.PersistentFlags().BoolVarP(&flagDKIMKeyActive, "active", "a", true, "whether or not the created key is active")
|
||||
DKIMKeyAddCmd.PersistentFlags().StringVarP(&flagSelector, "selector", "s", "", "force a selector for the key")
|
||||
DKIMKeyAddCmd.PersistentFlags().IntVarP(&flagKeyBits, "key-bits", "k", 2048, "force a size for the key")
|
||||
}
|
25
pkg/cmd/initdb.go
Normal file
25
pkg/cmd/initdb.go
Normal file
|
@ -0,0 +1,25 @@
|
|||
package cmd
|
||||
|
||||
import (
|
||||
"git.maurice.fr/thomas/mailout/pkg/database"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var InitDBCmd = &cobra.Command{
|
||||
Use: "initdb",
|
||||
Short: "initialises the database",
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
db, err := database.NewDB(cfg)
|
||||
if err != nil {
|
||||
logrus.WithError(err).Fatal("could not connect to the database")
|
||||
}
|
||||
|
||||
err = database.InitMigrate(db)
|
||||
if err != nil {
|
||||
logrus.WithError(err).Fatal("could not initialise the database")
|
||||
}
|
||||
|
||||
logrus.Info("successfully initialised the database")
|
||||
},
|
||||
}
|
48
pkg/cmd/root.go
Normal file
48
pkg/cmd/root.go
Normal file
|
@ -0,0 +1,48 @@
|
|||
package cmd
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"git.maurice.fr/thomas/mailout/pkg/config"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var (
|
||||
configFile string
|
||||
cfg *config.Config
|
||||
)
|
||||
|
||||
var RootCmd = &cobra.Command{
|
||||
Use: "mailoutctl",
|
||||
Short: "mailout management utility",
|
||||
PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
|
||||
var err error
|
||||
cfg, err = config.LoadConfig(configFile)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
var VersionCmd = &cobra.Command{
|
||||
Use: "version",
|
||||
Short: "Print the version number",
|
||||
Long: ``,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
fmt.Println("v0.0.1")
|
||||
},
|
||||
}
|
||||
|
||||
func InitRootCmd() {
|
||||
InitUserCmd()
|
||||
InitDKIMKeyCmd()
|
||||
|
||||
RootCmd.AddCommand(VersionCmd)
|
||||
RootCmd.AddCommand(InitDBCmd)
|
||||
RootCmd.AddCommand(UserCmd)
|
||||
RootCmd.AddCommand(DKIMKeyCmd)
|
||||
|
||||
RootCmd.PersistentFlags().StringVarP(&configFile, "config", "c", "mailout.yml", "Configuration file")
|
||||
}
|
193
pkg/cmd/user.go
Normal file
193
pkg/cmd/user.go
Normal file
|
@ -0,0 +1,193 @@
|
|||
package cmd
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"git.maurice.fr/thomas/mailout/pkg/database"
|
||||
"git.maurice.fr/thomas/mailout/pkg/models"
|
||||
"github.com/pterm/pterm"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/spf13/cobra"
|
||||
"golang.org/x/crypto/bcrypt"
|
||||
)
|
||||
|
||||
var (
|
||||
flagUserActive bool
|
||||
)
|
||||
|
||||
var UserCmd = &cobra.Command{
|
||||
Use: "user",
|
||||
Short: "manages users",
|
||||
}
|
||||
|
||||
var UserAddCmd = &cobra.Command{
|
||||
Use: "add [user_address] [password]",
|
||||
Short: "adds a user",
|
||||
Args: cobra.ExactArgs(2),
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
db, err := database.NewDB(cfg)
|
||||
if err != nil {
|
||||
logrus.WithError(err).Fatal("could not connect to the database")
|
||||
}
|
||||
|
||||
username, domain, err := splitUser(args[0])
|
||||
if err != nil {
|
||||
logrus.WithError(err).Fatal("could not parse user")
|
||||
}
|
||||
|
||||
qRes := make([]models.User, 0)
|
||||
var user models.User
|
||||
userExists := false
|
||||
logger := logrus.WithField("user", args[0])
|
||||
|
||||
err = db.Where(&models.User{Domain: domain, Username: username}).Find(&qRes).Error
|
||||
if err != nil {
|
||||
logger.WithError(err).Fatal("could not check user's existence")
|
||||
}
|
||||
|
||||
if len(qRes) == 0 {
|
||||
userExists = false
|
||||
} else {
|
||||
logger.Warning("user already exists, it's password will be updated")
|
||||
user = qRes[0]
|
||||
userExists = true
|
||||
}
|
||||
|
||||
passwordHash, err := bcrypt.GenerateFromPassword([]byte(args[1]), bcrypt.DefaultCost)
|
||||
if err != nil {
|
||||
logger.WithError(err).Fatal("could not compute user password hash")
|
||||
}
|
||||
|
||||
if userExists {
|
||||
err = db.Model(&models.User{}).Where(&user).Update("password", fmt.Sprintf("{BLF-CRYPT}%s", string(passwordHash))).Error
|
||||
if err != nil {
|
||||
logger.WithError(err).Fatal("could not update user password")
|
||||
}
|
||||
logger.Infof("updated user %s", user.ID)
|
||||
return
|
||||
}
|
||||
|
||||
user = models.User{
|
||||
Username: username,
|
||||
Domain: domain,
|
||||
Active: flagUserActive,
|
||||
Password: fmt.Sprintf("{BLF-CRYPT}%s", string(passwordHash)),
|
||||
}
|
||||
err = db.Save(&user).Error
|
||||
|
||||
if err != nil {
|
||||
logger.WithError(err).Fatal("could not create user")
|
||||
}
|
||||
|
||||
logger.Infof("created user %s", user.ID)
|
||||
},
|
||||
}
|
||||
|
||||
var UserListCmd = &cobra.Command{
|
||||
Use: "list",
|
||||
Short: "list users",
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
db, err := database.NewDB(cfg)
|
||||
if err != nil {
|
||||
logrus.WithError(err).Fatal("could not connect to the database")
|
||||
}
|
||||
|
||||
qRes := make([]models.User, 0)
|
||||
|
||||
err = db.Find(&qRes).Error
|
||||
if err != nil {
|
||||
logrus.WithError(err).Fatal("could not list users")
|
||||
}
|
||||
|
||||
tData := pterm.TableData{
|
||||
{"id", "username", "domain", "active", "uid", "gid", "created_at", "updated_at"},
|
||||
}
|
||||
for _, u := range qRes {
|
||||
tData = append(tData, []string{u.ID.String(), u.Username, u.Domain, fmt.Sprintf("%v", u.Active), fmt.Sprintf("%d", u.UID), fmt.Sprintf("%d", u.GID), u.CreatedAt.String(), u.UpdatedAt.String()})
|
||||
}
|
||||
|
||||
pterm.DefaultTable.WithHasHeader().WithData(tData).Render()
|
||||
},
|
||||
}
|
||||
|
||||
var UserDeleteCmd = &cobra.Command{
|
||||
Use: "delete",
|
||||
Short: "delete users",
|
||||
Args: cobra.ExactArgs(1),
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
db, err := database.NewDB(cfg)
|
||||
if err != nil {
|
||||
logrus.WithError(err).Fatal("could not connect to the database")
|
||||
}
|
||||
|
||||
userQuery, err := buildUserQuery(args[0])
|
||||
if err != nil {
|
||||
logrus.WithError(err).Fatal("unable to determine user")
|
||||
}
|
||||
|
||||
err = db.Where(&userQuery).Delete(&models.User{}).Error
|
||||
if err != nil {
|
||||
logrus.WithError(err).Fatal("could not delete user")
|
||||
}
|
||||
|
||||
logrus.Infof("deleted user %s if it existed", args[0])
|
||||
},
|
||||
}
|
||||
|
||||
var UserActivateCmd = &cobra.Command{
|
||||
Use: "activate",
|
||||
Short: "activates a user",
|
||||
Args: cobra.ExactArgs(1),
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
db, err := database.NewDB(cfg)
|
||||
if err != nil {
|
||||
logrus.WithError(err).Fatal("could not connect to the database")
|
||||
}
|
||||
|
||||
userQuery, err := buildUserQuery(args[0])
|
||||
if err != nil {
|
||||
logrus.WithError(err).Fatal("unable to determine user")
|
||||
}
|
||||
|
||||
err = db.Model(&models.User{}).Where(&userQuery).Update("active", true).Error
|
||||
if err != nil {
|
||||
logrus.WithError(err).Fatal("could not activate user")
|
||||
}
|
||||
|
||||
logrus.Infof("activated user %s", args[0])
|
||||
},
|
||||
}
|
||||
|
||||
var UserDeactivateCmd = &cobra.Command{
|
||||
Use: "deactivate",
|
||||
Short: "deactivates a user",
|
||||
Args: cobra.ExactArgs(1),
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
db, err := database.NewDB(cfg)
|
||||
if err != nil {
|
||||
logrus.WithError(err).Fatal("could not connect to the database")
|
||||
}
|
||||
|
||||
userQuery, err := buildUserQuery(args[0])
|
||||
if err != nil {
|
||||
logrus.WithError(err).Fatal("unable to determine user")
|
||||
}
|
||||
|
||||
err = db.Model(&models.User{}).Where(&userQuery).Update("active", false).Error
|
||||
if err != nil {
|
||||
logrus.WithError(err).Fatal("could not deactivate user")
|
||||
}
|
||||
|
||||
logrus.Infof("deactivated user %s", args[0])
|
||||
},
|
||||
}
|
||||
|
||||
func InitUserCmd() {
|
||||
UserCmd.AddCommand(UserAddCmd)
|
||||
UserCmd.AddCommand(UserListCmd)
|
||||
UserCmd.AddCommand(UserDeleteCmd)
|
||||
UserCmd.AddCommand(UserActivateCmd)
|
||||
UserCmd.AddCommand(UserDeactivateCmd)
|
||||
|
||||
UserAddCmd.PersistentFlags().BoolVarP(&flagUserActive, "active", "a", true, "whether or not the created user is active")
|
||||
}
|
45
pkg/cmd/utils.go
Normal file
45
pkg/cmd/utils.go
Normal file
|
@ -0,0 +1,45 @@
|
|||
package cmd
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"git.maurice.fr/thomas/mailout/pkg/models"
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
var (
|
||||
uuidRegex = regexp.MustCompile("^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$")
|
||||
)
|
||||
|
||||
func splitUser(user string) (string, string, error) {
|
||||
splt := strings.Split(user, "@")
|
||||
if len(splt) != 2 {
|
||||
return "", "", fmt.Errorf("invalid username: %s", user)
|
||||
}
|
||||
|
||||
if len(splt[0]) == 0 || len(splt[1]) == 0 {
|
||||
return "", "", fmt.Errorf("invalid username: %s", user)
|
||||
}
|
||||
|
||||
return splt[0], splt[1], nil
|
||||
}
|
||||
|
||||
func buildUserQuery(arg string) (*models.User, error) {
|
||||
var userQuery models.User
|
||||
if uuidRegex.Match([]byte(arg)) {
|
||||
id, err := uuid.Parse(arg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
userQuery.ID = id
|
||||
} else {
|
||||
username, domain, err := splitUser(arg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
userQuery = models.User{Domain: domain, Username: username}
|
||||
}
|
||||
return &userQuery, nil
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue