updated vmail
This commit is contained in:
parent
3e8fc9f73e
commit
688846b6c9
1
go.mod
1
go.mod
@ -3,6 +3,7 @@ module git.paulbsd.com/paulbsd/vmail
|
|||||||
go 1.14
|
go 1.14
|
||||||
|
|
||||||
require (
|
require (
|
||||||
|
github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d
|
||||||
github.com/labstack/echo v3.3.10+incompatible // indirect
|
github.com/labstack/echo v3.3.10+incompatible // indirect
|
||||||
github.com/labstack/echo/v4 v4.1.16
|
github.com/labstack/echo/v4 v4.1.16
|
||||||
github.com/lib/pq v1.7.0
|
github.com/lib/pq v1.7.0
|
||||||
|
2
go.sum
2
go.sum
@ -8,6 +8,8 @@ github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWX
|
|||||||
github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI=
|
github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI=
|
||||||
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
||||||
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
||||||
|
github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d h1:UQZhZ2O0vMHr2cI+DC1Mbh0TJxzA3RcLoMsFw+aXw7E=
|
||||||
|
github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho=
|
||||||
github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ=
|
github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ=
|
||||||
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
|
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
|
||||||
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
||||||
|
12
src/api/admin.go
Normal file
12
src/api/admin.go
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
package api
|
||||||
|
|
||||||
|
// Admin defines the admin struct
|
||||||
|
type Admin struct {
|
||||||
|
Username string `json:"username"`
|
||||||
|
Created string `json:"created"`
|
||||||
|
Modified string `json:"modified"`
|
||||||
|
Active bool `json:"active"`
|
||||||
|
Superadmin bool `json:"superadmin"`
|
||||||
|
Phone string `json:"phone"`
|
||||||
|
EmailOther string `json:"emailOther"`
|
||||||
|
}
|
11
src/api/alias.go
Normal file
11
src/api/alias.go
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
package api
|
||||||
|
|
||||||
|
// Alias defines the admin struct
|
||||||
|
type Alias struct {
|
||||||
|
Address string `json:"address"`
|
||||||
|
Goto string `json:"goto"`
|
||||||
|
Domain string `json:"domain"`
|
||||||
|
Created string `json:"created"`
|
||||||
|
Modified string `json:"modified"`
|
||||||
|
Active bool `json:"active"`
|
||||||
|
}
|
11
src/api/log.go
Normal file
11
src/api/log.go
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
package api
|
||||||
|
|
||||||
|
// Log defines the admin struct
|
||||||
|
type Log struct {
|
||||||
|
ID int `json:"id"`
|
||||||
|
Timestamp string `json:"timestamp"`
|
||||||
|
Username string `json:"username"`
|
||||||
|
Domain string `json:"domain"`
|
||||||
|
Action string `json:"action"`
|
||||||
|
Data string `json:"data"`
|
||||||
|
}
|
16
src/api/mailbox.go
Normal file
16
src/api/mailbox.go
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
package api
|
||||||
|
|
||||||
|
// Mailbox defines the admin struct
|
||||||
|
type Mailbox struct {
|
||||||
|
Username string `json:"username"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
Maildir string `json:"maildir"`
|
||||||
|
Quota string `json:"quota"`
|
||||||
|
Created string `json:"created"`
|
||||||
|
Modified string `json:"modified"`
|
||||||
|
Active bool `json:"active"`
|
||||||
|
Domain string `json:"domain"`
|
||||||
|
LocalPart string `json:"localpart"`
|
||||||
|
Phone string `json:"phone"`
|
||||||
|
EmailOther string `json:"emailother"`
|
||||||
|
}
|
@ -40,14 +40,13 @@ func (config *Config) GetConfig() error {
|
|||||||
|
|
||||||
// Config is the global config of vmail
|
// Config is the global config of vmail
|
||||||
type Config struct {
|
type Config struct {
|
||||||
Db *xorm.Engine
|
Db *xorm.Engine
|
||||||
DbHostname string
|
DbHostname string
|
||||||
DbName string
|
DbName string
|
||||||
DbUsername string
|
DbUsername string
|
||||||
DbPassword string
|
DbPassword string
|
||||||
URLBase string
|
URLBase string
|
||||||
vmailGroups []string
|
Port int
|
||||||
Port int
|
Init bool
|
||||||
Init bool
|
Version string
|
||||||
Version string
|
|
||||||
}
|
}
|
||||||
|
@ -20,7 +20,7 @@ func Initialize(ctx *context.Context, config *config.Config) (err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
config.Db.SetMapper(names.GonicMapper{})
|
config.Db.SetMapper(names.GonicMapper{})
|
||||||
config.Db.ShowSQL(false)
|
config.Db.ShowSQL(true)
|
||||||
|
|
||||||
err = models.NewEngine(ctx, config)
|
err = models.NewEngine(ctx, config)
|
||||||
|
|
||||||
|
@ -4,25 +4,57 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"git.paulbsd.com/paulbsd/vmail/src/api"
|
||||||
"git.paulbsd.com/paulbsd/vmail/src/config"
|
"git.paulbsd.com/paulbsd/vmail/src/config"
|
||||||
)
|
)
|
||||||
|
|
||||||
// GetAdmins ...
|
// GetAdmins return list of apiadmins
|
||||||
func GetAdmins(ctx *context.Context, config *config.Config) (admins []Admin, err error) {
|
func GetAdmins(ctx *context.Context, config *config.Config) (apiadmins []*api.Admin, err error) {
|
||||||
err = config.Db.Cols("username").Find(&admins)
|
var admins []Admin
|
||||||
|
err = config.Db.Find(&admins)
|
||||||
|
for _, adm := range admins {
|
||||||
|
apiadmins = append(apiadmins, adm.APIFormat())
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetAdmin ...
|
||||||
|
func GetAdmin(ctx *context.Context, config *config.Config, id interface{}) (apiadmin *api.Admin, err error) {
|
||||||
|
var admin Admin
|
||||||
|
has, err := config.Db.Where("username = ?", id).Get(&admin)
|
||||||
|
if !has || err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
apiadmin = admin.APIFormat()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// APIFormat returns a JSON formatted object of Admin
|
||||||
|
func (admin *Admin) APIFormat() *api.Admin {
|
||||||
|
if admin == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return &api.Admin{
|
||||||
|
Username: admin.Username,
|
||||||
|
Created: admin.Created.Format(timetostring),
|
||||||
|
Modified: admin.Modified.Format(timetostring),
|
||||||
|
Active: admin.Active,
|
||||||
|
Superadmin: admin.Superadmin,
|
||||||
|
Phone: admin.Phone,
|
||||||
|
EmailOther: admin.EmailOther,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Admin defines the admin struct
|
// Admin defines the admin struct
|
||||||
type Admin struct {
|
type Admin struct {
|
||||||
Username string `xorm:"not null pk unique VARCHAR(255)"`
|
Username string `xorm:"not null pk unique VARCHAR(255)"`
|
||||||
password string `xorm:"not null default '' VARCHAR(255)"`
|
Password string `xorm:"not null default '' VARCHAR(255)"`
|
||||||
Created time.Time `xorm:"default now() TIMESTAMPZ"`
|
Created time.Time `xorm:"default now() TIMESTAMPZ"`
|
||||||
Modified time.Time `xorm:"default now() TIMESTAMPZ"`
|
Modified time.Time `xorm:"default now() TIMESTAMPZ"`
|
||||||
Active bool `xorm:"not null default true BOOL"`
|
Active bool `xorm:"not null default true BOOL"`
|
||||||
Superadmin bool `xorm:"not null default false BOOL"`
|
Superadmin bool `xorm:"not null default false BOOL"`
|
||||||
Phone string `xorm:"not null default '' VARCHAR(30)"`
|
Phone string `xorm:"not null default '' VARCHAR(30)"`
|
||||||
EmailOther string `xorm:"not null default '' VARCHAR(255)"`
|
EmailOther string `xorm:"not null default '' VARCHAR(255)"`
|
||||||
token string `xorm:"not null default '' VARCHAR(255)"`
|
Token string `xorm:"not null default '' VARCHAR(255)"`
|
||||||
tokenValidity time.Time `xorm:"default '2000-01-01 00:00:00+01' TIMESTAMPZ"`
|
TokenValidity time.Time `xorm:"default '2000-01-01 00:00:00+01' TIMESTAMPZ"`
|
||||||
}
|
}
|
||||||
|
@ -4,15 +4,46 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"git.paulbsd.com/paulbsd/vmail/src/api"
|
||||||
"git.paulbsd.com/paulbsd/vmail/src/config"
|
"git.paulbsd.com/paulbsd/vmail/src/config"
|
||||||
)
|
)
|
||||||
|
|
||||||
// GetAliases ...
|
// GetAliases ...
|
||||||
func GetAliases(ctx *context.Context, config *config.Config) (aliases []Alias, err error) {
|
func GetAliases(ctx *context.Context, config *config.Config) (apialiases []*api.Alias, err error) {
|
||||||
err = config.Db.Cols("address").Find(&aliases)
|
var aliases []Alias
|
||||||
|
err = config.Db.Find(&aliases)
|
||||||
|
for _, al := range aliases {
|
||||||
|
apialiases = append(apialiases, al.APIFormat())
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetAlias ...
|
||||||
|
func GetAlias(ctx *context.Context, config *config.Config, id interface{}) (apialias *api.Alias, err error) {
|
||||||
|
var alias Alias
|
||||||
|
has, err := config.Db.Where("username = ?", id).Get(&alias)
|
||||||
|
if !has || err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
apialias = alias.APIFormat()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// APIFormat returns a JSON formatted object of Admin
|
||||||
|
func (alias *Alias) APIFormat() *api.Alias {
|
||||||
|
if alias == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return &api.Alias{
|
||||||
|
Address: alias.Address,
|
||||||
|
Goto: alias.Goto,
|
||||||
|
Domain: alias.Domain,
|
||||||
|
Created: alias.Created.Format(timetostring),
|
||||||
|
Modified: alias.Modified.Format(timetostring),
|
||||||
|
Active: alias.Active,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Alias defines the admin struct
|
// Alias defines the admin struct
|
||||||
type Alias struct {
|
type Alias struct {
|
||||||
Address string `xorm:"not null pk index(alias_address_active) unique VARCHAR(255)"`
|
Address string `xorm:"not null pk index(alias_address_active) unique VARCHAR(255)"`
|
||||||
|
@ -1,12 +1,44 @@
|
|||||||
package models
|
package models
|
||||||
|
|
||||||
import "time"
|
import (
|
||||||
|
"context"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"git.paulbsd.com/paulbsd/vmail/src/api"
|
||||||
|
"git.paulbsd.com/paulbsd/vmail/src/config"
|
||||||
|
)
|
||||||
|
|
||||||
|
// GetLogs return list of Log
|
||||||
|
func GetLogs(ctx *context.Context, config *config.Config) (apilogs []*api.Log, err error) {
|
||||||
|
var logs []Log
|
||||||
|
err = config.Db.Find(&logs)
|
||||||
|
for _, log := range logs {
|
||||||
|
apilogs = append(apilogs, log.APIFormat())
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// APIFormat returns a JSON formatted object of Admin
|
||||||
|
func (log *Log) APIFormat() *api.Log {
|
||||||
|
if log == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return &api.Log{
|
||||||
|
Timestamp: log.Timestamp.Format(timetostring),
|
||||||
|
Username: log.Username,
|
||||||
|
Domain: log.Domain,
|
||||||
|
Action: log.Action,
|
||||||
|
Data: log.Data,
|
||||||
|
ID: log.ID,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Log ...
|
||||||
type Log struct {
|
type Log struct {
|
||||||
|
ID int `xorm:"not null pk autoincr INTEGER"`
|
||||||
Timestamp time.Time `xorm:"default now() index(log_domain_timestamp_idx) TIMESTAMPZ"`
|
Timestamp time.Time `xorm:"default now() index(log_domain_timestamp_idx) TIMESTAMPZ"`
|
||||||
Username string `xorm:"not null default '' VARCHAR(255)"`
|
Username string `xorm:"not null default '' VARCHAR(255)"`
|
||||||
Domain string `xorm:"not null default '' index(log_domain_timestamp_idx) VARCHAR(255)"`
|
Domain string `xorm:"not null default '' index(log_domain_timestamp_idx) VARCHAR(255)"`
|
||||||
Action string `xorm:"not null default '' VARCHAR(255)"`
|
Action string `xorm:"not null default '' VARCHAR(255)"`
|
||||||
Data string `xorm:"not null default '' TEXT"`
|
Data string `xorm:"not null default '' TEXT"`
|
||||||
Id int `xorm:"not null pk autoincr INTEGER"`
|
|
||||||
}
|
}
|
||||||
|
@ -4,15 +4,52 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"git.paulbsd.com/paulbsd/vmail/src/api"
|
||||||
"git.paulbsd.com/paulbsd/vmail/src/config"
|
"git.paulbsd.com/paulbsd/vmail/src/config"
|
||||||
)
|
)
|
||||||
|
|
||||||
// GetMailboxes ...
|
// GetMailboxes ...
|
||||||
func GetMailboxes(ctx *context.Context, config *config.Config) (mailboxes []Mailbox, err error) {
|
func GetMailboxes(ctx *context.Context, config *config.Config) (apimailboxes []*api.Mailbox, err error) {
|
||||||
err = config.Db.Cols("username").Find(&mailboxes)
|
var mailboxes []Mailbox
|
||||||
|
err = config.Db.Find(&mailboxes)
|
||||||
|
for _, ml := range mailboxes {
|
||||||
|
apimailboxes = append(apimailboxes, ml.APIFormat())
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetMailbox ...
|
||||||
|
func GetMailbox(ctx *context.Context, config *config.Config, id interface{}) (apimailbox *api.Mailbox, err error) {
|
||||||
|
var mailbox Mailbox
|
||||||
|
has, err := config.Db.Where("username = ?", id).Get(&mailbox)
|
||||||
|
if !has || err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
apimailbox = mailbox.APIFormat()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// APIFormat returns a JSON formatted object of Admin
|
||||||
|
func (mailbox *Mailbox) APIFormat() *api.Mailbox {
|
||||||
|
if mailbox == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return &api.Mailbox{
|
||||||
|
Username: mailbox.Username,
|
||||||
|
Name: mailbox.Name,
|
||||||
|
Maildir: mailbox.Maildir,
|
||||||
|
Quota: quotaFormat(mailbox.Quota),
|
||||||
|
Created: mailbox.Created.Format(timetostring),
|
||||||
|
Modified: mailbox.Modified.Format(timetostring),
|
||||||
|
Active: mailbox.Active,
|
||||||
|
Domain: mailbox.Domain,
|
||||||
|
LocalPart: mailbox.LocalPart,
|
||||||
|
Phone: mailbox.Phone,
|
||||||
|
EmailOther: mailbox.EmailOther,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Mailbox ...
|
||||||
type Mailbox struct {
|
type Mailbox struct {
|
||||||
Username string `xorm:"not null pk unique index(mailbox_username_active) VARCHAR(255)"`
|
Username string `xorm:"not null pk unique index(mailbox_username_active) VARCHAR(255)"`
|
||||||
Password string `xorm:"not null default '' VARCHAR(255)"`
|
Password string `xorm:"not null default '' VARCHAR(255)"`
|
||||||
|
18
src/models/utils.go
Normal file
18
src/models/utils.go
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
package models
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/alecthomas/units"
|
||||||
|
)
|
||||||
|
|
||||||
|
const timetostring = "02/01/2006 15:04"
|
||||||
|
|
||||||
|
func quotaFormat(in int64) (out string) {
|
||||||
|
var converted units.Base2Bytes
|
||||||
|
converted, err := units.ParseBase2Bytes(fmt.Sprintf("%d%s", in, "B"))
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
return converted.String()
|
||||||
|
}
|
@ -23,11 +23,7 @@ func RunServer(ctx *context.Context, cfg *config.Config) (err error) {
|
|||||||
}))
|
}))
|
||||||
|
|
||||||
e.GET("/", func(c echo.Context) (err error) {
|
e.GET("/", func(c echo.Context) (err error) {
|
||||||
return c.HTML(http.StatusOK, "Welcome to Vmail")
|
return c.HTML(http.StatusOK, "Welcome to Vmail API")
|
||||||
})
|
|
||||||
e.GET("menu", func(c echo.Context) (err error) {
|
|
||||||
ret := []string{"admins", "domains", "mailboxes"}
|
|
||||||
return c.JSON(http.StatusOK, ret)
|
|
||||||
})
|
})
|
||||||
e.POST("/auth", func(c echo.Context) (err error) {
|
e.POST("/auth", func(c echo.Context) (err error) {
|
||||||
return c.String(http.StatusOK, "/auth")
|
return c.String(http.StatusOK, "/auth")
|
||||||
@ -36,6 +32,7 @@ func RunServer(ctx *context.Context, cfg *config.Config) (err error) {
|
|||||||
return c.JSON(http.StatusOK, "/api")
|
return c.JSON(http.StatusOK, "/api")
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// Admins
|
||||||
e.GET("/api/admin", func(c echo.Context) (err error) {
|
e.GET("/api/admin", func(c echo.Context) (err error) {
|
||||||
admins, err := models.GetAdmins(ctx, cfg)
|
admins, err := models.GetAdmins(ctx, cfg)
|
||||||
return c.JSON(http.StatusOK, admins)
|
return c.JSON(http.StatusOK, admins)
|
||||||
@ -45,15 +42,7 @@ func RunServer(ctx *context.Context, cfg *config.Config) (err error) {
|
|||||||
return c.JSON(http.StatusOK, admins)
|
return c.JSON(http.StatusOK, admins)
|
||||||
})
|
})
|
||||||
|
|
||||||
e.GET("/api/mailbox", func(c echo.Context) (err error) {
|
// Aliases
|
||||||
mailboxes, err := models.GetMailboxes(ctx, cfg)
|
|
||||||
return c.JSON(http.StatusOK, mailboxes)
|
|
||||||
})
|
|
||||||
e.GET("/api/mailbox/:id", func(c echo.Context) (err error) {
|
|
||||||
mailboxes, err := models.GetMailboxes(ctx, cfg)
|
|
||||||
return c.JSON(http.StatusOK, mailboxes)
|
|
||||||
})
|
|
||||||
|
|
||||||
e.GET("/api/alias", func(c echo.Context) (err error) {
|
e.GET("/api/alias", func(c echo.Context) (err error) {
|
||||||
aliases, err := models.GetAliases(ctx, cfg)
|
aliases, err := models.GetAliases(ctx, cfg)
|
||||||
return c.JSON(http.StatusOK, aliases)
|
return c.JSON(http.StatusOK, aliases)
|
||||||
@ -63,6 +52,22 @@ func RunServer(ctx *context.Context, cfg *config.Config) (err error) {
|
|||||||
return c.JSON(http.StatusOK, aliases)
|
return c.JSON(http.StatusOK, aliases)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// Mailboxes
|
||||||
|
e.GET("/api/mailbox", func(c echo.Context) (err error) {
|
||||||
|
mailboxes, err := models.GetMailboxes(ctx, cfg)
|
||||||
|
return c.JSON(http.StatusOK, mailboxes)
|
||||||
|
})
|
||||||
|
e.GET("/api/mailbox/:id", func(c echo.Context) (err error) {
|
||||||
|
mailbox, err := models.GetMailbox(ctx, cfg, c.Param("id"))
|
||||||
|
return c.JSON(http.StatusOK, mailbox)
|
||||||
|
})
|
||||||
|
|
||||||
|
// Logs
|
||||||
|
e.GET("/api/log", func(c echo.Context) (err error) {
|
||||||
|
logs, err := models.GetLogs(ctx, cfg)
|
||||||
|
return c.JSON(http.StatusOK, logs)
|
||||||
|
})
|
||||||
|
|
||||||
e.Logger.Fatal(e.Start(fmt.Sprintf(":%d", cfg.Port)))
|
e.Logger.Fatal(e.Start(fmt.Sprintf(":%d", cfg.Port)))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
19
vendor/github.com/alecthomas/units/COPYING
generated
vendored
Normal file
19
vendor/github.com/alecthomas/units/COPYING
generated
vendored
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
Copyright (C) 2014 Alec Thomas
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
|
this software and associated documentation files (the "Software"), to deal in
|
||||||
|
the Software without restriction, including without limitation the rights to
|
||||||
|
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||||
|
of the Software, and to permit persons to whom the Software is furnished to do
|
||||||
|
so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
11
vendor/github.com/alecthomas/units/README.md
generated
vendored
Normal file
11
vendor/github.com/alecthomas/units/README.md
generated
vendored
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
# Units - Helpful unit multipliers and functions for Go
|
||||||
|
|
||||||
|
The goal of this package is to have functionality similar to the [time](http://golang.org/pkg/time/) package.
|
||||||
|
|
||||||
|
It allows for code like this:
|
||||||
|
|
||||||
|
```go
|
||||||
|
n, err := ParseBase2Bytes("1KB")
|
||||||
|
// n == 1024
|
||||||
|
n = units.Mebibyte * 512
|
||||||
|
```
|
85
vendor/github.com/alecthomas/units/bytes.go
generated
vendored
Normal file
85
vendor/github.com/alecthomas/units/bytes.go
generated
vendored
Normal file
@ -0,0 +1,85 @@
|
|||||||
|
package units
|
||||||
|
|
||||||
|
// Base2Bytes is the old non-SI power-of-2 byte scale (1024 bytes in a kilobyte,
|
||||||
|
// etc.).
|
||||||
|
type Base2Bytes int64
|
||||||
|
|
||||||
|
// Base-2 byte units.
|
||||||
|
const (
|
||||||
|
Kibibyte Base2Bytes = 1024
|
||||||
|
KiB = Kibibyte
|
||||||
|
Mebibyte = Kibibyte * 1024
|
||||||
|
MiB = Mebibyte
|
||||||
|
Gibibyte = Mebibyte * 1024
|
||||||
|
GiB = Gibibyte
|
||||||
|
Tebibyte = Gibibyte * 1024
|
||||||
|
TiB = Tebibyte
|
||||||
|
Pebibyte = Tebibyte * 1024
|
||||||
|
PiB = Pebibyte
|
||||||
|
Exbibyte = Pebibyte * 1024
|
||||||
|
EiB = Exbibyte
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
bytesUnitMap = MakeUnitMap("iB", "B", 1024)
|
||||||
|
oldBytesUnitMap = MakeUnitMap("B", "B", 1024)
|
||||||
|
)
|
||||||
|
|
||||||
|
// ParseBase2Bytes supports both iB and B in base-2 multipliers. That is, KB
|
||||||
|
// and KiB are both 1024.
|
||||||
|
// However "kB", which is the correct SI spelling of 1000 Bytes, is rejected.
|
||||||
|
func ParseBase2Bytes(s string) (Base2Bytes, error) {
|
||||||
|
n, err := ParseUnit(s, bytesUnitMap)
|
||||||
|
if err != nil {
|
||||||
|
n, err = ParseUnit(s, oldBytesUnitMap)
|
||||||
|
}
|
||||||
|
return Base2Bytes(n), err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b Base2Bytes) String() string {
|
||||||
|
return ToString(int64(b), 1024, "iB", "B")
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
metricBytesUnitMap = MakeUnitMap("B", "B", 1000)
|
||||||
|
)
|
||||||
|
|
||||||
|
// MetricBytes are SI byte units (1000 bytes in a kilobyte).
|
||||||
|
type MetricBytes SI
|
||||||
|
|
||||||
|
// SI base-10 byte units.
|
||||||
|
const (
|
||||||
|
Kilobyte MetricBytes = 1000
|
||||||
|
KB = Kilobyte
|
||||||
|
Megabyte = Kilobyte * 1000
|
||||||
|
MB = Megabyte
|
||||||
|
Gigabyte = Megabyte * 1000
|
||||||
|
GB = Gigabyte
|
||||||
|
Terabyte = Gigabyte * 1000
|
||||||
|
TB = Terabyte
|
||||||
|
Petabyte = Terabyte * 1000
|
||||||
|
PB = Petabyte
|
||||||
|
Exabyte = Petabyte * 1000
|
||||||
|
EB = Exabyte
|
||||||
|
)
|
||||||
|
|
||||||
|
// ParseMetricBytes parses base-10 metric byte units. That is, KB is 1000 bytes.
|
||||||
|
func ParseMetricBytes(s string) (MetricBytes, error) {
|
||||||
|
n, err := ParseUnit(s, metricBytesUnitMap)
|
||||||
|
return MetricBytes(n), err
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: represents 1000B as uppercase "KB", while SI standard requires "kB".
|
||||||
|
func (m MetricBytes) String() string {
|
||||||
|
return ToString(int64(m), 1000, "B", "B")
|
||||||
|
}
|
||||||
|
|
||||||
|
// ParseStrictBytes supports both iB and B suffixes for base 2 and metric,
|
||||||
|
// respectively. That is, KiB represents 1024 and kB, KB represent 1000.
|
||||||
|
func ParseStrictBytes(s string) (int64, error) {
|
||||||
|
n, err := ParseUnit(s, bytesUnitMap)
|
||||||
|
if err != nil {
|
||||||
|
n, err = ParseUnit(s, metricBytesUnitMap)
|
||||||
|
}
|
||||||
|
return int64(n), err
|
||||||
|
}
|
13
vendor/github.com/alecthomas/units/doc.go
generated
vendored
Normal file
13
vendor/github.com/alecthomas/units/doc.go
generated
vendored
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
// Package units provides helpful unit multipliers and functions for Go.
|
||||||
|
//
|
||||||
|
// The goal of this package is to have functionality similar to the time [1] package.
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// [1] http://golang.org/pkg/time/
|
||||||
|
//
|
||||||
|
// It allows for code like this:
|
||||||
|
//
|
||||||
|
// n, err := ParseBase2Bytes("1KB")
|
||||||
|
// // n == 1024
|
||||||
|
// n = units.Mebibyte * 512
|
||||||
|
package units
|
3
vendor/github.com/alecthomas/units/go.mod
generated
vendored
Normal file
3
vendor/github.com/alecthomas/units/go.mod
generated
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
module github.com/alecthomas/units
|
||||||
|
|
||||||
|
require github.com/stretchr/testify v1.4.0
|
11
vendor/github.com/alecthomas/units/go.sum
generated
vendored
Normal file
11
vendor/github.com/alecthomas/units/go.sum
generated
vendored
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
|
||||||
|
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
|
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||||
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
|
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
|
github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
|
||||||
|
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||||
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
||||||
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
|
gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
|
||||||
|
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
50
vendor/github.com/alecthomas/units/si.go
generated
vendored
Normal file
50
vendor/github.com/alecthomas/units/si.go
generated
vendored
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
package units
|
||||||
|
|
||||||
|
// SI units.
|
||||||
|
type SI int64
|
||||||
|
|
||||||
|
// SI unit multiples.
|
||||||
|
const (
|
||||||
|
Kilo SI = 1000
|
||||||
|
Mega = Kilo * 1000
|
||||||
|
Giga = Mega * 1000
|
||||||
|
Tera = Giga * 1000
|
||||||
|
Peta = Tera * 1000
|
||||||
|
Exa = Peta * 1000
|
||||||
|
)
|
||||||
|
|
||||||
|
func MakeUnitMap(suffix, shortSuffix string, scale int64) map[string]float64 {
|
||||||
|
res := map[string]float64{
|
||||||
|
shortSuffix: 1,
|
||||||
|
// see below for "k" / "K"
|
||||||
|
"M" + suffix: float64(scale * scale),
|
||||||
|
"G" + suffix: float64(scale * scale * scale),
|
||||||
|
"T" + suffix: float64(scale * scale * scale * scale),
|
||||||
|
"P" + suffix: float64(scale * scale * scale * scale * scale),
|
||||||
|
"E" + suffix: float64(scale * scale * scale * scale * scale * scale),
|
||||||
|
}
|
||||||
|
|
||||||
|
// Standard SI prefixes use lowercase "k" for kilo = 1000.
|
||||||
|
// For compatibility, and to be fool-proof, we accept both "k" and "K" in metric mode.
|
||||||
|
//
|
||||||
|
// However, official binary prefixes are always capitalized - "KiB" -
|
||||||
|
// and we specifically never parse "kB" as 1024B because:
|
||||||
|
//
|
||||||
|
// (1) people pedantic enough to use lowercase according to SI unlikely to abuse "k" to mean 1024 :-)
|
||||||
|
//
|
||||||
|
// (2) Use of capital K for 1024 was an informal tradition predating IEC prefixes:
|
||||||
|
// "The binary meaning of the kilobyte for 1024 bytes typically uses the symbol KB, with an
|
||||||
|
// uppercase letter K."
|
||||||
|
// -- https://en.wikipedia.org/wiki/Kilobyte#Base_2_(1024_bytes)
|
||||||
|
// "Capitalization of the letter K became the de facto standard for binary notation, although this
|
||||||
|
// could not be extended to higher powers, and use of the lowercase k did persist.[13][14][15]"
|
||||||
|
// -- https://en.wikipedia.org/wiki/Binary_prefix#History
|
||||||
|
// See also the extensive https://en.wikipedia.org/wiki/Timeline_of_binary_prefixes.
|
||||||
|
if scale == 1024 {
|
||||||
|
res["K"+suffix] = float64(scale)
|
||||||
|
} else {
|
||||||
|
res["k"+suffix] = float64(scale)
|
||||||
|
res["K"+suffix] = float64(scale)
|
||||||
|
}
|
||||||
|
return res
|
||||||
|
}
|
138
vendor/github.com/alecthomas/units/util.go
generated
vendored
Normal file
138
vendor/github.com/alecthomas/units/util.go
generated
vendored
Normal file
@ -0,0 +1,138 @@
|
|||||||
|
package units
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
siUnits = []string{"", "K", "M", "G", "T", "P", "E"}
|
||||||
|
)
|
||||||
|
|
||||||
|
func ToString(n int64, scale int64, suffix, baseSuffix string) string {
|
||||||
|
mn := len(siUnits)
|
||||||
|
out := make([]string, mn)
|
||||||
|
for i, m := range siUnits {
|
||||||
|
if n%scale != 0 || i == 0 && n == 0 {
|
||||||
|
s := suffix
|
||||||
|
if i == 0 {
|
||||||
|
s = baseSuffix
|
||||||
|
}
|
||||||
|
out[mn-1-i] = fmt.Sprintf("%d%s%s", n%scale, m, s)
|
||||||
|
}
|
||||||
|
n /= scale
|
||||||
|
if n == 0 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return strings.Join(out, "")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Below code ripped straight from http://golang.org/src/pkg/time/format.go?s=33392:33438#L1123
|
||||||
|
var errLeadingInt = errors.New("units: bad [0-9]*") // never printed
|
||||||
|
|
||||||
|
// leadingInt consumes the leading [0-9]* from s.
|
||||||
|
func leadingInt(s string) (x int64, rem string, err error) {
|
||||||
|
i := 0
|
||||||
|
for ; i < len(s); i++ {
|
||||||
|
c := s[i]
|
||||||
|
if c < '0' || c > '9' {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
if x >= (1<<63-10)/10 {
|
||||||
|
// overflow
|
||||||
|
return 0, "", errLeadingInt
|
||||||
|
}
|
||||||
|
x = x*10 + int64(c) - '0'
|
||||||
|
}
|
||||||
|
return x, s[i:], nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func ParseUnit(s string, unitMap map[string]float64) (int64, error) {
|
||||||
|
// [-+]?([0-9]*(\.[0-9]*)?[a-z]+)+
|
||||||
|
orig := s
|
||||||
|
f := float64(0)
|
||||||
|
neg := false
|
||||||
|
|
||||||
|
// Consume [-+]?
|
||||||
|
if s != "" {
|
||||||
|
c := s[0]
|
||||||
|
if c == '-' || c == '+' {
|
||||||
|
neg = c == '-'
|
||||||
|
s = s[1:]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Special case: if all that is left is "0", this is zero.
|
||||||
|
if s == "0" {
|
||||||
|
return 0, nil
|
||||||
|
}
|
||||||
|
if s == "" {
|
||||||
|
return 0, errors.New("units: invalid " + orig)
|
||||||
|
}
|
||||||
|
for s != "" {
|
||||||
|
g := float64(0) // this element of the sequence
|
||||||
|
|
||||||
|
var x int64
|
||||||
|
var err error
|
||||||
|
|
||||||
|
// The next character must be [0-9.]
|
||||||
|
if !(s[0] == '.' || ('0' <= s[0] && s[0] <= '9')) {
|
||||||
|
return 0, errors.New("units: invalid " + orig)
|
||||||
|
}
|
||||||
|
// Consume [0-9]*
|
||||||
|
pl := len(s)
|
||||||
|
x, s, err = leadingInt(s)
|
||||||
|
if err != nil {
|
||||||
|
return 0, errors.New("units: invalid " + orig)
|
||||||
|
}
|
||||||
|
g = float64(x)
|
||||||
|
pre := pl != len(s) // whether we consumed anything before a period
|
||||||
|
|
||||||
|
// Consume (\.[0-9]*)?
|
||||||
|
post := false
|
||||||
|
if s != "" && s[0] == '.' {
|
||||||
|
s = s[1:]
|
||||||
|
pl := len(s)
|
||||||
|
x, s, err = leadingInt(s)
|
||||||
|
if err != nil {
|
||||||
|
return 0, errors.New("units: invalid " + orig)
|
||||||
|
}
|
||||||
|
scale := 1.0
|
||||||
|
for n := pl - len(s); n > 0; n-- {
|
||||||
|
scale *= 10
|
||||||
|
}
|
||||||
|
g += float64(x) / scale
|
||||||
|
post = pl != len(s)
|
||||||
|
}
|
||||||
|
if !pre && !post {
|
||||||
|
// no digits (e.g. ".s" or "-.s")
|
||||||
|
return 0, errors.New("units: invalid " + orig)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Consume unit.
|
||||||
|
i := 0
|
||||||
|
for ; i < len(s); i++ {
|
||||||
|
c := s[i]
|
||||||
|
if c == '.' || ('0' <= c && c <= '9') {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
u := s[:i]
|
||||||
|
s = s[i:]
|
||||||
|
unit, ok := unitMap[u]
|
||||||
|
if !ok {
|
||||||
|
return 0, errors.New("units: unknown unit " + u + " in " + orig)
|
||||||
|
}
|
||||||
|
|
||||||
|
f += g * unit
|
||||||
|
}
|
||||||
|
|
||||||
|
if neg {
|
||||||
|
f = -f
|
||||||
|
}
|
||||||
|
if f < float64(-1<<63) || f > float64(1<<63-1) {
|
||||||
|
return 0, errors.New("units: overflow parsing unit")
|
||||||
|
}
|
||||||
|
return int64(f), nil
|
||||||
|
}
|
3
vendor/modules.txt
vendored
3
vendor/modules.txt
vendored
@ -1,3 +1,6 @@
|
|||||||
|
# github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d
|
||||||
|
## explicit
|
||||||
|
github.com/alecthomas/units
|
||||||
# github.com/dgrijalva/jwt-go v3.2.0+incompatible
|
# github.com/dgrijalva/jwt-go v3.2.0+incompatible
|
||||||
github.com/dgrijalva/jwt-go
|
github.com/dgrijalva/jwt-go
|
||||||
# github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db
|
# github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db
|
||||||
|
Loading…
Reference in New Issue
Block a user