From 3ae66a389830eaf1b29bc747fe4c61414121cdda Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ferdinand=20M=C3=BCtsch?= Date: Sat, 2 Apr 2022 09:26:14 +0200 Subject: [PATCH 01/14] docs: add public url parameter to readme (resolve #349) [ci skip] --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 26f1406..4c53e26 100644 --- a/README.md +++ b/README.md @@ -143,6 +143,7 @@ You can specify configuration options either via a config file (default: `config | `server.tls_cert_path` /
`WAKAPI_TLS_CERT_PATH` | - | Path of SSL server certificate (leave blank to not use HTTPS) | | `server.tls_key_path` /
`WAKAPI_TLS_KEY_PATH` | - | Path of SSL server private key (leave blank to not use HTTPS) | | `server.base_path` /
`WAKAPI_BASE_PATH` | `/` | Web base path (change when running behind a proxy under a sub-path) | +| `server.public_url` /
`WAKAPI_PUBLIC_URL` | `http://localhost:3000` | URL at which your Wakapi instance can be found publicly | | `security.password_salt` /
`WAKAPI_PASSWORD_SALT` | - | Pepper to use for password hashing | | `security.insecure_cookies` /
`WAKAPI_INSECURE_COOKIES` | `false` | Whether or not to allow cookies over HTTP | | `security.cookie_max_age` /
`WAKAPI_COOKIE_MAX_AGE` | `172800` | Lifetime of authentication cookies in seconds or `0` to use [Session](https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies#Define_the_lifetime_of_a_cookie) cookies | From 977420c68d8745925e42350842b822dba0961c60 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ferdinand=20M=C3=BCtsch?= Date: Sun, 3 Apr 2022 18:02:21 +0200 Subject: [PATCH 02/14] fix: failing heartbeats index auto-migration on sqlite (resolve #346) --- go.mod | 12 +++--- go.sum | 28 ++++++-------- migrations/20220319_add_user_project_idx.go | 35 ----------------- migrations/20220403_drop_user_project_idx.go | 40 ++++++++++++++++++++ models/heartbeat.go | 4 +- version.txt | 2 +- 6 files changed, 61 insertions(+), 60 deletions(-) delete mode 100644 migrations/20220319_add_user_project_idx.go create mode 100644 migrations/20220403_drop_user_project_idx.go diff --git a/go.mod b/go.mod index 286aa9b..dd8b95b 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,7 @@ go 1.18 require ( codeberg.org/Codeberg/avatars v0.0.0-20211228163022-8da63012fe69 github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751 - github.com/duke-git/lancet/v2 v2.0.1 + github.com/duke-git/lancet/v2 v2.0.2 github.com/emersion/go-sasl v0.0.0-20211008083017-0b9dcfb154ac github.com/emersion/go-smtp v0.15.0 github.com/emvi/logbuch v1.2.0 @@ -25,12 +25,12 @@ require ( github.com/stretchr/testify v1.7.0 github.com/swaggo/swag v1.7.0 go.uber.org/atomic v1.9.0 - golang.org/x/crypto v0.0.0-20220321153916-2c7772ba3064 + golang.org/x/crypto v0.0.0-20220331220935-ae2d96664a29 golang.org/x/sync v0.0.0-20210220032951-036812b2e83c - gorm.io/driver/mysql v1.3.2 - gorm.io/driver/postgres v1.3.1 + gorm.io/driver/mysql v1.3.3 + gorm.io/driver/postgres v1.3.2 gorm.io/driver/sqlite v1.3.1 - gorm.io/gorm v1.23.4-0.20220320010245-2d5cb997ed4d + gorm.io/gorm v1.23.4 ) require ( @@ -64,7 +64,7 @@ require ( github.com/stretchr/objx v0.2.0 // indirect golang.org/x/mod v0.6.0-dev.0.20211013180041-c96bc1413d57 // indirect golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2 // indirect - golang.org/x/sys v0.0.0-20220319134239-a9b59b0215f8 // indirect + golang.org/x/sys v0.0.0-20220403020550-483a9cbc67c0 // indirect golang.org/x/text v0.3.7 // indirect golang.org/x/tools v0.1.8-0.20211029000441-d6a9af8af023 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect diff --git a/go.sum b/go.sum index ffcf0b2..7958992 100644 --- a/go.sum +++ b/go.sum @@ -23,8 +23,8 @@ github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ3 github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/duke-git/lancet/v2 v2.0.1 h1:OKNGIw22Yhxeq9rjK5241nfO79zTtYiiC3YERzvLqvA= -github.com/duke-git/lancet/v2 v2.0.1/go.mod h1:5Nawyf/bK783rCiHyVkZLx+jj8028oVVjLOrC21ZONA= +github.com/duke-git/lancet/v2 v2.0.2 h1:U1GBY7DIhYs8Zg/+pGT4XKgKR8p4mDMT++afG6ykTrc= +github.com/duke-git/lancet/v2 v2.0.2/go.mod h1:5Nawyf/bK783rCiHyVkZLx+jj8028oVVjLOrC21ZONA= github.com/emersion/go-sasl v0.0.0-20200509203442-7bfe0ed36a21/go.mod h1:iL2twTeMvZnrg54ZoPDNfJaJaqy0xIQFuBdrLsmspwQ= github.com/emersion/go-sasl v0.0.0-20211008083017-0b9dcfb154ac h1:tn/OQ2PmwQ0XFVgAHfjlLyqMewry25Rz7jWnVoh4Ggs= github.com/emersion/go-sasl v0.0.0-20211008083017-0b9dcfb154ac/go.mod h1:iL2twTeMvZnrg54ZoPDNfJaJaqy0xIQFuBdrLsmspwQ= @@ -83,7 +83,6 @@ github.com/jackc/pgconn v0.0.0-20190831204454-2fabfa3c18b7/go.mod h1:ZJKsE/KZfsU github.com/jackc/pgconn v1.8.0/go.mod h1:1C2Pb36bGIP9QHGBYCjnyhqu7Rv3sGshaQUvmfGIB/o= github.com/jackc/pgconn v1.9.0/go.mod h1:YctiPyvzfU11JFxoXokUOOKQXQmDMoJL9vJzHH8/2JY= github.com/jackc/pgconn v1.9.1-0.20210724152538-d89c8390a530/go.mod h1:4z2w8XhRbP1hYxkpTuBjTS3ne3J48K83+u0zoyvg2pI= -github.com/jackc/pgconn v1.10.1/go.mod h1:4z2w8XhRbP1hYxkpTuBjTS3ne3J48K83+u0zoyvg2pI= github.com/jackc/pgconn v1.11.0 h1:HiHArx4yFbwl91X3qqIHtUFoiIfLNJXCQRsnzkiwwaQ= github.com/jackc/pgconn v1.11.0/go.mod h1:4z2w8XhRbP1hYxkpTuBjTS3ne3J48K83+u0zoyvg2pI= github.com/jackc/pgio v1.0.0 h1:g12B9UwVnzGhueNavwioyEEpAmqMe1E/BN9ES+8ovkE= @@ -109,20 +108,17 @@ github.com/jackc/pgtype v0.0.0-20190421001408-4ed0de4755e0/go.mod h1:hdSHsc1V01C github.com/jackc/pgtype v0.0.0-20190824184912-ab885b375b90/go.mod h1:KcahbBH1nCMSo2DXpzsoWOAfFkdEtEJpPbVLq8eE+mc= github.com/jackc/pgtype v0.0.0-20190828014616-a8802b16cc59/go.mod h1:MWlu30kVJrUS8lot6TQqcg7mtthZ9T0EoIBFiJcmcyw= github.com/jackc/pgtype v1.8.1-0.20210724151600-32e20a603178/go.mod h1:C516IlIV9NKqfsMCXTdChteoXmwgUceqaLfjg2e3NlM= -github.com/jackc/pgtype v1.9.1/go.mod h1:LUMuVrfsFfdKGLw+AFFVv6KtHOFMwRgDDzBt76IqCA4= github.com/jackc/pgtype v1.10.0 h1:ILnBWrRMSXGczYvmkYD6PsYyVFUNLTnIUJHHDLmqk38= github.com/jackc/pgtype v1.10.0/go.mod h1:LUMuVrfsFfdKGLw+AFFVv6KtHOFMwRgDDzBt76IqCA4= github.com/jackc/pgx/v4 v4.0.0-20190420224344-cc3461e65d96/go.mod h1:mdxmSJJuR08CZQyj1PVQBHy9XOp5p8/SHH6a0psbY9Y= github.com/jackc/pgx/v4 v4.0.0-20190421002000-1b8f0016e912/go.mod h1:no/Y67Jkk/9WuGR0JG/JseM9irFbnEPbuWV2EELPNuM= github.com/jackc/pgx/v4 v4.0.0-pre1.0.20190824185557-6972a5742186/go.mod h1:X+GQnOEnf1dqHGpw7JmHqHc1NxDoalibchSk9/RWuDc= github.com/jackc/pgx/v4 v4.12.1-0.20210724153913-640aa07df17c/go.mod h1:1QD0+tgSXP7iUjYm9C1NxKhny7lq6ee99u/z+IHFcgs= -github.com/jackc/pgx/v4 v4.14.1/go.mod h1:RgDuE4Z34o7XE92RpLsvFiOEfrAUT0Xt2KxvX73W06M= github.com/jackc/pgx/v4 v4.15.0 h1:B7dTkXsdILD3MF987WGGCcg+tvLW6bZJdEcqVFeU//w= github.com/jackc/pgx/v4 v4.15.0/go.mod h1:D/zyOyXiaM1TmVWnOM18p0xdDtdakRBa0RsVGI3U3bw= github.com/jackc/puddle v0.0.0-20190413234325-e4ced69a3a2b/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= github.com/jackc/puddle v0.0.0-20190608224051-11cab39313c9/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= github.com/jackc/puddle v1.1.3/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= -github.com/jackc/puddle v1.2.0/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= github.com/jackc/puddle v1.2.1/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= github.com/jinzhu/configor v1.2.1 h1:OKk9dsR8i6HPOCZR8BcMtcEImAFjIhbJFZNyn5GCZko= github.com/jinzhu/configor v1.2.1/go.mod h1:nX89/MOmDba7ZX7GCyU/VIaQ2Ar2aizBl2d3JLF/rDc= @@ -232,8 +228,8 @@ golang.org/x/crypto v0.0.0-20201203163018-be400aefbc4c/go.mod h1:jdWPYTVW3xRLrWP golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.0.0-20220321153916-2c7772ba3064 h1:S25/rfnfsMVgORT4/J61MJ7rdyseOZOyvLIrZEZ7s6s= -golang.org/x/crypto v0.0.0-20220321153916-2c7772ba3064/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +golang.org/x/crypto v0.0.0-20220331220935-ae2d96664a29 h1:tkVvjkPTB7pnW3jnid7kNyAMPVWllTNOf/qKDze4p9o= +golang.org/x/crypto v0.0.0-20220331220935-ae2d96664a29/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= @@ -268,8 +264,8 @@ golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220319134239-a9b59b0215f8 h1:OH54vjqzRWmbJ62fjuhxy7AxFFgoHN0/DPc/UrL8cAs= -golang.org/x/sys v0.0.0-20220319134239-a9b59b0215f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220403020550-483a9cbc67c0 h1:PgUUmg0gNMIPY2WafhL/oLyQGw+kdTNPlVWOjltpp3w= +golang.org/x/sys v0.0.0-20220403020550-483a9cbc67c0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -313,13 +309,13 @@ gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo= gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gorm.io/driver/mysql v1.3.2 h1:QJryWiqQ91EvZ0jZL48NOpdlPdMjdip1hQ8bTgo4H7I= -gorm.io/driver/mysql v1.3.2/go.mod h1:ChK6AHbHgDCFZyJp0F+BmVGb06PSIoh9uVYKAlRbb2U= -gorm.io/driver/postgres v1.3.1 h1:Pyv+gg1Gq1IgsLYytj/S2k7ebII3CzEdpqQkPOdH24g= -gorm.io/driver/postgres v1.3.1/go.mod h1:WwvWOuR9unCLpGWCL6Y3JOeBWvbKi6JLhayiVclSZZU= +gorm.io/driver/mysql v1.3.3 h1:jXG9ANrwBc4+bMvBcSl8zCfPBaVoPyBEBshA8dA93X8= +gorm.io/driver/mysql v1.3.3/go.mod h1:ChK6AHbHgDCFZyJp0F+BmVGb06PSIoh9uVYKAlRbb2U= +gorm.io/driver/postgres v1.3.2 h1:1URWk4lHWJkcudB+9bxOcNNt3uk5VfB8V2mzTPOqjRg= +gorm.io/driver/postgres v1.3.2/go.mod h1:y0vEuInFKJtijuSGu9e5bs5hzzSzPK+LancpKpvbRBw= gorm.io/driver/sqlite v1.3.1 h1:bwfE+zTEWklBYoEodIOIBwuWHpnx52Z9zJFW5F33WLk= gorm.io/driver/sqlite v1.3.1/go.mod h1:wJx0hJspfycZ6myN38x1O/AqLtNS6c5o9TndewFbELg= gorm.io/gorm v1.23.1/go.mod h1:l2lP/RyAtc1ynaTjFksBde/O8v9oOGIApu2/xRitmZk= -gorm.io/gorm v1.23.4-0.20220320010245-2d5cb997ed4d h1:jDg/QfjT3PwXwVbUdArbL4dlayfD/zE1tC04Zx+BAcI= -gorm.io/gorm v1.23.4-0.20220320010245-2d5cb997ed4d/go.mod h1:l2lP/RyAtc1ynaTjFksBde/O8v9oOGIApu2/xRitmZk= +gorm.io/gorm v1.23.4 h1:1BKWM67O6CflSLcwGQR7ccfmC4ebOxQrTfOQGRE9wjg= +gorm.io/gorm v1.23.4/go.mod h1:l2lP/RyAtc1ynaTjFksBde/O8v9oOGIApu2/xRitmZk= honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= diff --git a/migrations/20220319_add_user_project_idx.go b/migrations/20220319_add_user_project_idx.go deleted file mode 100644 index ab38d0e..0000000 --- a/migrations/20220319_add_user_project_idx.go +++ /dev/null @@ -1,35 +0,0 @@ -package migrations - -import ( - "fmt" - "github.com/emvi/logbuch" - "github.com/muety/wakapi/config" - "github.com/muety/wakapi/models" - "gorm.io/gorm" -) - -func init() { - const name = "20220319-add_user_project_idx" - f := migrationFunc{ - name: name, - f: func(db *gorm.DB, cfg *config.Config) error { - if hasRun(name, db) { - return nil - } - - idxName := "idx_user_project" - - if !db.Migrator().HasIndex(&models.Heartbeat{}, idxName) { - logbuch.Info("running migration '%s'", name) - if err := db.Exec(fmt.Sprintf("create index %s on heartbeats (user_id, project)", idxName)).Error; err != nil { - logbuch.Warn("failed to create %s", idxName) - } - } - - setHasRun(name, db) - return nil - }, - } - - registerPostMigration(f) -} diff --git a/migrations/20220403_drop_user_project_idx.go b/migrations/20220403_drop_user_project_idx.go new file mode 100644 index 0000000..c6a2aa3 --- /dev/null +++ b/migrations/20220403_drop_user_project_idx.go @@ -0,0 +1,40 @@ +package migrations + +import ( + "github.com/emvi/logbuch" + "github.com/muety/wakapi/config" + "github.com/muety/wakapi/models" + "gorm.io/gorm" +) + +// migration to fix https://github.com/muety/wakapi/issues/346 +// caused by https://github.com/muety/wakapi/blob/2.3.2/migrations/20220319_add_user_project_idx.go in combination with +// the wrongly defined index at https://github.com/muety/wakapi/blob/5aae18e2415d9e620f383f98cd8cbdf39cd99f27/models/heartbeat.go#L18 +// and https://github.com/go-gorm/sqlite/issues/87 +// -> drop index and let it be auto-created again with properly formatted ddl + +func init() { + const name = "20220403-drop_user_project_idx" + const idxName = "idx_user_project" + + f := migrationFunc{ + name: name, + f: func(db *gorm.DB, cfg *config.Config) error { + if !db.Migrator().HasTable(&models.KeyStringValue{}) || hasRun(name, db) { + return nil + } + + if cfg.Db.IsSQLite() && db.Migrator().HasIndex(&models.Heartbeat{}, idxName) { + logbuch.Info("running migration '%s'", name) + if err := db.Migrator().DropIndex(&models.Heartbeat{}, idxName); err != nil { + logbuch.Warn("failed to drop %s", idxName) + } + } + + setHasRun(name, db) + return nil + }, + } + + registerPreMigration(f) +} diff --git a/models/heartbeat.go b/models/heartbeat.go index 9afed6c..ed7470d 100644 --- a/models/heartbeat.go +++ b/models/heartbeat.go @@ -11,11 +11,11 @@ import ( type Heartbeat struct { ID uint64 `gorm:"primary_key" hash:"ignore"` User *User `json:"-" gorm:"not null; constraint:OnUpdate:CASCADE,OnDelete:CASCADE;" hash:"ignore"` - UserID string `json:"-" gorm:"not null; index:idx_time_user,idx_user_project"` // idx_user_project is for quickly fetching a user's project list (settings page) + UserID string `json:"-" gorm:"not null; index:idx_time_user; index:idx_user_project"` // idx_user_project is for quickly fetching a user's project list (settings page) Entity string `json:"entity" gorm:"not null"` Type string `json:"type"` Category string `json:"category"` - Project string `json:"project" gorm:"index:idx_project,idx_user_project"` + Project string `json:"project" gorm:"index:idx_project; index:idx_user_project"` Branch string `json:"branch" gorm:"index:idx_branch"` Language string `json:"language" gorm:"index:idx_language"` IsWrite bool `json:"is_write"` diff --git a/version.txt b/version.txt index e703481..45674f1 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -2.3.2 \ No newline at end of file +2.3.3 \ No newline at end of file From 1a47243f700e925707c5923361272689aa3f7e89 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ferdinand=20M=C3=BCtsch?= Date: Wed, 13 Apr 2022 00:05:18 +0200 Subject: [PATCH 03/14] chore: make summary items subquery unique by summary id --- repositories/summary.go | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/repositories/summary.go b/repositories/summary.go index d330014..e4668b8 100644 --- a/repositories/summary.go +++ b/repositories/summary.go @@ -1,6 +1,7 @@ package repositories import ( + datastructure "github.com/duke-git/lancet/v2/datastructure/set" "github.com/muety/wakapi/models" "gorm.io/gorm" "time" @@ -78,20 +79,20 @@ func (r *SummaryRepository) DeleteByUser(userId string) error { // inplace func (r *SummaryRepository) populateItems(summaries []*models.Summary) error { summaryMap := map[uint]*models.Summary{} - summaryIds := make([]uint, len(summaries)) - for i, s := range summaries { + summaryIds := datastructure.NewSet[uint]() + for _, s := range summaries { if s.NumHeartbeats == 0 { continue } summaryMap[s.ID] = s - summaryIds[i] = s.ID + summaryIds.Add(s.ID) } var items []*models.SummaryItem if err := r.db. Model(&models.SummaryItem{}). - Where("summary_id in ?", summaryIds). + Where("summary_id in ?", summaryIds.Values()). Find(&items).Error; err != nil { return err } From 40067d252e148f623d4da9c9c0d9606cf2d9b3a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ferdinand=20M=C3=BCtsch?= Date: Mon, 18 Apr 2022 11:39:26 +0200 Subject: [PATCH 04/14] fix: non-ascii project badges (resolve #357) chore: locally generated badges (resolve #348) --- go.mod | 13 +- go.sum | 20 ++ main.go | 2 + models/compat/shields/v1/badge.go | 4 +- models/shared.go | 5 + routes/api/avatar.go | 6 + routes/api/badge.go | 98 +++++++ routes/compat/shields/v1/badge.go | 77 +---- routes/compat/shields/v1/badge_test.go | 2 +- routes/utils/badge_utils.go | 84 ++++++ routes/utils/summary_utils.go | 20 +- static/assets/css/app.dist.css | 2 +- static/assets/css/app.dist.css.br | Bin 3069 -> 3084 bytes static/assets/js/components/summary.js | 6 + utils/http.go | 29 ++ version.txt | 2 +- views/settings.tpl.html | 42 ++- views/summary.tpl.html | 379 +++++++++++++------------ 18 files changed, 511 insertions(+), 280 deletions(-) create mode 100644 routes/api/badge.go create mode 100644 routes/utils/badge_utils.go diff --git a/go.mod b/go.mod index dd8b95b..2b4e343 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,7 @@ go 1.18 require ( codeberg.org/Codeberg/avatars v0.0.0-20211228163022-8da63012fe69 github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751 - github.com/duke-git/lancet/v2 v2.0.2 + github.com/duke-git/lancet/v2 v2.0.4 github.com/emersion/go-sasl v0.0.0-20211008083017-0b9dcfb154ac github.com/emersion/go-smtp v0.15.0 github.com/emvi/logbuch v1.2.0 @@ -20,21 +20,22 @@ require ( github.com/leandro-lugaresi/hub v1.1.1 github.com/lpar/gzipped/v2 v2.0.2 github.com/mitchellh/hashstructure/v2 v2.0.2 + github.com/narqo/go-badge v0.0.0-20220127184443-140af28a266e github.com/patrickmn/go-cache v2.1.0+incompatible github.com/satori/go.uuid v1.2.0 github.com/stretchr/testify v1.7.0 github.com/swaggo/swag v1.7.0 go.uber.org/atomic v1.9.0 - golang.org/x/crypto v0.0.0-20220331220935-ae2d96664a29 + golang.org/x/crypto v0.0.0-20220411220226-7b82a4e95df4 golang.org/x/sync v0.0.0-20210220032951-036812b2e83c gorm.io/driver/mysql v1.3.3 - gorm.io/driver/postgres v1.3.2 + gorm.io/driver/postgres v1.3.4 gorm.io/driver/sqlite v1.3.1 gorm.io/gorm v1.23.4 ) require ( - github.com/BurntSushi/toml v1.0.0 // indirect + github.com/BurntSushi/toml v1.1.0 // indirect github.com/KyleBanks/depth v1.2.1 // indirect github.com/PuerkitoBio/purell v1.1.1 // indirect github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 // indirect @@ -45,6 +46,7 @@ require ( github.com/go-openapi/spec v0.20.2 // indirect github.com/go-openapi/swag v0.19.13 // indirect github.com/go-sql-driver/mysql v1.6.0 // indirect + github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 // indirect github.com/jackc/chunkreader/v2 v2.0.1 // indirect github.com/jackc/pgconn v1.11.0 // indirect github.com/jackc/pgio v1.0.0 // indirect @@ -62,9 +64,10 @@ require ( github.com/pmezard/go-difflib v1.0.0 // indirect github.com/robfig/cron/v3 v3.0.1 // indirect github.com/stretchr/objx v0.2.0 // indirect + golang.org/x/image v0.0.0-20220413100746-70e8d0d3baa9 // indirect golang.org/x/mod v0.6.0-dev.0.20211013180041-c96bc1413d57 // indirect golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2 // indirect - golang.org/x/sys v0.0.0-20220403020550-483a9cbc67c0 // indirect + golang.org/x/sys v0.0.0-20220412211240-33da011f77ad // indirect golang.org/x/text v0.3.7 // indirect golang.org/x/tools v0.1.8-0.20211029000441-d6a9af8af023 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect diff --git a/go.sum b/go.sum index 7958992..347bdae 100644 --- a/go.sum +++ b/go.sum @@ -3,6 +3,8 @@ codeberg.org/Codeberg/avatars v0.0.0-20211228163022-8da63012fe69/go.mod h1:ML/ht github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/toml v1.0.0 h1:dtDWrepsVPfW9H/4y7dDgFc2MBUSeJhlaDtK13CxFlU= github.com/BurntSushi/toml v1.0.0/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= +github.com/BurntSushi/toml v1.1.0 h1:ksErzDEI1khOiGPgpwuI7x2ebx/uXQNw7xJpn9Eq1+I= +github.com/BurntSushi/toml v1.1.0/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= github.com/KyleBanks/depth v1.2.1 h1:5h8fQADFrWtarTdtDudMmGsC7GPbOAu6RVB3ffsVFHc= github.com/KyleBanks/depth v1.2.1/go.mod h1:jzSb9d0L43HxTQfT+oSA1EEp2q+ne2uh6XgeJcm8brE= github.com/Masterminds/semver/v3 v3.1.1 h1:hLg3sBzpNErnxhQtUy/mmLR2I9foDujNK030IGemrRc= @@ -25,6 +27,8 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/duke-git/lancet/v2 v2.0.2 h1:U1GBY7DIhYs8Zg/+pGT4XKgKR8p4mDMT++afG6ykTrc= github.com/duke-git/lancet/v2 v2.0.2/go.mod h1:5Nawyf/bK783rCiHyVkZLx+jj8028oVVjLOrC21ZONA= +github.com/duke-git/lancet/v2 v2.0.4 h1:IvMurTpL0cGhQmGPtkCge2eCkuiu3USQtglZJnKXxEo= +github.com/duke-git/lancet/v2 v2.0.4/go.mod h1:5Nawyf/bK783rCiHyVkZLx+jj8028oVVjLOrC21ZONA= github.com/emersion/go-sasl v0.0.0-20200509203442-7bfe0ed36a21/go.mod h1:iL2twTeMvZnrg54ZoPDNfJaJaqy0xIQFuBdrLsmspwQ= github.com/emersion/go-sasl v0.0.0-20211008083017-0b9dcfb154ac h1:tn/OQ2PmwQ0XFVgAHfjlLyqMewry25Rz7jWnVoh4Ggs= github.com/emersion/go-sasl v0.0.0-20211008083017-0b9dcfb154ac/go.mod h1:iL2twTeMvZnrg54ZoPDNfJaJaqy0xIQFuBdrLsmspwQ= @@ -61,6 +65,8 @@ github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LB github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/gofrs/uuid v4.0.0+incompatible h1:1SD/1F5pU8p29ybwgQSwpQk+mwdRrXCYuPhW6m+TnJw= github.com/gofrs/uuid v4.0.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= +github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 h1:DACJavvAHhabrF08vX0COfcOBJRhZ8lUbR+ZWIs0Y5g= +github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k= github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/gorilla/handlers v1.5.1 h1:9lRY6j8DEeeBT10CvO9hGW0gmky0BprnvDI5vfhUHH4= @@ -73,6 +79,7 @@ github.com/gorilla/securecookie v1.1.1 h1:miw7JPhV+b/lAHSXz4qd/nN9jRiAFV5FwjeKyC github.com/gorilla/securecookie v1.1.1/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+HVt/4epWDjd4= github.com/hashicorp/golang-lru v0.5.4 h1:YDjusn29QI/Das2iO9M0BHnIbxPeyuCHsjMW+lJfyTc= github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= +github.com/jackc/chunkreader v1.0.0 h1:4s39bBR8ByfqH+DKm8rQA3E1LHZWB9XWcrz8fqaZbe0= github.com/jackc/chunkreader v1.0.0/go.mod h1:RT6O25fNZIuasFJRyZ4R/Y2BbhasbmZXF9QQ7T3kePo= github.com/jackc/chunkreader/v2 v2.0.0/go.mod h1:odVSm741yZoC3dpHEUXIqA9tQRhFrgOHwnPIn9lDKlk= github.com/jackc/chunkreader/v2 v2.0.1 h1:i+RDz65UE+mmpjTfyz0MoVTnzeYxroil2G82ki7MGG8= @@ -93,6 +100,7 @@ github.com/jackc/pgmock v0.0.0-20210724152146-4ad1a8207f65 h1:DadwsjnMwFjfWc9y5W github.com/jackc/pgmock v0.0.0-20210724152146-4ad1a8207f65/go.mod h1:5R2h2EEX+qri8jOWMbJCtaPWkrrNc7OHwsp2TCqp7ak= github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM= github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg= +github.com/jackc/pgproto3 v1.1.0 h1:FYYE4yRw+AgI8wXIinMlNjBbp/UitDJwfj5LqqewP1A= github.com/jackc/pgproto3 v1.1.0/go.mod h1:eR5FA3leWg7p9aeAqi37XOTgTIbkABlvcPB3E5rlc78= github.com/jackc/pgproto3/v2 v2.0.0-alpha1.0.20190420180111-c116219b62db/go.mod h1:bhq50y+xrl9n5mRYyCBFKkpRVTLYJVWeCc+mEAI3yXA= github.com/jackc/pgproto3/v2 v2.0.0-alpha1.0.20190609003834-432c2951c711/go.mod h1:uH0AWtUmuShn0bcesswc4aBTWGvw0cAxIJp+6OB//Wg= @@ -165,6 +173,8 @@ github.com/mattn/go-sqlite3 v2.0.3+incompatible h1:gXHsfypPkaMZrKbD5209QV9jbUTJK github.com/mattn/go-sqlite3 v2.0.3+incompatible/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc= github.com/mitchellh/hashstructure/v2 v2.0.2 h1:vGKWl0YJqUNxE8d+h8f6NJLcCJrgbhC4NcD46KavDd4= github.com/mitchellh/hashstructure/v2 v2.0.2/go.mod h1:MG3aRVU/N29oo/V/IhBX8GR/zz4kQkprJgF2EVszyDE= +github.com/narqo/go-badge v0.0.0-20220127184443-140af28a266e h1:bR8DQ4ZfItytLJwRlrLOPUHd5z18V6tECwYQFy8W+8g= +github.com/narqo/go-badge v0.0.0-20220127184443-140af28a266e/go.mod h1:m9BzkaxwU4IfPQi9ko23cmuFltayFe8iS0dlRlnEWiM= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= github.com/patrickmn/go-cache v2.1.0+incompatible h1:HRMgzkcYKYpi3C8ajMPV8OFXaaRUnok+kx1WdO15EQc= @@ -230,6 +240,12 @@ golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5y golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20220331220935-ae2d96664a29 h1:tkVvjkPTB7pnW3jnid7kNyAMPVWllTNOf/qKDze4p9o= golang.org/x/crypto v0.0.0-20220331220935-ae2d96664a29/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +golang.org/x/crypto v0.0.0-20220411220226-7b82a4e95df4 h1:kUhD7nTDoI3fVd9G4ORWrbV5NY0liEs/Jg2pv5f+bBA= +golang.org/x/crypto v0.0.0-20220411220226-7b82a4e95df4/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +golang.org/x/image v0.0.0-20211028202545-6944b10bf410 h1:hTftEOvwiOq2+O8k2D5/Q7COC7k5Qcrgc2TFURJYnvQ= +golang.org/x/image v0.0.0-20211028202545-6944b10bf410/go.mod h1:023OzeP/+EPmXeapQh35lcL3II3LrY8Ic+EFFKVhULM= +golang.org/x/image v0.0.0-20220413100746-70e8d0d3baa9 h1:LRtI4W37N+KFebI/qV0OFiLUv4GLOWeEW5hn/KEJvxE= +golang.org/x/image v0.0.0-20220413100746-70e8d0d3baa9/go.mod h1:023OzeP/+EPmXeapQh35lcL3II3LrY8Ic+EFFKVhULM= golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= @@ -266,6 +282,8 @@ golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220403020550-483a9cbc67c0 h1:PgUUmg0gNMIPY2WafhL/oLyQGw+kdTNPlVWOjltpp3w= golang.org/x/sys v0.0.0-20220403020550-483a9cbc67c0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220412211240-33da011f77ad h1:ntjMns5wyP/fN65tdBD4g8J5w8n015+iIIs9rtjXkY0= +golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -313,6 +331,8 @@ gorm.io/driver/mysql v1.3.3 h1:jXG9ANrwBc4+bMvBcSl8zCfPBaVoPyBEBshA8dA93X8= gorm.io/driver/mysql v1.3.3/go.mod h1:ChK6AHbHgDCFZyJp0F+BmVGb06PSIoh9uVYKAlRbb2U= gorm.io/driver/postgres v1.3.2 h1:1URWk4lHWJkcudB+9bxOcNNt3uk5VfB8V2mzTPOqjRg= gorm.io/driver/postgres v1.3.2/go.mod h1:y0vEuInFKJtijuSGu9e5bs5hzzSzPK+LancpKpvbRBw= +gorm.io/driver/postgres v1.3.4 h1:evZ7plF+Bp+Lr1mO5NdPvd6M/N98XtwHixGB+y7fdEQ= +gorm.io/driver/postgres v1.3.4/go.mod h1:y0vEuInFKJtijuSGu9e5bs5hzzSzPK+LancpKpvbRBw= gorm.io/driver/sqlite v1.3.1 h1:bwfE+zTEWklBYoEodIOIBwuWHpnx52Z9zJFW5F33WLk= gorm.io/driver/sqlite v1.3.1/go.mod h1:wJx0hJspfycZ6myN38x1O/AqLtNS6c5o9TndewFbELg= gorm.io/gorm v1.23.1/go.mod h1:l2lP/RyAtc1ynaTjFksBde/O8v9oOGIApu2/xRitmZk= diff --git a/main.go b/main.go index 119ee6e..fc8e950 100644 --- a/main.go +++ b/main.go @@ -182,6 +182,7 @@ func main() { metricsHandler := api.NewMetricsHandler(userService, summaryService, heartbeatService, keyValueService, metricsRepository) diagnosticsHandler := api.NewDiagnosticsApiHandler(userService, diagnosticsService) avatarHandler := api.NewAvatarHandler() + badgeHandler := api.NewBadgeHandler(userService, summaryService) // Compat Handlers wakatimeV1StatusBarHandler := wtV1Routes.NewStatusBarHandler(userService, summaryService) @@ -240,6 +241,7 @@ func main() { metricsHandler.RegisterRoutes(apiRouter) diagnosticsHandler.RegisterRoutes(apiRouter) avatarHandler.RegisterRoutes(apiRouter) + badgeHandler.RegisterRoutes(apiRouter) wakatimeV1StatusBarHandler.RegisterRoutes(apiRouter) wakatimeV1AllHandler.RegisterRoutes(apiRouter) wakatimeV1SummariesHandler.RegisterRoutes(apiRouter) diff --git a/models/compat/shields/v1/badge.go b/models/compat/shields/v1/badge.go index f9055ac..39f6dc1 100644 --- a/models/compat/shields/v1/badge.go +++ b/models/compat/shields/v1/badge.go @@ -8,8 +8,8 @@ import ( // https://shields.io/endpoint const ( - defaultLabel = "coding time" - defaultColor = "#2D3748" // not working + defaultLabel = "wakapi.dev" + defaultColor = "2F855A" ) type BadgeData struct { diff --git a/models/shared.go b/models/shared.go index ab75246..a38c30d 100644 --- a/models/shared.go +++ b/models/shared.go @@ -29,6 +29,11 @@ type Interval struct { End time.Time } +type KeyedInterval struct { + Interval + Key *IntervalKey +} + // CustomTime is a wrapper type around time.Time, mainly used for the purpose of transparently unmarshalling Python timestamps in the format . (e.g. 1619335137.3324468) type CustomTime time.Time diff --git a/routes/api/avatar.go b/routes/api/avatar.go index 5faf49b..43b1cf3 100644 --- a/routes/api/avatar.go +++ b/routes/api/avatar.go @@ -5,7 +5,9 @@ import ( "github.com/gorilla/mux" lru "github.com/hashicorp/golang-lru" conf "github.com/muety/wakapi/config" + "github.com/muety/wakapi/utils" "net/http" + "time" ) type AvatarHandler struct { @@ -33,6 +35,10 @@ func (h *AvatarHandler) RegisterRoutes(router *mux.Router) { func (h *AvatarHandler) Get(w http.ResponseWriter, r *http.Request) { hash := mux.Vars(r)["hash"] + if utils.IsNoCache(r, 1*time.Hour) { + h.cache.Remove(hash) + } + if !h.cache.Contains(hash) { h.cache.Add(hash, avatars.MakeMaleAvatar(hash)) } diff --git a/routes/api/badge.go b/routes/api/badge.go new file mode 100644 index 0000000..3c69755 --- /dev/null +++ b/routes/api/badge.go @@ -0,0 +1,98 @@ +package api + +import ( + "fmt" + "github.com/duke-git/lancet/v2/maputil" + "github.com/duke-git/lancet/v2/slice" + "github.com/gorilla/mux" + conf "github.com/muety/wakapi/config" + "github.com/muety/wakapi/models" + v1 "github.com/muety/wakapi/models/compat/shields/v1" + routeutils "github.com/muety/wakapi/routes/utils" + "github.com/muety/wakapi/services" + "github.com/muety/wakapi/utils" + "github.com/narqo/go-badge" + "github.com/patrickmn/go-cache" + "net/http" + "time" +) + +type BadgeHandler struct { + config *conf.Config + cache *cache.Cache + userSrvc services.IUserService + summarySrvc services.ISummaryService +} + +func NewBadgeHandler(userService services.IUserService, summaryService services.ISummaryService) *BadgeHandler { + return &BadgeHandler{ + config: conf.Get(), + cache: cache.New(time.Hour, time.Hour), + userSrvc: userService, + summarySrvc: summaryService, + } +} + +func (h *BadgeHandler) RegisterRoutes(router *mux.Router) { + r := router.PathPrefix("/badge/{user}").Subrouter() + r.Methods(http.MethodGet).HandlerFunc(h.Get) +} + +func (h *BadgeHandler) Get(w http.ResponseWriter, r *http.Request) { + user, err := h.userSrvc.GetUserById(mux.Vars(r)["user"]) + if err != nil { + w.WriteHeader(http.StatusNotFound) + return + } + + interval, filters, err := routeutils.GetBadgeParams(r, user) + if err != nil { + w.WriteHeader(http.StatusForbidden) + w.Write([]byte(err.Error())) + return + } + + cacheKey := fmt.Sprintf("%s_%v_%s", user.ID, *interval.Key, filters.Hash()) + noCache := utils.IsNoCache(r, 1*time.Hour) + if cacheResult, ok := h.cache.Get(cacheKey); ok && !noCache { + respondSvg(w, cacheResult.([]byte)) + return + } + + params := &models.SummaryParams{ + From: interval.Start, + To: interval.End, + User: user, + Filters: filters, + } + + summary, err, status := routeutils.LoadUserSummaryByParams(h.summarySrvc, params) + if err != nil { + w.WriteHeader(status) + w.Write([]byte(err.Error())) + return + } + + badgeData := v1.NewBadgeDataFrom(summary) + if customLabel := r.URL.Query().Get("label"); customLabel != "" { + badgeData.Label = customLabel + } + if customColor := r.URL.Query().Get("color"); customColor != "" { + badgeData.Color = customColor + } + + if badgeData.Color[0:1] != "#" && !slice.Contain(maputil.Keys(badge.ColorScheme), badgeData.Color) { + badgeData.Color = "#" + badgeData.Color + } + + badgeSvg, err := badge.RenderBytes(badgeData.Label, badgeData.Message, badge.Color(badgeData.Color)) + h.cache.SetDefault(cacheKey, badgeSvg) + respondSvg(w, badgeSvg) +} + +func respondSvg(w http.ResponseWriter, data []byte) { + w.Header().Set("Content-Type", "image/svg+xml") + w.Header().Set("Cache-Control", "max-age=3600") + w.WriteHeader(http.StatusOK) + w.Write(data) +} diff --git a/routes/compat/shields/v1/badge.go b/routes/compat/shields/v1/badge.go index fbc4162..48ff935 100644 --- a/routes/compat/shields/v1/badge.go +++ b/routes/compat/shields/v1/badge.go @@ -2,8 +2,8 @@ package v1 import ( "fmt" + routeutils "github.com/muety/wakapi/routes/utils" "net/http" - "regexp" "time" "github.com/gorilla/mux" @@ -15,11 +15,6 @@ import ( "github.com/patrickmn/go-cache" ) -const ( - intervalPattern = `interval:([a-z0-9_]+)` - entityFilterPattern = `(project|os|editor|language|machine|label):([_a-zA-Z0-9-\s\.]+)` -) - type BadgeHandler struct { config *conf.Config userSrvc services.IUserService @@ -53,77 +48,33 @@ func (h *BadgeHandler) RegisterRoutes(router *mux.Router) { // @Success 200 {object} v1.BadgeData // @Router /compat/shields/v1/{user}/{interval}/{filter} [get] func (h *BadgeHandler) Get(w http.ResponseWriter, r *http.Request) { - intervalReg := regexp.MustCompile(intervalPattern) - entityFilterReg := regexp.MustCompile(entityFilterPattern) - - var filterEntity, filterKey string - if groups := entityFilterReg.FindStringSubmatch(r.URL.Path); len(groups) > 2 { - filterEntity, filterKey = groups[1], groups[2] - } - - var interval = models.IntervalPast30Days - if groups := intervalReg.FindStringSubmatch(r.URL.Path); len(groups) > 1 { - if i, err := utils.ParseInterval(groups[1]); err == nil { - interval = i - } - } - - requestedUserId := mux.Vars(r)["user"] - user, err := h.userSrvc.GetUserById(requestedUserId) + user, err := h.userSrvc.GetUserById(mux.Vars(r)["user"]) if err != nil { w.WriteHeader(http.StatusNotFound) return } - _, rangeFrom, rangeTo := utils.ResolveIntervalTZ(interval, user.TZ()) - minStart := rangeTo.Add(-24 * time.Hour * time.Duration(user.ShareDataMaxDays)) - // negative value means no limit - if rangeFrom.Before(minStart) && user.ShareDataMaxDays >= 0 { + interval, filters, err := routeutils.GetBadgeParams(r, user) + if err != nil { w.WriteHeader(http.StatusForbidden) - w.Write([]byte("requested time range too broad")) + w.Write([]byte(err.Error())) return } - var permitEntity bool - var filters *models.Filters - switch filterEntity { - case "project": - permitEntity = user.ShareProjects - filters = models.NewFiltersWith(models.SummaryProject, filterKey) - case "os": - permitEntity = user.ShareOSs - filters = models.NewFiltersWith(models.SummaryOS, filterKey) - case "editor": - permitEntity = user.ShareEditors - filters = models.NewFiltersWith(models.SummaryEditor, filterKey) - case "language": - permitEntity = user.ShareLanguages - filters = models.NewFiltersWith(models.SummaryLanguage, filterKey) - case "machine": - permitEntity = user.ShareMachines - filters = models.NewFiltersWith(models.SummaryMachine, filterKey) - case "label": - permitEntity = user.ShareLabels - filters = models.NewFiltersWith(models.SummaryLabel, filterKey) - // branches are intentionally omitted here, as only relevant in combination with a project filter - default: - permitEntity = true - filters = &models.Filters{} - } - - if !permitEntity { - w.WriteHeader(http.StatusForbidden) - w.Write([]byte("user did not opt in to share entity-specific data")) - return - } - - cacheKey := fmt.Sprintf("%s_%v_%s_%s", user.ID, *interval, filterEntity, filterKey) + cacheKey := fmt.Sprintf("%s_%v_%s", user.ID, *interval.Key, filters.Hash()) if cacheResult, ok := h.cache.Get(cacheKey); ok { utils.RespondJSON(w, r, http.StatusOK, cacheResult.(*v1.BadgeData)) return } - summary, err, status := h.loadUserSummary(user, interval, filters) + params := &models.SummaryParams{ + From: interval.Start, + To: interval.End, + User: user, + Filters: filters, + } + + summary, err, status := routeutils.LoadUserSummaryByParams(h.summarySrvc, params) if err != nil { w.WriteHeader(status) w.Write([]byte(err.Error())) diff --git a/routes/compat/shields/v1/badge_test.go b/routes/compat/shields/v1/badge_test.go index 9bb2eec..88292df 100644 --- a/routes/compat/shields/v1/badge_test.go +++ b/routes/compat/shields/v1/badge_test.go @@ -30,7 +30,7 @@ func TestBadgeHandler_EntityPattern(t *testing.T) { {test: pathPrefix + "project:Anchr-Android_v2.0", key: "project", val: "Anchr-Android_v2.0"}, // all the way } - sut := regexp.MustCompile(entityFilterPattern) + sut := regexp.MustCompile(`(project|os|editor|language|machine|label):([^:?&/]+)`) // see entityFilterPattern in badge_utils.go for _, tc := range tests { var key, val string diff --git a/routes/utils/badge_utils.go b/routes/utils/badge_utils.go new file mode 100644 index 0000000..7b36f74 --- /dev/null +++ b/routes/utils/badge_utils.go @@ -0,0 +1,84 @@ +package utils + +import ( + "errors" + "github.com/muety/wakapi/models" + "github.com/muety/wakapi/utils" + "net/http" + "regexp" + "time" +) + +const ( + intervalPattern = `interval:([a-z0-9_]+)` + entityFilterPattern = `(project|os|editor|language|machine|label):([^:?&/]+)` +) + +var ( + intervalReg *regexp.Regexp + entityFilterReg *regexp.Regexp +) + +func init() { + intervalReg = regexp.MustCompile(intervalPattern) + entityFilterReg = regexp.MustCompile(entityFilterPattern) +} + +func GetBadgeParams(r *http.Request, requestedUser *models.User) (*models.KeyedInterval, *models.Filters, error) { + var filterEntity, filterKey string + if groups := entityFilterReg.FindStringSubmatch(r.URL.Path); len(groups) > 2 { + filterEntity, filterKey = groups[1], groups[2] + } + + var intervalKey = models.IntervalPast30Days + if groups := intervalReg.FindStringSubmatch(r.URL.Path); len(groups) > 1 { + if i, err := utils.ParseInterval(groups[1]); err == nil { + intervalKey = i + } + } + + _, rangeFrom, rangeTo := utils.ResolveIntervalTZ(intervalKey, requestedUser.TZ()) + interval := &models.KeyedInterval{ + Interval: models.Interval{Start: rangeFrom, End: rangeTo}, + Key: intervalKey, + } + + minStart := rangeTo.Add(-24 * time.Hour * time.Duration(requestedUser.ShareDataMaxDays)) + // negative value means no limit + if rangeFrom.Before(minStart) && requestedUser.ShareDataMaxDays >= 0 { + return nil, nil, errors.New("requested time range too broad") + } + + var permitEntity bool + var filters *models.Filters + switch filterEntity { + case "project": + permitEntity = requestedUser.ShareProjects + filters = models.NewFiltersWith(models.SummaryProject, filterKey) + case "os": + permitEntity = requestedUser.ShareOSs + filters = models.NewFiltersWith(models.SummaryOS, filterKey) + case "editor": + permitEntity = requestedUser.ShareEditors + filters = models.NewFiltersWith(models.SummaryEditor, filterKey) + case "language": + permitEntity = requestedUser.ShareLanguages + filters = models.NewFiltersWith(models.SummaryLanguage, filterKey) + case "machine": + permitEntity = requestedUser.ShareMachines + filters = models.NewFiltersWith(models.SummaryMachine, filterKey) + case "label": + permitEntity = requestedUser.ShareLabels + filters = models.NewFiltersWith(models.SummaryLabel, filterKey) + // branches are intentionally omitted here, as only relevant in combination with a project filter + default: + // non-entity-specific request, just a general, in-total query + permitEntity = true + } + + if !permitEntity { + return nil, nil, errors.New("user did not opt in to share entity-specific data") + } + + return interval, filters, nil +} diff --git a/routes/utils/summary_utils.go b/routes/utils/summary_utils.go index 739434f..d07304c 100644 --- a/routes/utils/summary_utils.go +++ b/routes/utils/summary_utils.go @@ -1,7 +1,6 @@ package utils import ( - "github.com/muety/wakapi/middlewares" "github.com/muety/wakapi/models" "github.com/muety/wakapi/services" "github.com/muety/wakapi/utils" @@ -9,24 +8,33 @@ import ( ) func LoadUserSummary(ss services.ISummaryService, r *http.Request) (*models.Summary, error, int) { - user := middlewares.GetPrincipal(r) summaryParams, err := utils.ParseSummaryParams(r) if err != nil { return nil, err, http.StatusBadRequest } + return LoadUserSummaryByParams(ss, summaryParams) +} +func LoadUserSummaryByParams(ss services.ISummaryService, params *models.SummaryParams) (*models.Summary, error, int) { var retrieveSummary services.SummaryRetriever = ss.Retrieve - if summaryParams.Recompute { + if params.Recompute { retrieveSummary = ss.Summarize } - summary, err := ss.Aliased(summaryParams.From, summaryParams.To, summaryParams.User, retrieveSummary, summaryParams.Filters, summaryParams.Recompute) + summary, err := ss.Aliased( + params.From, + params.To, + params.User, + retrieveSummary, + params.Filters, + params.Recompute, + ) if err != nil { return nil, err, http.StatusInternalServerError } - summary.FromTime = models.CustomTime(summary.FromTime.T().In(user.TZ())) - summary.ToTime = models.CustomTime(summary.ToTime.T().In(user.TZ())) + summary.FromTime = models.CustomTime(summary.FromTime.T().In(params.User.TZ())) + summary.ToTime = models.CustomTime(summary.ToTime.T().In(params.User.TZ())) return summary, nil, http.StatusOK } diff --git a/static/assets/css/app.dist.css b/static/assets/css/app.dist.css index 3bc2193..abe1771 100644 --- a/static/assets/css/app.dist.css +++ b/static/assets/css/app.dist.css @@ -1 +1 @@ -/*! tailwindcss v2.2.19 | MIT License | https://tailwindcss.com*//*! modern-normalize v1.1.0 | MIT License | https://github.com/sindresorhus/modern-normalize */html{-moz-tab-size:4;-o-tab-size:4;tab-size:4;line-height:1.15;-webkit-text-size-adjust:100%}body{margin:0;font-family:system-ui,-apple-system,Segoe UI,Roboto,Helvetica,Arial,sans-serif,Apple Color Emoji,Segoe UI Emoji}hr{height:0;color:inherit}abbr[title]{-webkit-text-decoration:underline dotted;text-decoration:underline dotted}b,strong{font-weight:bolder}code,kbd,pre,samp{font-family:ui-monospace,SFMono-Regular,Consolas,Liberation Mono,Menlo,monospace;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:initial}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit}button,input,optgroup,select,textarea{font-family:inherit;font-size:100%;line-height:1.15;margin:0}button,select{text-transform:none}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button}::-moz-focus-inner{border-style:none;padding:0}legend{padding:0}progress{vertical-align:initial}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dd,dl,figure,h1,h2,h3,h4,h5,h6,hr,p,pre{margin:0}button{background-color:initial;background-image:none}fieldset,ol,ul{margin:0;padding:0}ol,ul{list-style:none}html{font-family:ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,Noto Sans,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji;line-height:1.5}body{font-family:inherit;line-height:inherit}*,:after,:before{box-sizing:border-box;border:0 solid}hr{border-top-width:1px}img{border-style:solid}textarea{resize:vertical}input::-moz-placeholder,textarea::-moz-placeholder{opacity:1;color:#9ca3af}input:-ms-input-placeholder,textarea:-ms-input-placeholder{opacity:1;color:#9ca3af}input::placeholder,textarea::placeholder{opacity:1;color:#9ca3af}button{cursor:pointer}table{border-collapse:collapse}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}button,input,optgroup,select,textarea{padding:0;line-height:inherit;color:inherit}code,kbd,pre,samp{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace}audio,canvas,embed,iframe,img,object,svg,video{display:block;vertical-align:middle}img,video{max-width:100%;height:auto}[hidden]{display:none}*,:after,:before{--tw-border-opacity:1;border-color:rgba(229,231,235,var(--tw-border-opacity))}.absolute{position:absolute}.relative{position:relative}.top-0{top:0}.right-0{right:0}.z-10{z-index:10}.row-span-2{grid-row:span 2/span 2}.float-right{float:right}.m-0{margin:0}.mx-1{margin-left:.25rem;margin-right:.25rem}.mx-2{margin-left:.5rem;margin-right:.5rem}.mx-auto{margin-left:auto;margin-right:auto}.my-1{margin-top:.25rem;margin-bottom:.25rem}.my-2{margin-top:.5rem;margin-bottom:.5rem}.my-4{margin-top:1rem;margin-bottom:1rem}.my-8{margin-top:2rem;margin-bottom:2rem}.mt-1{margin-top:.25rem}.mt-2{margin-top:.5rem}.mt-4{margin-top:1rem}.mt-6{margin-top:1.5rem}.mt-8{margin-top:2rem}.mt-10{margin-top:2.5rem}.mt-12{margin-top:3rem}.mt-16{margin-top:4rem}.mt-20{margin-top:5rem}.mr-1{margin-right:.25rem}.mr-2{margin-right:.5rem}.mr-4{margin-right:1rem}.mr-8{margin-right:2rem}.mb-2{margin-bottom:.5rem}.mb-4{margin-bottom:1rem}.mb-8{margin-bottom:2rem}.mb-10{margin-bottom:2.5rem}.mb-16{margin-bottom:4rem}.-mb-1{margin-bottom:-.25rem}.ml-1{margin-left:.25rem}.ml-2{margin-left:.5rem}.ml-4{margin-left:1rem}.-ml-1{margin-left:-.25rem}.block{display:block}.inline-block{display:inline-block}.inline{display:inline}.flex{display:flex}.inline-flex{display:inline-flex}.table{display:table}.grid{display:grid}.hidden{display:none}.h-4{height:1rem}.h-full{height:100%}.min-h-screen{min-height:100vh}.w-4{width:1rem}.w-12{width:3rem}.w-40{width:10rem}.w-1\/2{width:50%}.w-full{width:100%}.max-w-lg{max-width:32rem}.max-w-4xl{max-width:56rem}.max-w-screen-sm{max-width:640px}.max-w-screen-lg{max-width:1024px}.max-w-screen-xl{max-width:1280px}.flex-1{flex:1 1 0%}.flex-shrink-0{flex-shrink:0}.flex-shrink{flex-shrink:1}.flex-grow{flex-grow:1}@-webkit-keyframes spin{to{transform:rotate(1turn)}}@keyframes spin{to{transform:rotate(1turn)}}@-webkit-keyframes ping{75%,to{transform:scale(2);opacity:0}}@keyframes ping{75%,to{transform:scale(2);opacity:0}}@-webkit-keyframes pulse{50%{opacity:.5}}@keyframes pulse{50%{opacity:.5}}@-webkit-keyframes bounce{0%,to{transform:translateY(-25%);-webkit-animation-timing-function:cubic-bezier(.8,0,1,1);animation-timing-function:cubic-bezier(.8,0,1,1)}50%{transform:none;-webkit-animation-timing-function:cubic-bezier(0,0,.2,1);animation-timing-function:cubic-bezier(0,0,.2,1)}}@keyframes bounce{0%,to{transform:translateY(-25%);-webkit-animation-timing-function:cubic-bezier(.8,0,1,1);animation-timing-function:cubic-bezier(.8,0,1,1)}50%{transform:none;-webkit-animation-timing-function:cubic-bezier(0,0,.2,1);animation-timing-function:cubic-bezier(0,0,.2,1)}}.cursor-pointer{cursor:pointer}.cursor-not-allowed{cursor:not-allowed}.resize{resize:both}.appearance-none{-webkit-appearance:none;-moz-appearance:none;appearance:none}.grid-cols-1{grid-template-columns:repeat(1,minmax(0,1fr))}.flex-col{flex-direction:column}.flex-wrap{flex-wrap:wrap}.flex-nowrap{flex-wrap:nowrap}.items-center{align-items:center}.justify-end{justify-content:flex-end}.justify-center{justify-content:center}.justify-between{justify-content:space-between}.gap-2{gap:.5rem}.gap-x-4{-moz-column-gap:1rem;column-gap:1rem}.gap-x-6{-moz-column-gap:1.5rem;column-gap:1.5rem}.gap-y-6{row-gap:1.5rem}.space-x-1>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-right:calc(.25rem*var(--tw-space-x-reverse));margin-left:calc(.25rem*(1 - var(--tw-space-x-reverse)))}.space-x-2>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-right:calc(.5rem*var(--tw-space-x-reverse));margin-left:calc(.5rem*(1 - var(--tw-space-x-reverse)))}.space-x-4>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-right:calc(1rem*var(--tw-space-x-reverse));margin-left:calc(1rem*(1 - var(--tw-space-x-reverse)))}.space-x-8>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-right:calc(2rem*var(--tw-space-x-reverse));margin-left:calc(2rem*(1 - var(--tw-space-x-reverse)))}.space-y-1>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(.25rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.25rem*var(--tw-space-y-reverse))}.space-y-2>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(.5rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.5rem*var(--tw-space-y-reverse))}.space-y-4>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(1rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(1rem*var(--tw-space-y-reverse))}.space-y-8>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(2rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(2rem*var(--tw-space-y-reverse))}.truncate{overflow:hidden;text-overflow:ellipsis}.truncate,.whitespace-nowrap{white-space:nowrap}.rounded-sm{border-radius:.125rem}.rounded{border-radius:.25rem}.rounded-md{border-radius:.375rem}.rounded-full{border-radius:9999px}.border-2{border-width:2px}.border-4{border-width:4px}.border{border-width:1px}.border-t{border-top-width:1px}.border-l{border-left-width:1px}.border-gray-700{--tw-border-opacity:1;border-color:rgba(55,65,81,var(--tw-border-opacity))}.border-gray-800{--tw-border-opacity:1;border-color:rgba(31,41,55,var(--tw-border-opacity))}.border-green-700{--tw-border-opacity:1;border-color:rgba(4,120,87,var(--tw-border-opacity))}.bg-transparent{background-color:initial}.bg-gray-800{--tw-bg-opacity:1;background-color:rgba(31,41,55,var(--tw-bg-opacity))}.bg-gray-900{--tw-bg-opacity:1;background-color:rgba(17,24,39,var(--tw-bg-opacity))}.bg-red-500{--tw-bg-opacity:1;background-color:rgba(239,68,68,var(--tw-bg-opacity))}.bg-green-500{--tw-bg-opacity:1;background-color:rgba(16,185,129,var(--tw-bg-opacity))}.hover\:bg-gray-700:hover{--tw-bg-opacity:1;background-color:rgba(55,65,81,var(--tw-bg-opacity))}.focus\:bg-gray-800:focus,.hover\:bg-gray-800:hover{--tw-bg-opacity:1;background-color:rgba(31,41,55,var(--tw-bg-opacity))}.p-1{padding:.25rem}.p-2{padding:.5rem}.p-4{padding:1rem}.px-2{padding-left:.5rem;padding-right:.5rem}.px-4{padding-left:1rem;padding-right:1rem}.px-6{padding-left:1.5rem;padding-right:1.5rem}.px-8{padding-left:2rem;padding-right:2rem}.py-1{padding-top:.25rem;padding-bottom:.25rem}.py-2{padding-top:.5rem;padding-bottom:.5rem}.py-4{padding-top:1rem;padding-bottom:1rem}.pt-10{padding-top:2.5rem}.pb-4{padding-bottom:1rem}.pb-10{padding-bottom:2.5rem}.text-left{text-align:left}.text-center{text-align:center}.text-right{text-align:right}.align-middle{vertical-align:middle}.font-mono{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace}.text-xs{font-size:.75rem;line-height:1rem}.text-sm{font-size:.875rem;line-height:1.25rem}.text-lg{font-size:1.125rem;line-height:1.75rem}.text-xl{font-size:1.25rem;line-height:1.75rem}.text-2xl{font-size:1.5rem;line-height:2rem}.text-3xl{font-size:1.875rem;line-height:2.25rem}.text-8xl{font-size:6rem;line-height:1}.font-semibold{font-weight:600}.capitalize{text-transform:capitalize}.leading-none{line-height:1}.leading-snug{line-height:1.375}.text-white{--tw-text-opacity:1;color:rgba(255,255,255,var(--tw-text-opacity))}.text-gray-300{--tw-text-opacity:1;color:rgba(209,213,219,var(--tw-text-opacity))}.text-gray-400{--tw-text-opacity:1;color:rgba(156,163,175,var(--tw-text-opacity))}.text-gray-500{--tw-text-opacity:1;color:rgba(107,114,128,var(--tw-text-opacity))}.text-gray-600{--tw-text-opacity:1;color:rgba(75,85,99,var(--tw-text-opacity))}.text-gray-700{--tw-text-opacity:1;color:rgba(55,65,81,var(--tw-text-opacity))}.text-red-600{--tw-text-opacity:1;color:rgba(220,38,38,var(--tw-text-opacity))}.text-green-700{--tw-text-opacity:1;color:rgba(4,120,87,var(--tw-text-opacity))}.hover\:text-gray-300:hover{--tw-text-opacity:1;color:rgba(209,213,219,var(--tw-text-opacity))}.hover\:text-gray-400:hover{--tw-text-opacity:1;color:rgba(156,163,175,var(--tw-text-opacity))}.hover\:text-gray-500:hover{--tw-text-opacity:1;color:rgba(107,114,128,var(--tw-text-opacity))}.antialiased{-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}*,:after,:before{--tw-shadow:0 0 #0000}.shadow{--tw-shadow:0 1px 3px 0 rgba(0,0,0,0.1),0 1px 2px 0 rgba(0,0,0,0.06)}.shadow,.shadow-md{box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.shadow-md{--tw-shadow:0 4px 6px -1px rgba(0,0,0,0.1),0 2px 4px -1px rgba(0,0,0,0.06)}.outline-none{outline:2px solid transparent;outline-offset:2px}*,:after,:before{--tw-ring-inset:var(--tw-empty,/*!*/ /*!*/);--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:rgba(59,130,246,0.5);--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000}body{font-family:Source Sans\ 3,Roboto,Helvetica Neue,Helvetica,Arial,sans-serif}[v-cloak]{display:none}.bg-gray-850{background-color:#242b3a}.hover\:bg-gray-850:hover{--bg-opacity:1;background-color:#242b3a}.text-xxs{font-size:.65rem}.text-8xl{font-size:5rem;line-height:1.1}.imp\:cursor-not-allowed{cursor:not-allowed!important}.h1{margin:0;font-size:1.875rem;line-height:2.25rem;font-weight:600;--tw-text-opacity:1;color:rgba(255,255,255,var(--tw-text-opacity))}.h1-subcaption{--tw-text-opacity:1;color:rgba(75,85,99,var(--tw-text-opacity))}.btn-default,.h1-subcaption{font-size:.875rem;line-height:1.25rem}.btn-default{border-radius:.25rem;--tw-bg-opacity:1;background-color:rgba(31,41,55,var(--tw-bg-opacity));padding:.5rem 1rem;font-weight:600;--tw-text-opacity:1;color:rgba(255,255,255,var(--tw-text-opacity))}.btn-default:hover{--bg-opacity:1;background-color:#242b3a}.btn-disabled{border-radius:.25rem;--tw-bg-opacity:1;background-color:rgba(31,41,55,var(--tw-bg-opacity));padding:.5rem 1rem;font-size:.875rem;line-height:1.25rem;font-weight:600;--tw-text-opacity:1;color:rgba(75,85,99,var(--tw-text-opacity))}.btn-primary{border-radius:.25rem;--tw-bg-opacity:1;background-color:rgba(4,120,87,var(--tw-bg-opacity))}.btn-primary:hover{--tw-bg-opacity:1;background-color:rgba(6,95,70,var(--tw-bg-opacity))}.btn-primary{padding:.5rem 1rem;font-size:.875rem;line-height:1.25rem;font-weight:600;--tw-text-opacity:1;color:rgba(255,255,255,var(--tw-text-opacity))}.btn-danger{border-radius:.25rem;--tw-bg-opacity:1;background-color:rgba(220,38,38,var(--tw-bg-opacity))}.btn-danger:hover{--tw-bg-opacity:1;background-color:rgba(185,28,28,var(--tw-bg-opacity))}.btn-danger{padding:.5rem 1rem;font-size:.875rem;line-height:1.25rem;font-weight:600;--tw-text-opacity:1;color:rgba(255,255,255,var(--tw-text-opacity))}.input-default{width:100%;-webkit-appearance:none;-moz-appearance:none;appearance:none;border-radius:.25rem}.input-default:focus{--tw-bg-opacity:1;background-color:rgba(31,41,55,var(--tw-bg-opacity))}.input-default{padding:.5rem 1rem;--tw-text-opacity:1;color:rgba(209,213,219,var(--tw-text-opacity));outline:2px solid transparent;outline-offset:2px;background-color:#242b3a}.select-default{cursor:pointer;width:100%;-webkit-appearance:none;-moz-appearance:none;appearance:none;border-radius:.25rem}.select-default:focus{--tw-bg-opacity:1;background-color:rgba(31,41,55,var(--tw-bg-opacity))}.select-default{padding:.5rem 1rem;--tw-text-opacity:1;color:rgba(209,213,219,var(--tw-text-opacity));outline:2px solid transparent;outline-offset:2px;background-color:#242b3a}.menu-item{display:flex;cursor:pointer;align-items:center}.menu-item>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-right:calc(.5rem*var(--tw-space-x-reverse));margin-left:calc(.5rem*(1 - var(--tw-space-x-reverse)))}.menu-item{border-radius:.25rem;padding:.5rem 1rem;font-size:.875rem;line-height:1.25rem;font-weight:600}.menu-item:hover{--bg-opacity:1;background-color:#242b3a}.submenu-item{border-radius:.25rem}.submenu-item:hover{--tw-bg-opacity:1;background-color:rgba(31,41,55,var(--tw-bg-opacity))}.submenu-item{padding:.25rem;text-align:right}.chip{margin-bottom:.25rem;display:inline-block;border-radius:.25rem;border-radius:9999px;padding:.25rem .5rem;font-size:.75rem;line-height:1rem;background-color:#242b3a}.chip,.link{font-weight:600}.link{color:rgba(156,163,175,var(--tw-text-opacity))}.link,.link:hover{--tw-text-opacity:1}.link:hover{color:rgba(209,213,219,var(--tw-text-opacity))}::-webkit-calendar-picker-indicator{filter:invert(1);cursor:pointer}@media (min-width:640px){.sm\:inline-block{display:inline-block}.sm\:flex{display:flex}}@media (min-width:768px){.md\:mb-0{margin-bottom:0}.md\:flex{display:flex}.md\:w-1\/2{width:50%}.md\:w-1\/3{width:33.333333%}.md\:w-2\/3{width:66.666667%}.md\:w-3\/4{width:75%}.md\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.md\:flex-nowrap{flex-wrap:nowrap}.md\:px-10{padding-left:2.5rem;padding-right:2.5rem}}@media (min-width:1024px){.lg\:inline-block{display:inline-block}.lg\:w-3\/4{width:75%}.lg\:px-24{padding-left:6rem;padding-right:6rem}} \ No newline at end of file +/*! tailwindcss v2.2.19 | MIT License | https://tailwindcss.com*//*! modern-normalize v1.1.0 | MIT License | https://github.com/sindresorhus/modern-normalize */html{-moz-tab-size:4;-o-tab-size:4;tab-size:4;line-height:1.15;-webkit-text-size-adjust:100%}body{margin:0;font-family:system-ui,-apple-system,Segoe UI,Roboto,Helvetica,Arial,sans-serif,Apple Color Emoji,Segoe UI Emoji}hr{height:0;color:inherit}abbr[title]{-webkit-text-decoration:underline dotted;text-decoration:underline dotted}b,strong{font-weight:bolder}code,kbd,pre,samp{font-family:ui-monospace,SFMono-Regular,Consolas,Liberation Mono,Menlo,monospace;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:initial}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit}button,input,optgroup,select,textarea{font-family:inherit;font-size:100%;line-height:1.15;margin:0}button,select{text-transform:none}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button}::-moz-focus-inner{border-style:none;padding:0}legend{padding:0}progress{vertical-align:initial}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dd,dl,figure,h1,h2,h3,h4,h5,h6,hr,p,pre{margin:0}button{background-color:initial;background-image:none}fieldset,ol,ul{margin:0;padding:0}ol,ul{list-style:none}html{font-family:ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,Noto Sans,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji;line-height:1.5}body{font-family:inherit;line-height:inherit}*,:after,:before{box-sizing:border-box;border:0 solid}hr{border-top-width:1px}img{border-style:solid}textarea{resize:vertical}input::-moz-placeholder,textarea::-moz-placeholder{opacity:1;color:#9ca3af}input:-ms-input-placeholder,textarea:-ms-input-placeholder{opacity:1;color:#9ca3af}input::placeholder,textarea::placeholder{opacity:1;color:#9ca3af}button{cursor:pointer}table{border-collapse:collapse}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}button,input,optgroup,select,textarea{padding:0;line-height:inherit;color:inherit}code,kbd,pre,samp{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace}audio,canvas,embed,iframe,img,object,svg,video{display:block;vertical-align:middle}img,video{max-width:100%;height:auto}[hidden]{display:none}*,:after,:before{--tw-border-opacity:1;border-color:rgba(229,231,235,var(--tw-border-opacity))}.absolute{position:absolute}.relative{position:relative}.top-0{top:0}.right-0{right:0}.z-10{z-index:10}.row-span-2{grid-row:span 2/span 2}.float-right{float:right}.m-0{margin:0}.mx-1{margin-left:.25rem;margin-right:.25rem}.mx-2{margin-left:.5rem;margin-right:.5rem}.mx-auto{margin-left:auto;margin-right:auto}.my-1{margin-top:.25rem;margin-bottom:.25rem}.my-2{margin-top:.5rem;margin-bottom:.5rem}.my-4{margin-top:1rem;margin-bottom:1rem}.my-8{margin-top:2rem;margin-bottom:2rem}.mt-1{margin-top:.25rem}.mt-2{margin-top:.5rem}.mt-4{margin-top:1rem}.mt-6{margin-top:1.5rem}.mt-8{margin-top:2rem}.mt-10{margin-top:2.5rem}.mt-12{margin-top:3rem}.mt-16{margin-top:4rem}.mt-20{margin-top:5rem}.mr-1{margin-right:.25rem}.mr-2{margin-right:.5rem}.mr-4{margin-right:1rem}.mr-8{margin-right:2rem}.mb-2{margin-bottom:.5rem}.mb-4{margin-bottom:1rem}.mb-8{margin-bottom:2rem}.mb-10{margin-bottom:2.5rem}.mb-16{margin-bottom:4rem}.-mb-1{margin-bottom:-.25rem}.ml-1{margin-left:.25rem}.ml-2{margin-left:.5rem}.ml-4{margin-left:1rem}.-ml-1{margin-left:-.25rem}.block{display:block}.inline-block{display:inline-block}.inline{display:inline}.flex{display:flex}.inline-flex{display:inline-flex}.table{display:table}.grid{display:grid}.hidden{display:none}.h-4{height:1rem}.h-full{height:100%}.min-h-screen{min-height:100vh}.w-4{width:1rem}.w-12{width:3rem}.w-40{width:10rem}.w-1\/2{width:50%}.w-1\/3{width:33.333333%}.w-2\/3{width:66.666667%}.w-full{width:100%}.max-w-lg{max-width:32rem}.max-w-4xl{max-width:56rem}.max-w-screen-sm{max-width:640px}.max-w-screen-lg{max-width:1024px}.max-w-screen-xl{max-width:1280px}.flex-1{flex:1 1 0%}.flex-shrink-0{flex-shrink:0}.flex-shrink{flex-shrink:1}.flex-grow{flex-grow:1}@-webkit-keyframes spin{to{transform:rotate(1turn)}}@keyframes spin{to{transform:rotate(1turn)}}@-webkit-keyframes ping{75%,to{transform:scale(2);opacity:0}}@keyframes ping{75%,to{transform:scale(2);opacity:0}}@-webkit-keyframes pulse{50%{opacity:.5}}@keyframes pulse{50%{opacity:.5}}@-webkit-keyframes bounce{0%,to{transform:translateY(-25%);-webkit-animation-timing-function:cubic-bezier(.8,0,1,1);animation-timing-function:cubic-bezier(.8,0,1,1)}50%{transform:none;-webkit-animation-timing-function:cubic-bezier(0,0,.2,1);animation-timing-function:cubic-bezier(0,0,.2,1)}}@keyframes bounce{0%,to{transform:translateY(-25%);-webkit-animation-timing-function:cubic-bezier(.8,0,1,1);animation-timing-function:cubic-bezier(.8,0,1,1)}50%{transform:none;-webkit-animation-timing-function:cubic-bezier(0,0,.2,1);animation-timing-function:cubic-bezier(0,0,.2,1)}}.cursor-pointer{cursor:pointer}.cursor-not-allowed{cursor:not-allowed}.resize{resize:both}.appearance-none{-webkit-appearance:none;-moz-appearance:none;appearance:none}.grid-cols-1{grid-template-columns:repeat(1,minmax(0,1fr))}.flex-col{flex-direction:column}.flex-wrap{flex-wrap:wrap}.flex-nowrap{flex-wrap:nowrap}.items-center{align-items:center}.justify-end{justify-content:flex-end}.justify-center{justify-content:center}.justify-between{justify-content:space-between}.gap-2{gap:.5rem}.gap-x-4{-moz-column-gap:1rem;column-gap:1rem}.gap-x-6{-moz-column-gap:1.5rem;column-gap:1.5rem}.gap-y-6{row-gap:1.5rem}.space-x-1>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-right:calc(.25rem*var(--tw-space-x-reverse));margin-left:calc(.25rem*(1 - var(--tw-space-x-reverse)))}.space-x-2>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-right:calc(.5rem*var(--tw-space-x-reverse));margin-left:calc(.5rem*(1 - var(--tw-space-x-reverse)))}.space-x-4>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-right:calc(1rem*var(--tw-space-x-reverse));margin-left:calc(1rem*(1 - var(--tw-space-x-reverse)))}.space-x-8>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-right:calc(2rem*var(--tw-space-x-reverse));margin-left:calc(2rem*(1 - var(--tw-space-x-reverse)))}.space-y-1>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(.25rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.25rem*var(--tw-space-y-reverse))}.space-y-2>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(.5rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.5rem*var(--tw-space-y-reverse))}.space-y-4>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(1rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(1rem*var(--tw-space-y-reverse))}.space-y-8>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(2rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(2rem*var(--tw-space-y-reverse))}.truncate{overflow:hidden;text-overflow:ellipsis}.truncate,.whitespace-nowrap{white-space:nowrap}.rounded-sm{border-radius:.125rem}.rounded{border-radius:.25rem}.rounded-md{border-radius:.375rem}.rounded-full{border-radius:9999px}.border-2{border-width:2px}.border-4{border-width:4px}.border{border-width:1px}.border-t{border-top-width:1px}.border-l{border-left-width:1px}.border-gray-700{--tw-border-opacity:1;border-color:rgba(55,65,81,var(--tw-border-opacity))}.border-gray-800{--tw-border-opacity:1;border-color:rgba(31,41,55,var(--tw-border-opacity))}.border-green-700{--tw-border-opacity:1;border-color:rgba(4,120,87,var(--tw-border-opacity))}.bg-transparent{background-color:initial}.bg-gray-800{--tw-bg-opacity:1;background-color:rgba(31,41,55,var(--tw-bg-opacity))}.bg-gray-900{--tw-bg-opacity:1;background-color:rgba(17,24,39,var(--tw-bg-opacity))}.bg-red-500{--tw-bg-opacity:1;background-color:rgba(239,68,68,var(--tw-bg-opacity))}.bg-green-500{--tw-bg-opacity:1;background-color:rgba(16,185,129,var(--tw-bg-opacity))}.hover\:bg-gray-700:hover{--tw-bg-opacity:1;background-color:rgba(55,65,81,var(--tw-bg-opacity))}.focus\:bg-gray-800:focus,.hover\:bg-gray-800:hover{--tw-bg-opacity:1;background-color:rgba(31,41,55,var(--tw-bg-opacity))}.p-1{padding:.25rem}.p-2{padding:.5rem}.p-4{padding:1rem}.px-2{padding-left:.5rem;padding-right:.5rem}.px-4{padding-left:1rem;padding-right:1rem}.px-6{padding-left:1.5rem;padding-right:1.5rem}.px-8{padding-left:2rem;padding-right:2rem}.py-1{padding-top:.25rem;padding-bottom:.25rem}.py-2{padding-top:.5rem;padding-bottom:.5rem}.py-4{padding-top:1rem;padding-bottom:1rem}.pt-10{padding-top:2.5rem}.pb-4{padding-bottom:1rem}.pb-10{padding-bottom:2.5rem}.text-left{text-align:left}.text-center{text-align:center}.text-right{text-align:right}.align-middle{vertical-align:middle}.font-mono{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace}.text-xs{font-size:.75rem;line-height:1rem}.text-sm{font-size:.875rem;line-height:1.25rem}.text-lg{font-size:1.125rem;line-height:1.75rem}.text-xl{font-size:1.25rem;line-height:1.75rem}.text-2xl{font-size:1.5rem;line-height:2rem}.text-3xl{font-size:1.875rem;line-height:2.25rem}.text-8xl{font-size:6rem;line-height:1}.font-semibold{font-weight:600}.capitalize{text-transform:capitalize}.leading-none{line-height:1}.leading-snug{line-height:1.375}.text-white{--tw-text-opacity:1;color:rgba(255,255,255,var(--tw-text-opacity))}.text-gray-300{--tw-text-opacity:1;color:rgba(209,213,219,var(--tw-text-opacity))}.text-gray-400{--tw-text-opacity:1;color:rgba(156,163,175,var(--tw-text-opacity))}.text-gray-500{--tw-text-opacity:1;color:rgba(107,114,128,var(--tw-text-opacity))}.text-gray-600{--tw-text-opacity:1;color:rgba(75,85,99,var(--tw-text-opacity))}.text-gray-700{--tw-text-opacity:1;color:rgba(55,65,81,var(--tw-text-opacity))}.text-red-600{--tw-text-opacity:1;color:rgba(220,38,38,var(--tw-text-opacity))}.text-green-700{--tw-text-opacity:1;color:rgba(4,120,87,var(--tw-text-opacity))}.hover\:text-gray-300:hover{--tw-text-opacity:1;color:rgba(209,213,219,var(--tw-text-opacity))}.hover\:text-gray-400:hover{--tw-text-opacity:1;color:rgba(156,163,175,var(--tw-text-opacity))}.hover\:text-gray-500:hover{--tw-text-opacity:1;color:rgba(107,114,128,var(--tw-text-opacity))}.antialiased{-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}*,:after,:before{--tw-shadow:0 0 #0000}.shadow{--tw-shadow:0 1px 3px 0 rgba(0,0,0,0.1),0 1px 2px 0 rgba(0,0,0,0.06)}.shadow,.shadow-md{box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.shadow-md{--tw-shadow:0 4px 6px -1px rgba(0,0,0,0.1),0 2px 4px -1px rgba(0,0,0,0.06)}.outline-none{outline:2px solid transparent;outline-offset:2px}*,:after,:before{--tw-ring-inset:var(--tw-empty,/*!*/ /*!*/);--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:rgba(59,130,246,0.5);--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000}body{font-family:Source Sans\ 3,Roboto,Helvetica Neue,Helvetica,Arial,sans-serif}[v-cloak]{display:none}.bg-gray-850{background-color:#242b3a}.hover\:bg-gray-850:hover{--bg-opacity:1;background-color:#242b3a}.text-xxs{font-size:.65rem}.text-8xl{font-size:5rem;line-height:1.1}.imp\:cursor-not-allowed{cursor:not-allowed!important}.h1{margin:0;font-size:1.875rem;line-height:2.25rem;font-weight:600;--tw-text-opacity:1;color:rgba(255,255,255,var(--tw-text-opacity))}.h1-subcaption{--tw-text-opacity:1;color:rgba(75,85,99,var(--tw-text-opacity))}.btn-default,.h1-subcaption{font-size:.875rem;line-height:1.25rem}.btn-default{border-radius:.25rem;--tw-bg-opacity:1;background-color:rgba(31,41,55,var(--tw-bg-opacity));padding:.5rem 1rem;font-weight:600;--tw-text-opacity:1;color:rgba(255,255,255,var(--tw-text-opacity))}.btn-default:hover{--bg-opacity:1;background-color:#242b3a}.btn-disabled{border-radius:.25rem;--tw-bg-opacity:1;background-color:rgba(31,41,55,var(--tw-bg-opacity));padding:.5rem 1rem;font-size:.875rem;line-height:1.25rem;font-weight:600;--tw-text-opacity:1;color:rgba(75,85,99,var(--tw-text-opacity))}.btn-primary{border-radius:.25rem;--tw-bg-opacity:1;background-color:rgba(4,120,87,var(--tw-bg-opacity))}.btn-primary:hover{--tw-bg-opacity:1;background-color:rgba(6,95,70,var(--tw-bg-opacity))}.btn-primary{padding:.5rem 1rem;font-size:.875rem;line-height:1.25rem;font-weight:600;--tw-text-opacity:1;color:rgba(255,255,255,var(--tw-text-opacity))}.btn-danger{border-radius:.25rem;--tw-bg-opacity:1;background-color:rgba(220,38,38,var(--tw-bg-opacity))}.btn-danger:hover{--tw-bg-opacity:1;background-color:rgba(185,28,28,var(--tw-bg-opacity))}.btn-danger{padding:.5rem 1rem;font-size:.875rem;line-height:1.25rem;font-weight:600;--tw-text-opacity:1;color:rgba(255,255,255,var(--tw-text-opacity))}.input-default{width:100%;-webkit-appearance:none;-moz-appearance:none;appearance:none;border-radius:.25rem}.input-default:focus{--tw-bg-opacity:1;background-color:rgba(31,41,55,var(--tw-bg-opacity))}.input-default{padding:.5rem 1rem;--tw-text-opacity:1;color:rgba(209,213,219,var(--tw-text-opacity));outline:2px solid transparent;outline-offset:2px;background-color:#242b3a}.select-default{cursor:pointer;width:100%;-webkit-appearance:none;-moz-appearance:none;appearance:none;border-radius:.25rem}.select-default:focus{--tw-bg-opacity:1;background-color:rgba(31,41,55,var(--tw-bg-opacity))}.select-default{padding:.5rem 1rem;--tw-text-opacity:1;color:rgba(209,213,219,var(--tw-text-opacity));outline:2px solid transparent;outline-offset:2px;background-color:#242b3a}.menu-item{display:flex;cursor:pointer;align-items:center}.menu-item>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-right:calc(.5rem*var(--tw-space-x-reverse));margin-left:calc(.5rem*(1 - var(--tw-space-x-reverse)))}.menu-item{border-radius:.25rem;padding:.5rem 1rem;font-size:.875rem;line-height:1.25rem;font-weight:600}.menu-item:hover{--bg-opacity:1;background-color:#242b3a}.submenu-item{border-radius:.25rem}.submenu-item:hover{--tw-bg-opacity:1;background-color:rgba(31,41,55,var(--tw-bg-opacity))}.submenu-item{padding:.25rem;text-align:right}.chip{margin-bottom:.25rem;display:inline-block;border-radius:.25rem;border-radius:9999px;padding:.25rem .5rem;font-size:.75rem;line-height:1rem;background-color:#242b3a}.chip,.link{font-weight:600}.link{color:rgba(156,163,175,var(--tw-text-opacity))}.link,.link:hover{--tw-text-opacity:1}.link:hover{color:rgba(209,213,219,var(--tw-text-opacity))}::-webkit-calendar-picker-indicator{filter:invert(1);cursor:pointer}@media (min-width:640px){.sm\:inline-block{display:inline-block}.sm\:flex{display:flex}}@media (min-width:768px){.md\:mb-0{margin-bottom:0}.md\:flex{display:flex}.md\:w-1\/2{width:50%}.md\:w-1\/3{width:33.333333%}.md\:w-2\/3{width:66.666667%}.md\:w-3\/4{width:75%}.md\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.md\:flex-nowrap{flex-wrap:nowrap}.md\:px-10{padding-left:2.5rem;padding-right:2.5rem}}@media (min-width:1024px){.lg\:inline-block{display:inline-block}.lg\:w-3\/4{width:75%}.lg\:px-24{padding-left:6rem;padding-right:6rem}} \ No newline at end of file diff --git a/static/assets/css/app.dist.css.br b/static/assets/css/app.dist.css.br index 34b8ad36df3903facbf73ab3ee28a2f1d038b72f..2bc790ac656e79575c3aa058798c7f6a14820d49 100644 GIT binary patch literal 3084 zcmV+n4D<8hNZtWpRbV%N_yPu4qlPH69_gVL;`NIMsc6e-eFD`dJ5iuCO`UKiNYA%v zpH)lgzoVD4gQDK)lN+$&B?|&y|I)}xomH*VJ;}aZoxtv%X?h1q3c)vjYxx|$bt#l! zBYiEJjqF^V3d!8_0WE>fmM6t?&TG5u&8X@9>$I}f+5xZ2J#Gn_%F+QqQ=@0*YhLti zIp8JWulbTe3fV`*C6+y41=!WTR9jwu?}ysI^z2GHZYbhLBy|73*L3O>2bNm&U!C{e z?H9tlFa8&=_bDB`?HYQjrY1Zjedwh^LfKuy|1yv_Y(L{hMB9w)@ph(s`}UKSdE>or zZ|DB;ICL>p#J$xl_=$|EHoppcy)r8s^AJkX2AJ!r7Wzm#0?tJ{=Yj9bLdv61hENWz z!>*7i>oVxYzQ2~v?*9(`w4dMUNxkw>a-{2MW3AGfWJD;U*>q3*zaSv174}4pZXh?x z;m3^gjS%S{kKqtZD(poFwEfNM^KtMTfacrvsa?s+0{lL_+08T4Ow6>7ObOf29NBhP zuwd!c>j3)QlaBx78t-(Q?7haFH~^S-rFT+0`3+UzU!wL+x2dx>mb|N!N0K%F%uRy3NYHCl*Xf=+u zRH7CiP)iSIneuI<8f%=Tf_k-21*7m%ytrlip4tst_eca={S`Jy;XOli;kJpuxaJtG zzvNx#+2LCh(uy515#ddfjL}W#KOn^=kjhaZOR$`{xD`Q7R7DmbzCOslHtLE!$oAC#QQr{- zo=xNVM`p>anJu$tj=7Q6Eh$M$I7MYHD%VC3#CDV>>MIW6gI1Mx6{A@^D>nRAx|cHAGME;?tW2r^2b*68o3FR=|^fWTGZO! z&P-q~%6Z$B?;@+zbiqrt%lEbjS*PlI(N?wiVK3?gK$6Xy(J8L&wcw@O+m=>BUbyuW z2Nd`wp^aFmmS*<5e6~1Ob@e$41z^s0s2}j_`iE|rStR^rM=65DM>~Qha@qRpc^Fz!kVc^HAGrwKhcX*Fyd zngSERIO18bmuWe+ZBs$r4=83%*(OrUP9 zhGrbQvx5mH0YK}X#rH3;V1zJA7{i!cs|7>s_+^X+DyR>$qYwv>Aab|5>p_tfQ6 zGONVJxGRc-zD+=FmA;p?QW{fq5VCDW7QDp0f2zHbN=8>c3vW|-K>*;Go_t4K7)#eQ z0%sBk%B7}X|5NSCo)RO7K1c%!23fJ>1A=D{%(Si=qc3j|213vVd$vNAe=B(}c7ou@kP4Z2l@Thbw>;y}#e-OD zXdIk&fQ%hl_8+g9<&^vd7$Ju#*s+hZ@NG?dGmQSz8TkB=8^vwu5pY{=f@zG?M!yw} zYCI3>GY3l$-g|uyYo1sX{W7Al`O9C#9E~u)z%yT5Ec`Yo!sjWc*4Wh2ocB6qOku_l z=Dd$n&Q+dkyp~RYvp7At%%kEJo`gYL*n2deW`xgscGbz$#+>KcH7+n?0&||nuJeTF zi0?JWQ*u05S16)njvd}%P-_``**$4`x^aY7b#7=&A#wMn)DspWku-7NEzafKeK}W8 zh7u2gX^+LRb**1C))CI2g8*X-QIiCu*#}j<#|Ifu$5S=?JjjIGaYjVZ7&7 zeUqYs8MePvTRFp-50a_FH~2PD3DoZV!Jz<6KtvanCT9L@av~G-rFGn38h{1J)BLx&rnE^vpCZ!8CNpki1t-ym%g5GzErnyZBUW8?beWXTe?` z_W&%Q<&7vy&U(R%-LP?L8cYcWWwxPBKtwqq`*R3Mwh7%4CO=X2ACsOr352pK zG^sil@aK=7I>bKxMryH*A`KnCmz#dlwwCGtUfg|rX>-0+O?$uSJ(5;_2a=j zwuSYAM;B{K;v`QEJh)hE{GDu$o|64VmDkcFTTy`t>%^?^J}1H6mDw*3dMoD$euxahHrUI9WtKCuQsN|c=4S2T zbKUEZ97Im*U!mkF=jva(hESNuO(pI;OA(1~%%k34ceV*e0>%4W?e_&@hqCx6tJCRI z9b6#`F5b3<>Wr-fvBqDzvpmmo{dwjTjnOhjC^MzUpp8Ra<>8)?d(bJ-+LLm}9AoEULq=ojLB;WjuO;MKbw^Z=3Tiz(lE0waD09vDR2(se$|)nVCMb3Bt`N%_i8Id7U+2=5&ro6 zU>J*C@NyW0@mF&Wv;LC~d2A-BhV_%Ydy4h{zU+uzVAf2le-%=)%|DS_njb*lOO^zB2MtwyEP;W*+5*1FPj1$bz0M8;E@p$zD_hWx{1DJ=Se?aB3(i zDLj%@b%I1n!f(yyIURFEg-D=mJ|xb zsy)EIC%JXe99=sJ?TmiZ46LR+!-GgAMN|Om9C5aQUXp941QF-+eoYywMVuaPC1}rf z>l(F$5c;qyq2oy{qvb5c)~9D!E=%snrG~-;@<>P{iV&J+m>M>2^QKAO?J&!DBUol` zcs#B7ebbL+^u0~w%G)vF*j|UNZms>OGqR#f`DR|m68&uSV-eJ%3~R%ER46S^zx!+g z8pOjgyUOV3BC4VCY*$4k0J}OWPZ`^%GlEtCt9@lt+OKp&VL^T_RJ~RnUvQe;o>U|F20u?dKPI zvYff4DbjVcajDWC$%s%yv++Ljzl4CSmfJCEbbYx}4&P^-YlO)Aejg6Lra~+{?snd+ zKDWkm0Gemxr*>s43-J5!W)sg$GcnUTG9}Eb=E&B&gau2fUi;B+?~4@tC)aqV+ohHz zR^k9)+L_+TQpj(hV$XfbRtxn8_H`pyR?A4KtS$?JR^_TP%TR5l%B&g^Agn4m+0vAo zp0c5zoq4qagYCi7j9W92nI!;W%bZgn)D%5xPfKaFwzgEE7VlF_4`!M2t)&`koS}j` zwNC}3@KU_EWxJl*jo9}diD2tL$p$IBV~8%?HW3)t9If?Nyz5-^zC|Ie*d7xR-Zbe* zD=^4f=+9-n9j?zSZ#X;O?wa{+Cs22}8Vm!6t^NeUp4Opj4p@^G%({0UrA1D3* zlx9QHyY<}%pP1-<)IM&d`;Ah`A6wCLgO@uE%uBw4>2o#NVF3tqaVd}t-)g4{iJ7nX>GjPCu{X#jo|n-9ecLG!1&y+l}T3g#4Cm9@T+)liJU* z=}qPV0@B`a6*i<+9jpmg;_E+lh$0<2*}ZfY^>_RWCJn|2I-kV-I~p5#<4p)=wK26wCdt+}4p5jA2afsRcu9 z|7FZIP-zvRS>6C)*<)uYp?vOV-0hEZ99IUzrj=&w1?~xR-5q$gz9`pw>W|x>-zCNO zo=61bdLfL}gaAOOCodN`y2GQBifRrpf4$BAlp{al>YbC>k~~1BO|ut(;GqW~L8|Fr zWhejDIAHEf-n!M{+6_S-p_z5O^^3IS7902YD4Pssui%Ygl+CLiG-ySB@wsF#;4bu{ zo&*-JM{}qLmZh>ft`xSZJVP)8nX$d6E}vv#mAGg(EOEfs9;nq2d@pS!WftcEWSf&5 z@PzgLsrJg4CUoUJ@z$3Q1ORrylWP$dM#iy5;7kHRxyAbNKh^A2_Eg+>pa;_MfI*fo zxj~HVfa%tCb7LuINChIzls$GS7by!R0Pw=7N_3Fyh>QcPy0ilGZ$}_n#hdd*@4xO> z0t+iSUV8za<1o;bG9=BKyq-KOn2m=RSN+TNzbMyMOFq_@d_-w)1tMlod3O)i-M(rs zW{e9#jPtjW-eQ*qjtr@gi5D56l3~j;4n!P?HRd#~e6x>i8d?q0_dFA8?- z<1Bnj(@_s&;IsnQ9&n?$Eja>itBv1}SXvDKt!Rwmcu?;kScY)Y>w36MJ;UMe#wVh` z{$XJLM3`UTnID~Zep5q)&r=>2vx(E3_d0D{Va5^WypPk)Ri10SmQH}PI6b(`YsD)) z2}7`;_i#S-2%q=tNXW!v&U5XU5SVd+InQIqdBStV_nPBLrr223LrBiX4(~8nmbBJX zJ$dxt;Rvnj+|ZUn;_gi;8!SK~+2Gz=oYSfLa;=^WC7uM+8jExD-acroBdnlN0AmZ~ z;uC~M9%(w;Xo(7k5;P-Ai)E1BIgk+30-Khf8U#|N_5nJ<3(-#k{&Oqd?ADW~5Ht(tgoJlJRs4CA)(x!9+$w~1%LZXP!P7Ps1fKWosle6c{B!+yFpqs{yWr79nzA^_Q;H`WYmC2@jnPxK z|5D|(B*~l3=!^KceD_d=ODEwA0oA zv0otJr&`$yuV{yqv0$TN?dRzCa*2JMLp>doKwe`som1D(*6;NaM?Z)D%@0Bp>SUjz zVC>4wUk`dK=Lmj?48nHUuLsL4E3;DKBzNX|?cp`?IwS|ttI1a=dFpk^*REj{CURqn zm1ij;(T%xO%CpGU!APKZpR0OZAa*E=53_Nc-lM_ga>Sz-VWGY_TM1&dzx2-j9Fe0` zj0irLneWK`EVzKVLs+HXX=vnMQFHp;Ev+IAQRQBvNHy;WG&Br3Q^*vel#*gCde=nT za4ANvg3v|j(-Of|7Lz=0OU*>AU(jO|wmCRAl#~=6$*S5xA|>HBW^=-<`nU#WDlCm8 z^;wRybXB4DEeZ<19Ty5uL+!UXb2NJEMc8Wxxs8@GN%Bj;L`RlKY#GdA2i*1WRmn=Ja?CUWMj_1Lx75qovr z>qniD6LgjTR3sOMTcz)dN}Eic`abCMKUak 1 { + if maxAge, _ := strconv.Atoi(match[1]); time.Duration(maxAge)*time.Second <= cacheTtl { + return true + } + } + return false +} diff --git a/version.txt b/version.txt index 45674f1..fd06a92 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -2.3.3 \ No newline at end of file +2.3.4 \ No newline at end of file diff --git a/views/settings.tpl.html b/views/settings.tpl.html index 3de5d7a..1f3c637 100644 --- a/views/settings.tpl.html +++ b/views/settings.tpl.html @@ -525,41 +525,53 @@
- + - The integration with Shields.IO allows to generate badges for README pages or forums. To enable this feature, you need to grant public, unauthorized access to the respective endpoints. See Permissions.

- Only available on public instances, not on localhost. + This integration with allows to generate badges for README pages or forums. To enable this feature, you need to grant public, unauthorized access to the respective endpoints. See Permissions. Adapt the URL's label and color parameters for customized badges.

+ In addition, there is an endpoint compatible with Shields.IO to allow for even more customization (e.g. different styles). Only available on public instances, not on localhost.
{{ if ne .User.ShareDataMaxDays 0 }}
-
+
Shields.io badge
-
+
Shields.io badge
+
+ +
+
+ Shields.io badge +
+
diff --git a/views/summary.tpl.html b/views/summary.tpl.html index af5ecbb..c219c84 100644 --- a/views/summary.tpl.html +++ b/views/summary.tpl.html @@ -16,194 +16,201 @@ {{ if .User.HasData }} -
-
+
+
+
+
+ + {{ end }} + +
+ + {{ if .User.HasData }} + + {{ if not .IsProjectDetails }} + +
+
+ Total Time + {{ .TotalTime | duration }} +
+
+ Total Heartbeats + {{ .NumHeartbeats }} +
+
+ Top Project + {{ .MaxByToString 0 }} +
+
+ Top Language + {{ .MaxByToString 1 }} +
+
+ Top OS + {{ .MaxByToString 3 }} +
+
+ Top Editor + {{ .MaxByToString 2 }} +
+
+ {{ else }} +
+

Project "{{ .GetProjectFilter }}"

+
+

{{ .TotalTime | duration }}

+
+ Coding Time Badge +
+
+
+ {{ end }} + +
+ + + + +
+
+ Languages +
+ +
+
+ + +
+ +
+
+ Editors +
+ +
+
+ + +
+ + + + + +
+ +
+
+ + {{ else }} + +
+
+ User welcome illustration +
+

Welcome to Wakapi!

+

+ It looks like there is no data available for the specified time range.
If you logged in to Wakapi for the first time, see the setup instructions below on how to get started. +

+
+

Setup Instructions

+
+ # Step 1: Download WakaTime plugin for your IDE
+ # See: https://wakatime.com/plugins

+ + # Step 2: Set your ~/.wakatime.cfg to this:

+ + [settings]
+ api_url = %s/api
+ api_key = {{ .ApiKey }}

+ + # Step 3: Start coding and then check back here! +
+
+
+ + {{ end }} + +
-{{ end }} - -
- - {{ if .User.HasData }} - - {{ if not .IsProjectDetails }} - -
-
- Total Time - {{ .TotalTime | duration }} -
-
- Total Heartbeats - {{ .NumHeartbeats }} -
-
- Top Project - {{ .MaxByToString 0 }} -
-
- Top Language - {{ .MaxByToString 1 }} -
-
- Top OS - {{ .MaxByToString 3 }} -
-
- Top Editor - {{ .MaxByToString 2 }} -
-
- {{ else }} -
-

Project "{{ .GetProjectFilter }}"

-

{{ .TotalTime | duration }}

-
- {{ end }} - -
- - - - -
-
- Languages -
- -
-
- - -
- -
-
- Editors -
- -
-
- - -
- - - - - -
- -
-
- - {{ else }} - -
-
- User welcome illustration -
-

Welcome to Wakapi!

-

- It looks like there is no data available for the specified time range.
If you logged in to Wakapi for the first time, see the setup instructions below on how to get started. -

-
-

Setup Instructions

-
- # Step 1: Download WakaTime plugin for your IDE
- # See: https://wakatime.com/plugins

- - # Step 2: Set your ~/.wakatime.cfg to this:

- - [settings]
- api_url = %s/api
- api_key = {{ .ApiKey }}

- - # Step 3: Start coding and then check back here! -
-
-
- - {{ end }} - -
- {{ template "footer.tpl.html" . }} {{ template "foot.tpl.html" . }} From e7740398319537394bb041b75d826b08ea4701f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ferdinand=20M=C3=BCtsch?= Date: Mon, 18 Apr 2022 11:49:06 +0200 Subject: [PATCH 05/14] chore: fall back to today badge on project page --- README.md | 2 +- static/assets/js/components/summary.js | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 4c53e26..aaa2074 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ - + diff --git a/static/assets/js/components/summary.js b/static/assets/js/components/summary.js index 25d873c..fff253d 100644 --- a/static/assets/js/components/summary.js +++ b/static/assets/js/components/summary.js @@ -2,8 +2,8 @@ PetiteVue.createApp({ $delimiters: ['${', '}'], get currentInterval() { const urlParams = new URLSearchParams(window.location.search) - return urlParams.has('interval') - ? urlParams.get('interval') - : null + if (urlParams.has('interval')) return urlParams.get('interval') + if (!urlParams.has('from') && !urlParams.has('to')) return 'today' + return null } }).mount('#summary-page') \ No newline at end of file From 5276f689185af1473825d9457d035aa2d70cc1e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ferdinand=20M=C3=BCtsch?= Date: Mon, 18 Apr 2022 15:18:01 +0200 Subject: [PATCH 06/14] fix: double counting when using precise missing intervals --- config.default.yml | 3 +- config/config.go | 21 +- coverage/coverage.out | 1730 +++++++++++++++++------------------ main.go | 6 +- routes/utils/badge_utils.go | 1 + services/summary.go | 12 +- services/summary_test.go | 2 +- 7 files changed, 881 insertions(+), 894 deletions(-) diff --git a/config.default.yml b/config.default.yml index 1509c45..261a1d5 100644 --- a/config.default.yml +++ b/config.default.yml @@ -72,4 +72,5 @@ mail: client_id: client_secret: -quick_start: false # whether to skip initial tasks on application startup, like summary generation \ No newline at end of file +quick_start: false # whether to skip initial tasks on application startup, like summary generation +skip_migrations: false # whether to intentionally not run database migrations, only use for dev purposes \ No newline at end of file diff --git a/config/config.go b/config/config.go index b80e71a..72b6b7d 100644 --- a/config/config.go +++ b/config/config.go @@ -142,16 +142,17 @@ type SMTPMailConfig struct { } type Config struct { - Env string `default:"dev" env:"ENVIRONMENT"` - Version string `yaml:"-"` - QuickStart bool `yaml:"quick_start" env:"WAKAPI_QUICK_START"` - InstanceId string `yaml:"-"` // only temporary, changes between runs - App appConfig - Security securityConfig - Db dbConfig - Server serverConfig - Sentry sentryConfig - Mail mailConfig + Env string `default:"dev" env:"ENVIRONMENT"` + Version string `yaml:"-"` + QuickStart bool `yaml:"quick_start" env:"WAKAPI_QUICK_START"` + SkipMigrations bool `yaml:"skip_migrations" env:"WAKAPI_SKIP_MIGRATIONS"` + InstanceId string `yaml:"-"` // only temporary, changes between runs + App appConfig + Security securityConfig + Db dbConfig + Server serverConfig + Sentry sentryConfig + Mail mailConfig } func (c *Config) CreateCookie(name, value string) *http.Cookie { diff --git a/coverage/coverage.out b/coverage/coverage.out index 6a79144..4e822b8 100644 --- a/coverage/coverage.out +++ b/coverage/coverage.out @@ -1,199 +1,4 @@ mode: set -github.com/muety/wakapi/models/alias.go:18.32,20.2 1 0 -github.com/muety/wakapi/models/alias.go:22.37,23.35 1 0 -github.com/muety/wakapi/models/alias.go:28.2,28.14 1 0 -github.com/muety/wakapi/models/alias.go:23.35,24.18 1 0 -github.com/muety/wakapi/models/alias.go:24.18,26.4 1 0 -github.com/muety/wakapi/models/filters.go:21.33,23.2 1 1 -github.com/muety/wakapi/models/filters.go:25.48,26.22 1 1 -github.com/muety/wakapi/models/filters.go:31.2,31.14 1 1 -github.com/muety/wakapi/models/filters.go:26.22,27.18 1 1 -github.com/muety/wakapi/models/filters.go:27.18,29.4 1 1 -github.com/muety/wakapi/models/filters.go:39.56,41.2 1 1 -github.com/muety/wakapi/models/filters.go:43.66,46.2 2 1 -github.com/muety/wakapi/models/filters.go:48.59,50.2 1 1 -github.com/muety/wakapi/models/filters.go:52.70,53.16 1 1 -github.com/muety/wakapi/models/filters.go:69.2,69.10 1 1 -github.com/muety/wakapi/models/filters.go:54.22,55.41 1 1 -github.com/muety/wakapi/models/filters.go:56.17,57.31 1 0 -github.com/muety/wakapi/models/filters.go:58.23,59.43 1 1 -github.com/muety/wakapi/models/filters.go:60.21,61.39 1 0 -github.com/muety/wakapi/models/filters.go:62.22,63.41 1 0 -github.com/muety/wakapi/models/filters.go:64.20,65.37 1 1 -github.com/muety/wakapi/models/filters.go:66.21,67.39 1 0 -github.com/muety/wakapi/models/filters.go:72.49,73.44 1 1 -github.com/muety/wakapi/models/filters.go:88.2,88.29 1 1 -github.com/muety/wakapi/models/filters.go:73.44,75.3 1 1 -github.com/muety/wakapi/models/filters.go:75.8,75.41 1 1 -github.com/muety/wakapi/models/filters.go:75.41,77.3 1 0 -github.com/muety/wakapi/models/filters.go:77.8,77.53 1 1 -github.com/muety/wakapi/models/filters.go:77.53,79.3 1 1 -github.com/muety/wakapi/models/filters.go:79.8,79.49 1 1 -github.com/muety/wakapi/models/filters.go:79.49,81.3 1 0 -github.com/muety/wakapi/models/filters.go:81.8,81.51 1 1 -github.com/muety/wakapi/models/filters.go:81.51,83.3 1 0 -github.com/muety/wakapi/models/filters.go:83.8,83.47 1 1 -github.com/muety/wakapi/models/filters.go:83.47,85.3 1 0 -github.com/muety/wakapi/models/filters.go:85.8,85.49 1 1 -github.com/muety/wakapi/models/filters.go:85.49,87.3 1 0 -github.com/muety/wakapi/models/filters.go:91.46,92.30 1 1 -github.com/muety/wakapi/models/filters.go:95.2,95.66 1 0 -github.com/muety/wakapi/models/filters.go:92.30,94.3 1 1 -github.com/muety/wakapi/models/filters.go:98.34,101.2 2 1 -github.com/muety/wakapi/models/filters.go:103.31,105.51 2 0 -github.com/muety/wakapi/models/filters.go:108.2,108.14 1 0 -github.com/muety/wakapi/models/filters.go:105.51,107.3 1 0 -github.com/muety/wakapi/models/filters.go:111.51,113.2 1 0 -github.com/muety/wakapi/models/filters.go:115.37,117.51 2 0 -github.com/muety/wakapi/models/filters.go:122.2,122.14 1 0 -github.com/muety/wakapi/models/filters.go:117.51,118.37 1 0 -github.com/muety/wakapi/models/filters.go:118.37,120.4 1 0 -github.com/muety/wakapi/models/filters.go:125.59,126.18 1 0 -github.com/muety/wakapi/models/filters.go:127.22,128.20 1 0 -github.com/muety/wakapi/models/filters.go:129.23,130.21 1 0 -github.com/muety/wakapi/models/filters.go:131.21,132.19 1 0 -github.com/muety/wakapi/models/filters.go:133.17,134.15 1 0 -github.com/muety/wakapi/models/filters.go:135.22,136.20 1 0 -github.com/muety/wakapi/models/filters.go:137.20,138.18 1 0 -github.com/muety/wakapi/models/filters.go:139.21,140.19 1 0 -github.com/muety/wakapi/models/filters.go:141.10,142.21 1 0 -github.com/muety/wakapi/models/filters.go:146.33,148.16 2 0 -github.com/muety/wakapi/models/filters.go:151.2,151.32 1 0 -github.com/muety/wakapi/models/filters.go:148.16,150.3 1 0 -github.com/muety/wakapi/models/filters.go:154.44,160.2 1 1 -github.com/muety/wakapi/models/filters.go:163.70,164.22 1 1 -github.com/muety/wakapi/models/filters.go:172.2,172.17 1 1 -github.com/muety/wakapi/models/filters.go:180.2,180.23 1 1 -github.com/muety/wakapi/models/filters.go:188.2,188.21 1 1 -github.com/muety/wakapi/models/filters.go:196.2,196.22 1 1 -github.com/muety/wakapi/models/filters.go:204.2,204.21 1 1 -github.com/muety/wakapi/models/filters.go:212.2,212.10 1 1 -github.com/muety/wakapi/models/filters.go:164.22,166.31 2 1 -github.com/muety/wakapi/models/filters.go:170.3,170.22 1 1 -github.com/muety/wakapi/models/filters.go:166.31,169.4 2 1 -github.com/muety/wakapi/models/filters.go:172.17,174.26 2 0 -github.com/muety/wakapi/models/filters.go:178.3,178.17 1 0 -github.com/muety/wakapi/models/filters.go:174.26,177.4 2 0 -github.com/muety/wakapi/models/filters.go:180.23,182.32 2 1 -github.com/muety/wakapi/models/filters.go:186.3,186.23 1 1 -github.com/muety/wakapi/models/filters.go:182.32,185.4 2 1 -github.com/muety/wakapi/models/filters.go:188.21,190.30 2 0 -github.com/muety/wakapi/models/filters.go:194.3,194.21 1 0 -github.com/muety/wakapi/models/filters.go:190.30,193.4 2 0 -github.com/muety/wakapi/models/filters.go:196.22,198.31 2 0 -github.com/muety/wakapi/models/filters.go:202.3,202.22 1 0 -github.com/muety/wakapi/models/filters.go:198.31,201.4 2 0 -github.com/muety/wakapi/models/filters.go:204.21,206.30 2 0 -github.com/muety/wakapi/models/filters.go:210.3,210.21 1 0 -github.com/muety/wakapi/models/filters.go:206.30,209.4 2 0 -github.com/muety/wakapi/models/filters.go:215.83,216.41 1 1 -github.com/muety/wakapi/models/filters.go:219.2,219.28 1 1 -github.com/muety/wakapi/models/filters.go:222.2,222.10 1 1 -github.com/muety/wakapi/models/filters.go:216.41,218.3 1 0 -github.com/muety/wakapi/models/filters.go:219.28,221.3 1 1 -github.com/muety/wakapi/models/interval.go:39.47,40.23 1 0 -github.com/muety/wakapi/models/interval.go:45.2,45.14 1 0 -github.com/muety/wakapi/models/interval.go:40.23,41.13 1 0 -github.com/muety/wakapi/models/interval.go:41.13,43.4 1 0 -github.com/muety/wakapi/models/mail_address.go:15.13,18.2 2 1 -github.com/muety/wakapi/models/mail_address.go:24.38,26.2 1 0 -github.com/muety/wakapi/models/mail_address.go:28.35,30.21 2 1 -github.com/muety/wakapi/models/mail_address.go:36.2,36.11 1 1 -github.com/muety/wakapi/models/mail_address.go:30.21,31.21 1 1 -github.com/muety/wakapi/models/mail_address.go:34.3,34.18 1 1 -github.com/muety/wakapi/models/mail_address.go:31.21,33.4 1 1 -github.com/muety/wakapi/models/mail_address.go:39.35,41.2 1 1 -github.com/muety/wakapi/models/mail_address.go:43.43,45.22 2 0 -github.com/muety/wakapi/models/mail_address.go:48.2,48.12 1 0 -github.com/muety/wakapi/models/mail_address.go:45.22,47.3 1 0 -github.com/muety/wakapi/models/mail_address.go:51.46,53.22 2 1 -github.com/muety/wakapi/models/mail_address.go:56.2,56.12 1 1 -github.com/muety/wakapi/models/mail_address.go:53.22,55.3 1 1 -github.com/muety/wakapi/models/mail_address.go:59.40,60.22 1 1 -github.com/muety/wakapi/models/mail_address.go:65.2,65.13 1 1 -github.com/muety/wakapi/models/mail_address.go:60.22,61.17 1 1 -github.com/muety/wakapi/models/mail_address.go:61.17,63.4 1 1 -github.com/muety/wakapi/models/shared.go:35.52,37.2 1 0 -github.com/muety/wakapi/models/shared.go:39.52,42.16 3 0 -github.com/muety/wakapi/models/shared.go:45.2,47.12 3 0 -github.com/muety/wakapi/models/shared.go:42.16,44.3 1 0 -github.com/muety/wakapi/models/shared.go:50.52,56.22 2 0 -github.com/muety/wakapi/models/shared.go:71.2,74.12 3 0 -github.com/muety/wakapi/models/shared.go:57.14,61.17 2 0 -github.com/muety/wakapi/models/shared.go:64.17,66.8 2 0 -github.com/muety/wakapi/models/shared.go:67.10,68.64 1 0 -github.com/muety/wakapi/models/shared.go:61.17,63.4 1 0 -github.com/muety/wakapi/models/shared.go:77.51,80.2 2 0 -github.com/muety/wakapi/models/shared.go:82.45,84.2 1 0 -github.com/muety/wakapi/models/shared.go:86.37,88.2 1 0 -github.com/muety/wakapi/models/shared.go:90.35,92.2 1 0 -github.com/muety/wakapi/models/shared.go:94.34,96.2 1 0 -github.com/muety/wakapi/models/heartbeat.go:33.34,35.2 1 1 -github.com/muety/wakapi/models/heartbeat.go:37.55,40.2 2 0 -github.com/muety/wakapi/models/heartbeat.go:42.65,44.46 2 1 -github.com/muety/wakapi/models/heartbeat.go:44.46,45.108 1 1 -github.com/muety/wakapi/models/heartbeat.go:45.108,48.4 2 1 -github.com/muety/wakapi/models/heartbeat.go:52.50,53.11 1 1 -github.com/muety/wakapi/models/heartbeat.go:68.2,68.15 1 1 -github.com/muety/wakapi/models/heartbeat.go:72.2,72.12 1 1 -github.com/muety/wakapi/models/heartbeat.go:54.22,55.18 1 1 -github.com/muety/wakapi/models/heartbeat.go:56.21,57.17 1 1 -github.com/muety/wakapi/models/heartbeat.go:58.23,59.19 1 1 -github.com/muety/wakapi/models/heartbeat.go:60.17,61.26 1 1 -github.com/muety/wakapi/models/heartbeat.go:62.22,63.18 1 1 -github.com/muety/wakapi/models/heartbeat.go:64.21,65.17 1 0 -github.com/muety/wakapi/models/heartbeat.go:68.15,70.3 1 1 -github.com/muety/wakapi/models/heartbeat.go:75.37,91.2 1 0 -github.com/muety/wakapi/models/heartbeat.go:99.41,101.16 2 0 -github.com/muety/wakapi/models/heartbeat.go:104.2,105.10 2 0 -github.com/muety/wakapi/models/heartbeat.go:101.16,103.3 1 0 -github.com/muety/wakapi/models/heartbeat.go:108.38,118.2 1 0 -github.com/muety/wakapi/models/language_mapping.go:11.42,13.2 1 0 -github.com/muety/wakapi/models/language_mapping.go:15.51,17.2 1 0 -github.com/muety/wakapi/models/language_mapping.go:19.52,21.2 1 0 -github.com/muety/wakapi/models/models.go:3.14,5.2 0 1 -github.com/muety/wakapi/models/project_label.go:14.39,16.2 1 0 -github.com/muety/wakapi/models/duration.go:24.55,38.2 2 0 -github.com/muety/wakapi/models/duration.go:40.39,42.16 2 0 -github.com/muety/wakapi/models/duration.go:45.2,46.10 2 0 -github.com/muety/wakapi/models/duration.go:42.16,44.3 1 0 -github.com/muety/wakapi/models/duration.go:49.49,50.11 1 0 -github.com/muety/wakapi/models/duration.go:65.2,65.15 1 0 -github.com/muety/wakapi/models/duration.go:69.2,69.12 1 0 -github.com/muety/wakapi/models/duration.go:51.22,52.18 1 0 -github.com/muety/wakapi/models/duration.go:53.21,54.17 1 0 -github.com/muety/wakapi/models/duration.go:55.23,56.19 1 0 -github.com/muety/wakapi/models/duration.go:57.17,58.26 1 0 -github.com/muety/wakapi/models/duration.go:59.22,60.18 1 0 -github.com/muety/wakapi/models/duration.go:61.21,62.17 1 0 -github.com/muety/wakapi/models/duration.go:65.15,67.3 1 0 -github.com/muety/wakapi/models/durations.go:7.30,9.2 1 0 -github.com/muety/wakapi/models/durations.go:11.40,13.2 1 0 -github.com/muety/wakapi/models/durations.go:15.35,17.2 1 0 -github.com/muety/wakapi/models/durations.go:19.45,21.22 2 0 -github.com/muety/wakapi/models/durations.go:24.2,24.14 1 0 -github.com/muety/wakapi/models/durations.go:21.22,23.3 1 0 -github.com/muety/wakapi/models/durations.go:27.39,30.2 2 0 -github.com/muety/wakapi/models/durations.go:32.39,34.18 1 0 -github.com/muety/wakapi/models/durations.go:37.2,37.16 1 0 -github.com/muety/wakapi/models/durations.go:34.18,36.3 1 0 -github.com/muety/wakapi/models/durations.go:40.38,42.18 1 0 -github.com/muety/wakapi/models/durations.go:45.2,45.24 1 0 -github.com/muety/wakapi/models/durations.go:42.18,44.3 1 0 -github.com/muety/wakapi/models/heartbeats.go:7.31,9.2 1 0 -github.com/muety/wakapi/models/heartbeats.go:11.41,13.2 1 0 -github.com/muety/wakapi/models/heartbeats.go:15.36,17.2 1 0 -github.com/muety/wakapi/models/heartbeats.go:19.43,22.2 2 0 -github.com/muety/wakapi/models/heartbeats.go:24.41,26.18 1 0 -github.com/muety/wakapi/models/heartbeats.go:29.2,29.16 1 0 -github.com/muety/wakapi/models/heartbeats.go:26.18,28.3 1 0 -github.com/muety/wakapi/models/heartbeats.go:32.40,34.18 1 0 -github.com/muety/wakapi/models/heartbeats.go:37.2,37.24 1 0 -github.com/muety/wakapi/models/heartbeats.go:34.18,36.3 1 0 -github.com/muety/wakapi/models/mail.go:19.44,23.2 3 0 -github.com/muety/wakapi/models/mail.go:25.44,29.2 3 0 -github.com/muety/wakapi/models/mail.go:31.32,44.2 1 0 -github.com/muety/wakapi/models/mail.go:46.41,48.2 1 0 github.com/muety/wakapi/models/summary.go:64.29,66.2 1 1 github.com/muety/wakapi/models/summary.go:68.35,70.2 1 0 github.com/muety/wakapi/models/summary.go:72.38,74.2 1 0 @@ -292,6 +97,201 @@ github.com/muety/wakapi/models/summary.go:359.50,363.2 1 1 github.com/muety/wakapi/models/summary.go:365.33,367.2 1 1 github.com/muety/wakapi/models/summary.go:369.43,371.2 1 1 github.com/muety/wakapi/models/summary.go:373.38,375.2 1 1 +github.com/muety/wakapi/models/duration.go:24.55,38.2 2 0 +github.com/muety/wakapi/models/duration.go:40.39,42.16 2 0 +github.com/muety/wakapi/models/duration.go:45.2,46.10 2 0 +github.com/muety/wakapi/models/duration.go:42.16,44.3 1 0 +github.com/muety/wakapi/models/duration.go:49.49,50.11 1 0 +github.com/muety/wakapi/models/duration.go:65.2,65.15 1 0 +github.com/muety/wakapi/models/duration.go:69.2,69.12 1 0 +github.com/muety/wakapi/models/duration.go:51.22,52.18 1 0 +github.com/muety/wakapi/models/duration.go:53.21,54.17 1 0 +github.com/muety/wakapi/models/duration.go:55.23,56.19 1 0 +github.com/muety/wakapi/models/duration.go:57.17,58.26 1 0 +github.com/muety/wakapi/models/duration.go:59.22,60.18 1 0 +github.com/muety/wakapi/models/duration.go:61.21,62.17 1 0 +github.com/muety/wakapi/models/duration.go:65.15,67.3 1 0 +github.com/muety/wakapi/models/heartbeats.go:7.31,9.2 1 0 +github.com/muety/wakapi/models/heartbeats.go:11.41,13.2 1 0 +github.com/muety/wakapi/models/heartbeats.go:15.36,17.2 1 0 +github.com/muety/wakapi/models/heartbeats.go:19.43,22.2 2 0 +github.com/muety/wakapi/models/heartbeats.go:24.41,26.18 1 0 +github.com/muety/wakapi/models/heartbeats.go:29.2,29.16 1 0 +github.com/muety/wakapi/models/heartbeats.go:26.18,28.3 1 0 +github.com/muety/wakapi/models/heartbeats.go:32.40,34.18 1 0 +github.com/muety/wakapi/models/heartbeats.go:37.2,37.24 1 0 +github.com/muety/wakapi/models/heartbeats.go:34.18,36.3 1 0 +github.com/muety/wakapi/models/language_mapping.go:11.42,13.2 1 0 +github.com/muety/wakapi/models/language_mapping.go:15.51,17.2 1 0 +github.com/muety/wakapi/models/language_mapping.go:19.52,21.2 1 0 +github.com/muety/wakapi/models/mail.go:19.44,23.2 3 0 +github.com/muety/wakapi/models/mail.go:25.44,29.2 3 0 +github.com/muety/wakapi/models/mail.go:31.32,44.2 1 0 +github.com/muety/wakapi/models/mail.go:46.41,48.2 1 0 +github.com/muety/wakapi/models/models.go:3.14,5.2 0 1 +github.com/muety/wakapi/models/project_label.go:14.39,16.2 1 0 +github.com/muety/wakapi/models/alias.go:18.32,20.2 1 0 +github.com/muety/wakapi/models/alias.go:22.37,23.35 1 0 +github.com/muety/wakapi/models/alias.go:28.2,28.14 1 0 +github.com/muety/wakapi/models/alias.go:23.35,24.18 1 0 +github.com/muety/wakapi/models/alias.go:24.18,26.4 1 0 +github.com/muety/wakapi/models/durations.go:7.30,9.2 1 0 +github.com/muety/wakapi/models/durations.go:11.40,13.2 1 0 +github.com/muety/wakapi/models/durations.go:15.35,17.2 1 0 +github.com/muety/wakapi/models/durations.go:19.45,21.22 2 0 +github.com/muety/wakapi/models/durations.go:24.2,24.14 1 0 +github.com/muety/wakapi/models/durations.go:21.22,23.3 1 0 +github.com/muety/wakapi/models/durations.go:27.39,30.2 2 0 +github.com/muety/wakapi/models/durations.go:32.39,34.18 1 0 +github.com/muety/wakapi/models/durations.go:37.2,37.16 1 0 +github.com/muety/wakapi/models/durations.go:34.18,36.3 1 0 +github.com/muety/wakapi/models/durations.go:40.38,42.18 1 0 +github.com/muety/wakapi/models/durations.go:45.2,45.24 1 0 +github.com/muety/wakapi/models/durations.go:42.18,44.3 1 0 +github.com/muety/wakapi/models/filters.go:21.33,23.2 1 1 +github.com/muety/wakapi/models/filters.go:25.48,26.22 1 1 +github.com/muety/wakapi/models/filters.go:31.2,31.14 1 1 +github.com/muety/wakapi/models/filters.go:26.22,27.18 1 1 +github.com/muety/wakapi/models/filters.go:27.18,29.4 1 1 +github.com/muety/wakapi/models/filters.go:39.56,41.2 1 1 +github.com/muety/wakapi/models/filters.go:43.66,46.2 2 1 +github.com/muety/wakapi/models/filters.go:48.59,50.2 1 1 +github.com/muety/wakapi/models/filters.go:52.70,53.16 1 1 +github.com/muety/wakapi/models/filters.go:69.2,69.10 1 1 +github.com/muety/wakapi/models/filters.go:54.22,55.41 1 1 +github.com/muety/wakapi/models/filters.go:56.17,57.31 1 0 +github.com/muety/wakapi/models/filters.go:58.23,59.43 1 1 +github.com/muety/wakapi/models/filters.go:60.21,61.39 1 0 +github.com/muety/wakapi/models/filters.go:62.22,63.41 1 0 +github.com/muety/wakapi/models/filters.go:64.20,65.37 1 1 +github.com/muety/wakapi/models/filters.go:66.21,67.39 1 0 +github.com/muety/wakapi/models/filters.go:72.49,73.44 1 1 +github.com/muety/wakapi/models/filters.go:88.2,88.29 1 1 +github.com/muety/wakapi/models/filters.go:73.44,75.3 1 1 +github.com/muety/wakapi/models/filters.go:75.8,75.41 1 1 +github.com/muety/wakapi/models/filters.go:75.41,77.3 1 0 +github.com/muety/wakapi/models/filters.go:77.8,77.53 1 1 +github.com/muety/wakapi/models/filters.go:77.53,79.3 1 1 +github.com/muety/wakapi/models/filters.go:79.8,79.49 1 1 +github.com/muety/wakapi/models/filters.go:79.49,81.3 1 0 +github.com/muety/wakapi/models/filters.go:81.8,81.51 1 1 +github.com/muety/wakapi/models/filters.go:81.51,83.3 1 0 +github.com/muety/wakapi/models/filters.go:83.8,83.47 1 1 +github.com/muety/wakapi/models/filters.go:83.47,85.3 1 0 +github.com/muety/wakapi/models/filters.go:85.8,85.49 1 1 +github.com/muety/wakapi/models/filters.go:85.49,87.3 1 0 +github.com/muety/wakapi/models/filters.go:91.46,92.30 1 1 +github.com/muety/wakapi/models/filters.go:95.2,95.66 1 0 +github.com/muety/wakapi/models/filters.go:92.30,94.3 1 1 +github.com/muety/wakapi/models/filters.go:98.34,101.2 2 1 +github.com/muety/wakapi/models/filters.go:103.31,105.51 2 0 +github.com/muety/wakapi/models/filters.go:108.2,108.14 1 0 +github.com/muety/wakapi/models/filters.go:105.51,107.3 1 0 +github.com/muety/wakapi/models/filters.go:111.51,113.2 1 0 +github.com/muety/wakapi/models/filters.go:115.37,117.51 2 0 +github.com/muety/wakapi/models/filters.go:122.2,122.14 1 0 +github.com/muety/wakapi/models/filters.go:117.51,118.37 1 0 +github.com/muety/wakapi/models/filters.go:118.37,120.4 1 0 +github.com/muety/wakapi/models/filters.go:125.59,126.18 1 0 +github.com/muety/wakapi/models/filters.go:127.22,128.20 1 0 +github.com/muety/wakapi/models/filters.go:129.23,130.21 1 0 +github.com/muety/wakapi/models/filters.go:131.21,132.19 1 0 +github.com/muety/wakapi/models/filters.go:133.17,134.15 1 0 +github.com/muety/wakapi/models/filters.go:135.22,136.20 1 0 +github.com/muety/wakapi/models/filters.go:137.20,138.18 1 0 +github.com/muety/wakapi/models/filters.go:139.21,140.19 1 0 +github.com/muety/wakapi/models/filters.go:141.10,142.21 1 0 +github.com/muety/wakapi/models/filters.go:146.33,148.16 2 0 +github.com/muety/wakapi/models/filters.go:151.2,151.32 1 0 +github.com/muety/wakapi/models/filters.go:148.16,150.3 1 0 +github.com/muety/wakapi/models/filters.go:154.44,160.2 1 1 +github.com/muety/wakapi/models/filters.go:163.70,164.22 1 1 +github.com/muety/wakapi/models/filters.go:172.2,172.17 1 1 +github.com/muety/wakapi/models/filters.go:180.2,180.23 1 1 +github.com/muety/wakapi/models/filters.go:188.2,188.21 1 1 +github.com/muety/wakapi/models/filters.go:196.2,196.22 1 1 +github.com/muety/wakapi/models/filters.go:204.2,204.21 1 1 +github.com/muety/wakapi/models/filters.go:212.2,212.10 1 1 +github.com/muety/wakapi/models/filters.go:164.22,166.31 2 1 +github.com/muety/wakapi/models/filters.go:170.3,170.22 1 1 +github.com/muety/wakapi/models/filters.go:166.31,169.4 2 1 +github.com/muety/wakapi/models/filters.go:172.17,174.26 2 0 +github.com/muety/wakapi/models/filters.go:178.3,178.17 1 0 +github.com/muety/wakapi/models/filters.go:174.26,177.4 2 0 +github.com/muety/wakapi/models/filters.go:180.23,182.32 2 1 +github.com/muety/wakapi/models/filters.go:186.3,186.23 1 1 +github.com/muety/wakapi/models/filters.go:182.32,185.4 2 1 +github.com/muety/wakapi/models/filters.go:188.21,190.30 2 0 +github.com/muety/wakapi/models/filters.go:194.3,194.21 1 0 +github.com/muety/wakapi/models/filters.go:190.30,193.4 2 0 +github.com/muety/wakapi/models/filters.go:196.22,198.31 2 0 +github.com/muety/wakapi/models/filters.go:202.3,202.22 1 0 +github.com/muety/wakapi/models/filters.go:198.31,201.4 2 0 +github.com/muety/wakapi/models/filters.go:204.21,206.30 2 0 +github.com/muety/wakapi/models/filters.go:210.3,210.21 1 0 +github.com/muety/wakapi/models/filters.go:206.30,209.4 2 0 +github.com/muety/wakapi/models/filters.go:215.83,216.41 1 1 +github.com/muety/wakapi/models/filters.go:219.2,219.28 1 1 +github.com/muety/wakapi/models/filters.go:222.2,222.10 1 1 +github.com/muety/wakapi/models/filters.go:216.41,218.3 1 0 +github.com/muety/wakapi/models/filters.go:219.28,221.3 1 1 +github.com/muety/wakapi/models/mail_address.go:15.13,18.2 2 1 +github.com/muety/wakapi/models/mail_address.go:24.38,26.2 1 0 +github.com/muety/wakapi/models/mail_address.go:28.35,30.21 2 1 +github.com/muety/wakapi/models/mail_address.go:36.2,36.11 1 1 +github.com/muety/wakapi/models/mail_address.go:30.21,31.21 1 1 +github.com/muety/wakapi/models/mail_address.go:34.3,34.18 1 1 +github.com/muety/wakapi/models/mail_address.go:31.21,33.4 1 1 +github.com/muety/wakapi/models/mail_address.go:39.35,41.2 1 1 +github.com/muety/wakapi/models/mail_address.go:43.43,45.22 2 0 +github.com/muety/wakapi/models/mail_address.go:48.2,48.12 1 0 +github.com/muety/wakapi/models/mail_address.go:45.22,47.3 1 0 +github.com/muety/wakapi/models/mail_address.go:51.46,53.22 2 1 +github.com/muety/wakapi/models/mail_address.go:56.2,56.12 1 1 +github.com/muety/wakapi/models/mail_address.go:53.22,55.3 1 1 +github.com/muety/wakapi/models/mail_address.go:59.40,60.22 1 1 +github.com/muety/wakapi/models/mail_address.go:65.2,65.13 1 1 +github.com/muety/wakapi/models/mail_address.go:60.22,61.17 1 1 +github.com/muety/wakapi/models/mail_address.go:61.17,63.4 1 1 +github.com/muety/wakapi/models/shared.go:40.52,42.2 1 0 +github.com/muety/wakapi/models/shared.go:44.52,47.16 3 0 +github.com/muety/wakapi/models/shared.go:50.2,52.12 3 0 +github.com/muety/wakapi/models/shared.go:47.16,49.3 1 0 +github.com/muety/wakapi/models/shared.go:55.52,61.22 2 0 +github.com/muety/wakapi/models/shared.go:76.2,79.12 3 0 +github.com/muety/wakapi/models/shared.go:62.14,66.17 2 0 +github.com/muety/wakapi/models/shared.go:69.17,71.8 2 0 +github.com/muety/wakapi/models/shared.go:72.10,73.64 1 0 +github.com/muety/wakapi/models/shared.go:66.17,68.4 1 0 +github.com/muety/wakapi/models/shared.go:82.51,85.2 2 0 +github.com/muety/wakapi/models/shared.go:87.45,89.2 1 0 +github.com/muety/wakapi/models/shared.go:91.37,93.2 1 0 +github.com/muety/wakapi/models/shared.go:95.35,97.2 1 0 +github.com/muety/wakapi/models/shared.go:99.34,101.2 1 0 +github.com/muety/wakapi/models/heartbeat.go:33.34,35.2 1 1 +github.com/muety/wakapi/models/heartbeat.go:37.55,40.2 2 0 +github.com/muety/wakapi/models/heartbeat.go:42.65,44.46 2 1 +github.com/muety/wakapi/models/heartbeat.go:44.46,45.108 1 1 +github.com/muety/wakapi/models/heartbeat.go:45.108,48.4 2 1 +github.com/muety/wakapi/models/heartbeat.go:52.50,53.11 1 1 +github.com/muety/wakapi/models/heartbeat.go:68.2,68.15 1 1 +github.com/muety/wakapi/models/heartbeat.go:72.2,72.12 1 1 +github.com/muety/wakapi/models/heartbeat.go:54.22,55.18 1 1 +github.com/muety/wakapi/models/heartbeat.go:56.21,57.17 1 1 +github.com/muety/wakapi/models/heartbeat.go:58.23,59.19 1 1 +github.com/muety/wakapi/models/heartbeat.go:60.17,61.26 1 1 +github.com/muety/wakapi/models/heartbeat.go:62.22,63.18 1 1 +github.com/muety/wakapi/models/heartbeat.go:64.21,65.17 1 0 +github.com/muety/wakapi/models/heartbeat.go:68.15,70.3 1 1 +github.com/muety/wakapi/models/heartbeat.go:75.37,91.2 1 0 +github.com/muety/wakapi/models/heartbeat.go:99.41,101.16 2 0 +github.com/muety/wakapi/models/heartbeat.go:104.2,105.10 2 0 +github.com/muety/wakapi/models/heartbeat.go:101.16,103.3 1 0 +github.com/muety/wakapi/models/heartbeat.go:108.38,118.2 1 0 +github.com/muety/wakapi/models/interval.go:39.47,40.23 1 0 +github.com/muety/wakapi/models/interval.go:45.2,45.14 1 0 +github.com/muety/wakapi/models/interval.go:40.23,41.13 1 0 +github.com/muety/wakapi/models/interval.go:41.13,43.4 1 0 github.com/muety/wakapi/models/user.go:11.13,13.2 1 1 github.com/muety/wakapi/models/user.go:83.36,84.22 1 1 github.com/muety/wakapi/models/user.go:87.2,88.16 2 1 @@ -315,6 +315,119 @@ github.com/muety/wakapi/models/user.go:142.45,144.2 1 0 github.com/muety/wakapi/models/user.go:146.45,148.2 1 0 github.com/muety/wakapi/models/user.go:150.39,152.2 1 0 github.com/muety/wakapi/models/user.go:154.39,157.2 2 0 +github.com/muety/wakapi/config/utils.go:5.78,7.22 2 0 +github.com/muety/wakapi/config/utils.go:13.2,13.11 1 0 +github.com/muety/wakapi/config/utils.go:7.22,8.18 1 0 +github.com/muety/wakapi/config/utils.go:11.3,11.12 1 0 +github.com/muety/wakapi/config/utils.go:8.18,10.4 1 0 +github.com/muety/wakapi/config/config.go:158.64,160.2 1 0 +github.com/muety/wakapi/config/config.go:162.59,164.2 1 0 +github.com/muety/wakapi/config/config.go:166.82,176.2 1 0 +github.com/muety/wakapi/config/config.go:178.31,180.2 1 0 +github.com/muety/wakapi/config/config.go:182.32,184.2 1 0 +github.com/muety/wakapi/config/config.go:186.74,187.19 1 0 +github.com/muety/wakapi/config/config.go:188.10,189.34 1 0 +github.com/muety/wakapi/config/config.go:189.34,190.90 1 0 +github.com/muety/wakapi/config/config.go:193.4,193.100 1 0 +github.com/muety/wakapi/config/config.go:196.4,196.91 1 0 +github.com/muety/wakapi/config/config.go:199.4,199.95 1 0 +github.com/muety/wakapi/config/config.go:202.4,202.93 1 0 +github.com/muety/wakapi/config/config.go:205.4,205.97 1 0 +github.com/muety/wakapi/config/config.go:208.4,208.101 1 0 +github.com/muety/wakapi/config/config.go:211.4,211.98 1 0 +github.com/muety/wakapi/config/config.go:214.4,214.97 1 0 +github.com/muety/wakapi/config/config.go:217.4,217.14 1 0 +github.com/muety/wakapi/config/config.go:190.90,192.5 1 0 +github.com/muety/wakapi/config/config.go:193.100,195.5 1 0 +github.com/muety/wakapi/config/config.go:196.91,198.5 1 0 +github.com/muety/wakapi/config/config.go:199.95,201.5 1 0 +github.com/muety/wakapi/config/config.go:202.93,204.5 1 0 +github.com/muety/wakapi/config/config.go:205.97,207.5 1 0 +github.com/muety/wakapi/config/config.go:208.101,210.5 1 0 +github.com/muety/wakapi/config/config.go:211.98,213.5 1 0 +github.com/muety/wakapi/config/config.go:214.97,216.5 1 0 +github.com/muety/wakapi/config/config.go:222.60,224.2 1 0 +github.com/muety/wakapi/config/config.go:226.59,228.2 1 0 +github.com/muety/wakapi/config/config.go:230.57,232.2 1 0 +github.com/muety/wakapi/config/config.go:234.53,236.2 1 0 +github.com/muety/wakapi/config/config.go:238.55,241.2 2 0 +github.com/muety/wakapi/config/config.go:243.50,245.2 1 0 +github.com/muety/wakapi/config/config.go:247.54,250.2 2 0 +github.com/muety/wakapi/config/config.go:252.36,254.2 1 0 +github.com/muety/wakapi/config/config.go:256.35,258.2 1 0 +github.com/muety/wakapi/config/config.go:260.38,262.2 1 0 +github.com/muety/wakapi/config/config.go:264.46,266.2 1 0 +github.com/muety/wakapi/config/config.go:268.43,270.2 1 0 +github.com/muety/wakapi/config/config.go:272.29,274.2 1 1 +github.com/muety/wakapi/config/config.go:276.48,287.16 2 0 +github.com/muety/wakapi/config/config.go:291.2,292.53 2 0 +github.com/muety/wakapi/config/config.go:296.2,296.15 1 0 +github.com/muety/wakapi/config/config.go:287.16,289.3 1 0 +github.com/muety/wakapi/config/config.go:292.53,294.3 1 0 +github.com/muety/wakapi/config/config.go:299.38,300.43 1 0 +github.com/muety/wakapi/config/config.go:303.2,303.15 1 0 +github.com/muety/wakapi/config/config.go:300.43,302.3 1 0 +github.com/muety/wakapi/config/config.go:306.45,307.27 1 0 +github.com/muety/wakapi/config/config.go:310.2,310.24 1 0 +github.com/muety/wakapi/config/config.go:313.2,313.25 1 0 +github.com/muety/wakapi/config/config.go:316.2,316.15 1 0 +github.com/muety/wakapi/config/config.go:307.27,309.3 1 0 +github.com/muety/wakapi/config/config.go:310.24,312.3 1 0 +github.com/muety/wakapi/config/config.go:313.25,315.3 1 0 +github.com/muety/wakapi/config/config.go:319.77,320.29 1 0 +github.com/muety/wakapi/config/config.go:325.2,325.19 1 0 +github.com/muety/wakapi/config/config.go:320.29,321.18 1 0 +github.com/muety/wakapi/config/config.go:321.18,323.4 1 0 +github.com/muety/wakapi/config/config.go:328.42,329.28 1 0 +github.com/muety/wakapi/config/config.go:345.2,345.20 1 0 +github.com/muety/wakapi/config/config.go:330.52,331.21 1 0 +github.com/muety/wakapi/config/config.go:332.53,333.22 1 0 +github.com/muety/wakapi/config/config.go:334.55,335.24 1 0 +github.com/muety/wakapi/config/config.go:336.54,337.23 1 0 +github.com/muety/wakapi/config/config.go:338.52,339.21 1 0 +github.com/muety/wakapi/config/config.go:340.54,341.23 1 0 +github.com/muety/wakapi/config/config.go:342.52,343.21 1 0 +github.com/muety/wakapi/config/config.go:348.26,350.2 1 0 +github.com/muety/wakapi/config/config.go:352.20,354.2 1 0 +github.com/muety/wakapi/config/config.go:356.35,361.96 3 0 +github.com/muety/wakapi/config/config.go:365.2,375.52 7 0 +github.com/muety/wakapi/config/config.go:379.2,379.47 1 0 +github.com/muety/wakapi/config/config.go:385.2,385.29 1 0 +github.com/muety/wakapi/config/config.go:391.2,391.106 1 0 +github.com/muety/wakapi/config/config.go:394.2,394.28 1 0 +github.com/muety/wakapi/config/config.go:397.2,397.51 1 0 +github.com/muety/wakapi/config/config.go:401.2,401.94 1 0 +github.com/muety/wakapi/config/config.go:404.2,404.81 1 0 +github.com/muety/wakapi/config/config.go:407.2,407.75 1 0 +github.com/muety/wakapi/config/config.go:410.2,410.74 1 0 +github.com/muety/wakapi/config/config.go:414.2,415.14 2 0 +github.com/muety/wakapi/config/config.go:361.96,363.3 1 0 +github.com/muety/wakapi/config/config.go:375.52,377.3 1 0 +github.com/muety/wakapi/config/config.go:379.47,380.14 1 0 +github.com/muety/wakapi/config/config.go:380.14,382.4 1 0 +github.com/muety/wakapi/config/config.go:385.29,388.3 2 0 +github.com/muety/wakapi/config/config.go:391.106,393.3 1 0 +github.com/muety/wakapi/config/config.go:394.28,396.3 1 0 +github.com/muety/wakapi/config/config.go:397.51,400.3 2 0 +github.com/muety/wakapi/config/config.go:401.94,403.3 1 0 +github.com/muety/wakapi/config/config.go:404.81,406.3 1 0 +github.com/muety/wakapi/config/config.go:407.75,409.3 1 0 +github.com/muety/wakapi/config/config.go:410.74,412.3 1 0 +github.com/muety/wakapi/config/db.go:39.50,40.19 1 0 +github.com/muety/wakapi/config/db.go:53.2,53.12 1 0 +github.com/muety/wakapi/config/db.go:41.23,45.5 1 0 +github.com/muety/wakapi/config/db.go:46.26,49.5 1 0 +github.com/muety/wakapi/config/db.go:50.24,51.48 1 0 +github.com/muety/wakapi/config/db.go:56.53,66.2 1 1 +github.com/muety/wakapi/config/db.go:68.56,70.16 2 1 +github.com/muety/wakapi/config/db.go:74.2,81.3 1 1 +github.com/muety/wakapi/config/db.go:70.16,72.3 1 0 +github.com/muety/wakapi/config/db.go:84.54,86.2 1 1 +github.com/muety/wakapi/config/eventbus.go:26.13,28.2 1 1 +github.com/muety/wakapi/config/eventbus.go:30.26,32.2 1 0 +github.com/muety/wakapi/config/fs.go:9.56,10.19 1 0 +github.com/muety/wakapi/config/fs.go:13.2,13.19 1 0 +github.com/muety/wakapi/config/fs.go:10.19,12.3 1 0 github.com/muety/wakapi/config/sentry.go:22.35,24.2 1 0 github.com/muety/wakapi/config/sentry.go:26.62,29.2 2 0 github.com/muety/wakapi/config/sentry.go:39.33,46.2 2 0 @@ -348,152 +461,146 @@ github.com/muety/wakapi/config/sentry.go:142.17,144.3 1 0 github.com/muety/wakapi/config/sentry.go:147.49,151.51 2 0 github.com/muety/wakapi/config/sentry.go:154.2,154.12 1 0 github.com/muety/wakapi/config/sentry.go:151.51,153.3 1 0 -github.com/muety/wakapi/config/utils.go:5.78,7.22 2 0 -github.com/muety/wakapi/config/utils.go:13.2,13.11 1 0 -github.com/muety/wakapi/config/utils.go:7.22,8.18 1 0 -github.com/muety/wakapi/config/utils.go:11.3,11.12 1 0 -github.com/muety/wakapi/config/utils.go:8.18,10.4 1 0 -github.com/muety/wakapi/config/config.go:157.64,159.2 1 0 -github.com/muety/wakapi/config/config.go:161.59,163.2 1 0 -github.com/muety/wakapi/config/config.go:165.82,175.2 1 0 -github.com/muety/wakapi/config/config.go:177.31,179.2 1 0 -github.com/muety/wakapi/config/config.go:181.32,183.2 1 0 -github.com/muety/wakapi/config/config.go:185.74,186.19 1 0 -github.com/muety/wakapi/config/config.go:187.10,188.34 1 0 -github.com/muety/wakapi/config/config.go:188.34,189.90 1 0 -github.com/muety/wakapi/config/config.go:192.4,192.100 1 0 -github.com/muety/wakapi/config/config.go:195.4,195.91 1 0 -github.com/muety/wakapi/config/config.go:198.4,198.95 1 0 -github.com/muety/wakapi/config/config.go:201.4,201.93 1 0 -github.com/muety/wakapi/config/config.go:204.4,204.97 1 0 -github.com/muety/wakapi/config/config.go:207.4,207.101 1 0 -github.com/muety/wakapi/config/config.go:210.4,210.98 1 0 -github.com/muety/wakapi/config/config.go:213.4,213.97 1 0 -github.com/muety/wakapi/config/config.go:216.4,216.14 1 0 -github.com/muety/wakapi/config/config.go:189.90,191.5 1 0 -github.com/muety/wakapi/config/config.go:192.100,194.5 1 0 -github.com/muety/wakapi/config/config.go:195.91,197.5 1 0 -github.com/muety/wakapi/config/config.go:198.95,200.5 1 0 -github.com/muety/wakapi/config/config.go:201.93,203.5 1 0 -github.com/muety/wakapi/config/config.go:204.97,206.5 1 0 -github.com/muety/wakapi/config/config.go:207.101,209.5 1 0 -github.com/muety/wakapi/config/config.go:210.98,212.5 1 0 -github.com/muety/wakapi/config/config.go:213.97,215.5 1 0 -github.com/muety/wakapi/config/config.go:221.60,223.2 1 0 -github.com/muety/wakapi/config/config.go:225.59,227.2 1 0 -github.com/muety/wakapi/config/config.go:229.57,231.2 1 0 -github.com/muety/wakapi/config/config.go:233.53,235.2 1 0 -github.com/muety/wakapi/config/config.go:237.55,240.2 2 0 -github.com/muety/wakapi/config/config.go:242.50,244.2 1 0 -github.com/muety/wakapi/config/config.go:246.54,249.2 2 0 -github.com/muety/wakapi/config/config.go:251.36,253.2 1 0 -github.com/muety/wakapi/config/config.go:255.35,257.2 1 0 -github.com/muety/wakapi/config/config.go:259.38,261.2 1 0 -github.com/muety/wakapi/config/config.go:263.46,265.2 1 0 -github.com/muety/wakapi/config/config.go:267.43,269.2 1 0 -github.com/muety/wakapi/config/config.go:271.29,273.2 1 1 -github.com/muety/wakapi/config/config.go:275.48,286.16 2 0 -github.com/muety/wakapi/config/config.go:290.2,291.53 2 0 -github.com/muety/wakapi/config/config.go:295.2,295.15 1 0 -github.com/muety/wakapi/config/config.go:286.16,288.3 1 0 -github.com/muety/wakapi/config/config.go:291.53,293.3 1 0 -github.com/muety/wakapi/config/config.go:298.38,299.43 1 0 -github.com/muety/wakapi/config/config.go:302.2,302.15 1 0 -github.com/muety/wakapi/config/config.go:299.43,301.3 1 0 -github.com/muety/wakapi/config/config.go:305.45,306.27 1 0 -github.com/muety/wakapi/config/config.go:309.2,309.24 1 0 -github.com/muety/wakapi/config/config.go:312.2,312.25 1 0 -github.com/muety/wakapi/config/config.go:315.2,315.15 1 0 -github.com/muety/wakapi/config/config.go:306.27,308.3 1 0 -github.com/muety/wakapi/config/config.go:309.24,311.3 1 0 -github.com/muety/wakapi/config/config.go:312.25,314.3 1 0 -github.com/muety/wakapi/config/config.go:318.77,319.29 1 0 -github.com/muety/wakapi/config/config.go:324.2,324.19 1 0 -github.com/muety/wakapi/config/config.go:319.29,320.18 1 0 -github.com/muety/wakapi/config/config.go:320.18,322.4 1 0 -github.com/muety/wakapi/config/config.go:327.42,328.28 1 0 -github.com/muety/wakapi/config/config.go:344.2,344.20 1 0 -github.com/muety/wakapi/config/config.go:329.52,330.21 1 0 -github.com/muety/wakapi/config/config.go:331.53,332.22 1 0 -github.com/muety/wakapi/config/config.go:333.55,334.24 1 0 -github.com/muety/wakapi/config/config.go:335.54,336.23 1 0 -github.com/muety/wakapi/config/config.go:337.52,338.21 1 0 -github.com/muety/wakapi/config/config.go:339.54,340.23 1 0 -github.com/muety/wakapi/config/config.go:341.52,342.21 1 0 -github.com/muety/wakapi/config/config.go:347.26,349.2 1 0 -github.com/muety/wakapi/config/config.go:351.20,353.2 1 0 -github.com/muety/wakapi/config/config.go:355.35,360.96 3 0 -github.com/muety/wakapi/config/config.go:364.2,374.52 7 0 -github.com/muety/wakapi/config/config.go:378.2,378.47 1 0 -github.com/muety/wakapi/config/config.go:384.2,384.29 1 0 -github.com/muety/wakapi/config/config.go:390.2,390.106 1 0 -github.com/muety/wakapi/config/config.go:393.2,393.28 1 0 -github.com/muety/wakapi/config/config.go:396.2,396.51 1 0 -github.com/muety/wakapi/config/config.go:400.2,400.94 1 0 -github.com/muety/wakapi/config/config.go:403.2,403.81 1 0 -github.com/muety/wakapi/config/config.go:406.2,406.75 1 0 -github.com/muety/wakapi/config/config.go:409.2,409.74 1 0 -github.com/muety/wakapi/config/config.go:413.2,414.14 2 0 -github.com/muety/wakapi/config/config.go:360.96,362.3 1 0 -github.com/muety/wakapi/config/config.go:374.52,376.3 1 0 -github.com/muety/wakapi/config/config.go:378.47,379.14 1 0 -github.com/muety/wakapi/config/config.go:379.14,381.4 1 0 -github.com/muety/wakapi/config/config.go:384.29,387.3 2 0 -github.com/muety/wakapi/config/config.go:390.106,392.3 1 0 -github.com/muety/wakapi/config/config.go:393.28,395.3 1 0 -github.com/muety/wakapi/config/config.go:396.51,399.3 2 0 -github.com/muety/wakapi/config/config.go:400.94,402.3 1 0 -github.com/muety/wakapi/config/config.go:403.81,405.3 1 0 -github.com/muety/wakapi/config/config.go:406.75,408.3 1 0 -github.com/muety/wakapi/config/config.go:409.74,411.3 1 0 -github.com/muety/wakapi/config/db.go:39.50,40.19 1 0 -github.com/muety/wakapi/config/db.go:53.2,53.12 1 0 -github.com/muety/wakapi/config/db.go:41.23,45.5 1 0 -github.com/muety/wakapi/config/db.go:46.26,49.5 1 0 -github.com/muety/wakapi/config/db.go:50.24,51.48 1 0 -github.com/muety/wakapi/config/db.go:56.53,66.2 1 1 -github.com/muety/wakapi/config/db.go:68.56,70.16 2 1 -github.com/muety/wakapi/config/db.go:74.2,81.3 1 1 -github.com/muety/wakapi/config/db.go:70.16,72.3 1 0 -github.com/muety/wakapi/config/db.go:84.54,86.2 1 1 -github.com/muety/wakapi/config/eventbus.go:26.13,28.2 1 1 -github.com/muety/wakapi/config/eventbus.go:30.26,32.2 1 0 -github.com/muety/wakapi/config/fs.go:9.56,10.19 1 0 -github.com/muety/wakapi/config/fs.go:13.2,13.19 1 0 -github.com/muety/wakapi/config/fs.go:10.19,12.3 1 0 -github.com/muety/wakapi/routes/compat/shields/v1/badge.go:30.112,37.2 1 0 -github.com/muety/wakapi/routes/compat/shields/v1/badge.go:39.59,43.2 2 0 -github.com/muety/wakapi/routes/compat/shields/v1/badge.go:55.68,60.79 4 0 -github.com/muety/wakapi/routes/compat/shields/v1/badge.go:64.2,65.75 2 0 -github.com/muety/wakapi/routes/compat/shields/v1/badge.go:71.2,73.16 3 0 -github.com/muety/wakapi/routes/compat/shields/v1/badge.go:78.2,81.62 3 0 -github.com/muety/wakapi/routes/compat/shields/v1/badge.go:87.2,89.22 3 0 -github.com/muety/wakapi/routes/compat/shields/v1/badge.go:114.2,114.19 1 0 -github.com/muety/wakapi/routes/compat/shields/v1/badge.go:120.2,121.50 2 0 -github.com/muety/wakapi/routes/compat/shields/v1/badge.go:126.2,127.16 2 0 -github.com/muety/wakapi/routes/compat/shields/v1/badge.go:133.2,135.44 3 0 -github.com/muety/wakapi/routes/compat/shields/v1/badge.go:60.79,62.3 1 0 -github.com/muety/wakapi/routes/compat/shields/v1/badge.go:65.75,66.59 1 0 -github.com/muety/wakapi/routes/compat/shields/v1/badge.go:66.59,68.4 1 0 -github.com/muety/wakapi/routes/compat/shields/v1/badge.go:73.16,76.3 2 0 -github.com/muety/wakapi/routes/compat/shields/v1/badge.go:81.62,85.3 3 0 -github.com/muety/wakapi/routes/compat/shields/v1/badge.go:90.17,92.68 2 0 -github.com/muety/wakapi/routes/compat/shields/v1/badge.go:93.12,95.63 2 0 -github.com/muety/wakapi/routes/compat/shields/v1/badge.go:96.16,98.67 2 0 -github.com/muety/wakapi/routes/compat/shields/v1/badge.go:99.18,101.69 2 0 -github.com/muety/wakapi/routes/compat/shields/v1/badge.go:102.17,104.68 2 0 -github.com/muety/wakapi/routes/compat/shields/v1/badge.go:105.15,107.66 2 0 -github.com/muety/wakapi/routes/compat/shields/v1/badge.go:109.10,111.30 2 0 -github.com/muety/wakapi/routes/compat/shields/v1/badge.go:114.19,118.3 3 0 -github.com/muety/wakapi/routes/compat/shields/v1/badge.go:121.50,124.3 2 0 -github.com/muety/wakapi/routes/compat/shields/v1/badge.go:127.16,131.3 3 0 -github.com/muety/wakapi/routes/compat/shields/v1/badge.go:138.144,140.16 2 0 -github.com/muety/wakapi/routes/compat/shields/v1/badge.go:144.2,151.29 3 0 -github.com/muety/wakapi/routes/compat/shields/v1/badge.go:155.2,163.16 2 0 -github.com/muety/wakapi/routes/compat/shields/v1/badge.go:167.2,167.36 1 0 -github.com/muety/wakapi/routes/compat/shields/v1/badge.go:140.16,142.3 1 0 -github.com/muety/wakapi/routes/compat/shields/v1/badge.go:151.29,153.3 1 0 -github.com/muety/wakapi/routes/compat/shields/v1/badge.go:163.16,165.3 1 0 +github.com/muety/wakapi/utils/template.go:13.41,15.16 2 0 +github.com/muety/wakapi/utils/template.go:18.2,18.23 1 0 +github.com/muety/wakapi/utils/template.go:15.16,17.3 1 0 +github.com/muety/wakapi/utils/template.go:21.37,22.30 1 0 +github.com/muety/wakapi/utils/template.go:25.2,25.10 1 0 +github.com/muety/wakapi/utils/template.go:22.30,24.3 1 0 +github.com/muety/wakapi/utils/template.go:28.83,33.16 4 0 +github.com/muety/wakapi/utils/template.go:37.2,37.29 1 0 +github.com/muety/wakapi/utils/template.go:62.2,62.23 1 0 +github.com/muety/wakapi/utils/template.go:33.16,35.3 1 0 +github.com/muety/wakapi/utils/template.go:37.29,39.51 2 0 +github.com/muety/wakapi/utils/template.go:43.3,44.17 2 0 +github.com/muety/wakapi/utils/template.go:47.3,48.17 2 0 +github.com/muety/wakapi/utils/template.go:52.3,55.17 3 0 +github.com/muety/wakapi/utils/template.go:59.3,59.27 1 0 +github.com/muety/wakapi/utils/template.go:39.51,40.12 1 0 +github.com/muety/wakapi/utils/template.go:44.17,46.4 1 0 +github.com/muety/wakapi/utils/template.go:48.17,50.4 1 0 +github.com/muety/wakapi/utils/template.go:55.17,57.4 1 0 +github.com/muety/wakapi/utils/db.go:8.34,9.37 1 0 +github.com/muety/wakapi/utils/db.go:17.2,18.14 2 0 +github.com/muety/wakapi/utils/db.go:9.37,11.110 2 0 +github.com/muety/wakapi/utils/db.go:15.3,15.20 1 0 +github.com/muety/wakapi/utils/db.go:11.110,14.4 2 0 +github.com/muety/wakapi/utils/db.go:21.39,22.37 1 0 +github.com/muety/wakapi/utils/db.go:30.2,31.14 2 0 +github.com/muety/wakapi/utils/db.go:22.37,24.119 2 0 +github.com/muety/wakapi/utils/db.go:28.3,28.20 1 0 +github.com/muety/wakapi/utils/db.go:24.119,27.4 2 0 +github.com/muety/wakapi/utils/strings.go:8.34,10.2 1 0 +github.com/muety/wakapi/utils/common.go:18.73,19.58 1 0 +github.com/muety/wakapi/utils/common.go:22.2,22.87 1 0 +github.com/muety/wakapi/utils/common.go:25.2,25.64 1 0 +github.com/muety/wakapi/utils/common.go:19.58,21.3 1 0 +github.com/muety/wakapi/utils/common.go:22.87,24.3 1 0 +github.com/muety/wakapi/utils/common.go:28.40,30.2 1 0 +github.com/muety/wakapi/utils/common.go:32.44,34.2 1 0 +github.com/muety/wakapi/utils/common.go:36.49,38.2 1 0 +github.com/muety/wakapi/utils/common.go:40.45,42.2 1 0 +github.com/muety/wakapi/utils/common.go:44.24,46.2 1 0 +github.com/muety/wakapi/utils/common.go:48.56,51.45 3 1 +github.com/muety/wakapi/utils/common.go:54.2,54.40 1 1 +github.com/muety/wakapi/utils/common.go:51.45,53.3 1 1 +github.com/muety/wakapi/utils/date.go:9.48,11.2 1 0 +github.com/muety/wakapi/utils/date.go:13.51,15.2 1 0 +github.com/muety/wakapi/utils/date.go:17.52,19.2 1 0 +github.com/muety/wakapi/utils/date.go:21.51,23.2 1 0 +github.com/muety/wakapi/utils/date.go:26.41,28.21 2 0 +github.com/muety/wakapi/utils/date.go:31.2,31.33 1 0 +github.com/muety/wakapi/utils/date.go:28.21,30.3 1 0 +github.com/muety/wakapi/utils/date.go:35.67,38.33 2 1 +github.com/muety/wakapi/utils/date.go:47.2,47.18 1 1 +github.com/muety/wakapi/utils/date.go:38.33,40.19 2 1 +github.com/muety/wakapi/utils/date.go:43.3,44.10 2 1 +github.com/muety/wakapi/utils/date.go:40.19,42.4 1 1 +github.com/muety/wakapi/utils/date.go:50.50,56.2 5 0 +github.com/muety/wakapi/utils/date.go:59.36,62.2 2 0 +github.com/muety/wakapi/utils/http.go:21.13,23.2 1 1 +github.com/muety/wakapi/utils/http.go:25.90,28.58 3 0 +github.com/muety/wakapi/utils/http.go:28.58,30.3 1 0 +github.com/muety/wakapi/utils/http.go:33.62,35.48 2 0 +github.com/muety/wakapi/utils/http.go:38.2,38.93 1 0 +github.com/muety/wakapi/utils/http.go:43.2,43.14 1 0 +github.com/muety/wakapi/utils/http.go:35.48,37.3 1 0 +github.com/muety/wakapi/utils/http.go:38.93,39.89 1 0 +github.com/muety/wakapi/utils/http.go:39.89,41.4 1 0 +github.com/muety/wakapi/utils/summary.go:10.66,11.40 1 0 +github.com/muety/wakapi/utils/summary.go:16.2,16.48 1 0 +github.com/muety/wakapi/utils/summary.go:11.40,12.27 1 0 +github.com/muety/wakapi/utils/summary.go:12.27,14.4 1 0 +github.com/muety/wakapi/utils/summary.go:19.88,22.2 2 0 +github.com/muety/wakapi/utils/summary.go:24.95,26.16 2 0 +github.com/muety/wakapi/utils/summary.go:29.2,29.38 1 0 +github.com/muety/wakapi/utils/summary.go:26.16,28.3 1 0 +github.com/muety/wakapi/utils/summary.go:32.105,36.18 3 0 +github.com/muety/wakapi/utils/summary.go:71.2,71.22 1 0 +github.com/muety/wakapi/utils/summary.go:37.28,38.26 1 0 +github.com/muety/wakapi/utils/summary.go:39.32,41.24 2 0 +github.com/muety/wakapi/utils/summary.go:42.31,43.29 1 0 +github.com/muety/wakapi/utils/summary.go:44.31,46.27 2 0 +github.com/muety/wakapi/utils/summary.go:47.32,48.30 1 0 +github.com/muety/wakapi/utils/summary.go:49.32,51.28 2 0 +github.com/muety/wakapi/utils/summary.go:52.31,53.29 1 0 +github.com/muety/wakapi/utils/summary.go:54.32,55.31 1 0 +github.com/muety/wakapi/utils/summary.go:56.41,58.42 2 0 +github.com/muety/wakapi/utils/summary.go:59.33,60.32 1 0 +github.com/muety/wakapi/utils/summary.go:61.33,62.32 1 0 +github.com/muety/wakapi/utils/summary.go:63.35,64.32 1 0 +github.com/muety/wakapi/utils/summary.go:65.26,66.21 1 0 +github.com/muety/wakapi/utils/summary.go:67.10,68.39 1 0 +github.com/muety/wakapi/utils/summary.go:74.73,81.56 5 0 +github.com/muety/wakapi/utils/summary.go:97.2,107.8 3 0 +github.com/muety/wakapi/utils/summary.go:81.56,83.3 1 0 +github.com/muety/wakapi/utils/summary.go:83.8,83.54 1 0 +github.com/muety/wakapi/utils/summary.go:83.54,85.3 1 0 +github.com/muety/wakapi/utils/summary.go:85.8,87.17 2 0 +github.com/muety/wakapi/utils/summary.go:91.3,92.17 2 0 +github.com/muety/wakapi/utils/summary.go:87.17,89.4 1 0 +github.com/muety/wakapi/utils/summary.go:92.17,94.4 1 0 +github.com/muety/wakapi/utils/summary.go:110.59,112.48 2 0 +github.com/muety/wakapi/utils/summary.go:115.2,115.49 1 0 +github.com/muety/wakapi/utils/summary.go:118.2,118.47 1 0 +github.com/muety/wakapi/utils/summary.go:121.2,121.48 1 0 +github.com/muety/wakapi/utils/summary.go:124.2,124.57 1 0 +github.com/muety/wakapi/utils/summary.go:127.2,127.46 1 0 +github.com/muety/wakapi/utils/summary.go:130.2,130.47 1 0 +github.com/muety/wakapi/utils/summary.go:133.2,133.16 1 0 +github.com/muety/wakapi/utils/summary.go:112.48,114.3 1 0 +github.com/muety/wakapi/utils/summary.go:115.49,117.3 1 0 +github.com/muety/wakapi/utils/summary.go:118.47,120.3 1 0 +github.com/muety/wakapi/utils/summary.go:121.48,123.3 1 0 +github.com/muety/wakapi/utils/summary.go:124.57,126.3 1 0 +github.com/muety/wakapi/utils/summary.go:127.46,129.3 1 0 +github.com/muety/wakapi/utils/summary.go:130.47,132.3 1 0 +github.com/muety/wakapi/utils/summary.go:136.48,140.51 2 0 +github.com/muety/wakapi/utils/summary.go:143.2,143.12 1 0 +github.com/muety/wakapi/utils/summary.go:140.51,142.3 1 0 +github.com/muety/wakapi/utils/auth.go:16.79,18.54 2 0 +github.com/muety/wakapi/utils/auth.go:22.2,24.16 3 0 +github.com/muety/wakapi/utils/auth.go:28.2,30.45 3 0 +github.com/muety/wakapi/utils/auth.go:33.2,34.32 2 0 +github.com/muety/wakapi/utils/auth.go:18.54,20.3 1 0 +github.com/muety/wakapi/utils/auth.go:24.16,26.3 1 0 +github.com/muety/wakapi/utils/auth.go:30.45,32.3 1 0 +github.com/muety/wakapi/utils/auth.go:37.65,39.85 2 0 +github.com/muety/wakapi/utils/auth.go:43.2,44.30 2 0 +github.com/muety/wakapi/utils/auth.go:39.85,41.3 1 0 +github.com/muety/wakapi/utils/auth.go:47.94,49.16 2 0 +github.com/muety/wakapi/utils/auth.go:53.2,53.107 1 0 +github.com/muety/wakapi/utils/auth.go:57.2,57.22 1 0 +github.com/muety/wakapi/utils/auth.go:49.16,51.3 1 0 +github.com/muety/wakapi/utils/auth.go:53.107,55.3 1 0 +github.com/muety/wakapi/utils/auth.go:60.56,64.2 3 0 +github.com/muety/wakapi/utils/auth.go:66.55,69.16 3 0 +github.com/muety/wakapi/utils/auth.go:72.2,72.16 1 0 +github.com/muety/wakapi/utils/auth.go:69.16,71.3 1 0 +github.com/muety/wakapi/utils/color.go:8.90,10.32 2 0 +github.com/muety/wakapi/utils/color.go:15.2,15.15 1 0 +github.com/muety/wakapi/utils/color.go:10.32,11.50 1 0 +github.com/muety/wakapi/utils/color.go:11.50,13.4 1 0 github.com/muety/wakapi/middlewares/sentry.go:15.60,16.43 1 0 github.com/muety/wakapi/middlewares/sentry.go:16.43,20.3 1 0 github.com/muety/wakapi/middlewares/sentry.go:23.78,26.54 3 0 @@ -584,472 +691,24 @@ github.com/muety/wakapi/middlewares/security.go:25.80,26.36 1 0 github.com/muety/wakapi/middlewares/security.go:31.2,31.27 1 0 github.com/muety/wakapi/middlewares/security.go:26.36,27.30 1 0 github.com/muety/wakapi/middlewares/security.go:27.30,29.4 1 0 -github.com/muety/wakapi/utils/date.go:14.43,16.2 1 1 -github.com/muety/wakapi/utils/date.go:18.48,20.2 1 0 -github.com/muety/wakapi/utils/date.go:22.41,24.21 2 1 -github.com/muety/wakapi/utils/date.go:27.2,27.23 1 1 -github.com/muety/wakapi/utils/date.go:24.21,26.3 1 0 -github.com/muety/wakapi/utils/date.go:30.46,32.2 1 0 -github.com/muety/wakapi/utils/date.go:34.51,36.2 1 0 -github.com/muety/wakapi/utils/date.go:38.44,41.2 2 1 -github.com/muety/wakapi/utils/date.go:43.52,45.2 1 0 -github.com/muety/wakapi/utils/date.go:47.45,49.2 1 0 -github.com/muety/wakapi/utils/date.go:51.51,53.2 1 0 -github.com/muety/wakapi/utils/date.go:55.44,57.2 1 0 -github.com/muety/wakapi/utils/date.go:60.42,62.2 1 1 -github.com/muety/wakapi/utils/date.go:65.46,67.2 1 0 -github.com/muety/wakapi/utils/date.go:70.41,72.21 2 1 -github.com/muety/wakapi/utils/date.go:75.2,75.33 1 1 -github.com/muety/wakapi/utils/date.go:72.21,74.3 1 1 -github.com/muety/wakapi/utils/date.go:79.63,81.2 1 0 -github.com/muety/wakapi/utils/date.go:84.62,90.2 5 0 -github.com/muety/wakapi/utils/date.go:93.67,96.33 2 1 -github.com/muety/wakapi/utils/date.go:105.2,105.18 1 1 -github.com/muety/wakapi/utils/date.go:96.33,98.19 2 1 -github.com/muety/wakapi/utils/date.go:101.3,102.10 2 1 -github.com/muety/wakapi/utils/date.go:98.19,100.4 1 1 -github.com/muety/wakapi/utils/date.go:108.50,114.2 5 0 -github.com/muety/wakapi/utils/date.go:117.36,120.2 2 0 -github.com/muety/wakapi/utils/date.go:123.79,126.36 3 1 -github.com/muety/wakapi/utils/date.go:130.2,130.21 1 1 -github.com/muety/wakapi/utils/date.go:134.2,134.21 1 1 -github.com/muety/wakapi/utils/date.go:138.2,138.13 1 1 -github.com/muety/wakapi/utils/date.go:126.36,129.3 2 0 -github.com/muety/wakapi/utils/date.go:130.21,133.3 2 1 -github.com/muety/wakapi/utils/date.go:134.21,137.3 2 1 -github.com/muety/wakapi/utils/strings.go:8.34,10.2 1 0 -github.com/muety/wakapi/utils/summary.go:10.66,11.40 1 0 -github.com/muety/wakapi/utils/summary.go:16.2,16.48 1 0 -github.com/muety/wakapi/utils/summary.go:11.40,12.27 1 0 -github.com/muety/wakapi/utils/summary.go:12.27,14.4 1 0 -github.com/muety/wakapi/utils/summary.go:19.88,22.2 2 0 -github.com/muety/wakapi/utils/summary.go:24.95,26.16 2 0 -github.com/muety/wakapi/utils/summary.go:29.2,29.38 1 0 -github.com/muety/wakapi/utils/summary.go:26.16,28.3 1 0 -github.com/muety/wakapi/utils/summary.go:32.105,36.18 3 0 -github.com/muety/wakapi/utils/summary.go:71.2,71.22 1 0 -github.com/muety/wakapi/utils/summary.go:37.28,38.26 1 0 -github.com/muety/wakapi/utils/summary.go:39.32,41.24 2 0 -github.com/muety/wakapi/utils/summary.go:42.31,43.29 1 0 -github.com/muety/wakapi/utils/summary.go:44.31,46.27 2 0 -github.com/muety/wakapi/utils/summary.go:47.32,48.30 1 0 -github.com/muety/wakapi/utils/summary.go:49.32,51.28 2 0 -github.com/muety/wakapi/utils/summary.go:52.31,53.29 1 0 -github.com/muety/wakapi/utils/summary.go:54.32,55.31 1 0 -github.com/muety/wakapi/utils/summary.go:56.41,58.42 2 0 -github.com/muety/wakapi/utils/summary.go:59.33,60.32 1 0 -github.com/muety/wakapi/utils/summary.go:61.33,62.32 1 0 -github.com/muety/wakapi/utils/summary.go:63.35,64.32 1 0 -github.com/muety/wakapi/utils/summary.go:65.26,66.21 1 0 -github.com/muety/wakapi/utils/summary.go:67.10,68.39 1 0 -github.com/muety/wakapi/utils/summary.go:74.73,81.56 5 0 -github.com/muety/wakapi/utils/summary.go:97.2,107.8 3 0 -github.com/muety/wakapi/utils/summary.go:81.56,83.3 1 0 -github.com/muety/wakapi/utils/summary.go:83.8,83.54 1 0 -github.com/muety/wakapi/utils/summary.go:83.54,85.3 1 0 -github.com/muety/wakapi/utils/summary.go:85.8,87.17 2 0 -github.com/muety/wakapi/utils/summary.go:91.3,92.17 2 0 -github.com/muety/wakapi/utils/summary.go:87.17,89.4 1 0 -github.com/muety/wakapi/utils/summary.go:92.17,94.4 1 0 -github.com/muety/wakapi/utils/summary.go:110.59,112.48 2 0 -github.com/muety/wakapi/utils/summary.go:115.2,115.49 1 0 -github.com/muety/wakapi/utils/summary.go:118.2,118.47 1 0 -github.com/muety/wakapi/utils/summary.go:121.2,121.48 1 0 -github.com/muety/wakapi/utils/summary.go:124.2,124.57 1 0 -github.com/muety/wakapi/utils/summary.go:127.2,127.46 1 0 -github.com/muety/wakapi/utils/summary.go:130.2,130.47 1 0 -github.com/muety/wakapi/utils/summary.go:133.2,133.16 1 0 -github.com/muety/wakapi/utils/summary.go:112.48,114.3 1 0 -github.com/muety/wakapi/utils/summary.go:115.49,117.3 1 0 -github.com/muety/wakapi/utils/summary.go:118.47,120.3 1 0 -github.com/muety/wakapi/utils/summary.go:121.48,123.3 1 0 -github.com/muety/wakapi/utils/summary.go:124.57,126.3 1 0 -github.com/muety/wakapi/utils/summary.go:127.46,129.3 1 0 -github.com/muety/wakapi/utils/summary.go:130.47,132.3 1 0 -github.com/muety/wakapi/utils/summary.go:136.48,140.51 2 0 -github.com/muety/wakapi/utils/summary.go:143.2,143.12 1 0 -github.com/muety/wakapi/utils/summary.go:140.51,142.3 1 0 -github.com/muety/wakapi/utils/auth.go:16.79,18.54 2 0 -github.com/muety/wakapi/utils/auth.go:22.2,24.16 3 0 -github.com/muety/wakapi/utils/auth.go:28.2,30.45 3 0 -github.com/muety/wakapi/utils/auth.go:33.2,34.32 2 0 -github.com/muety/wakapi/utils/auth.go:18.54,20.3 1 0 -github.com/muety/wakapi/utils/auth.go:24.16,26.3 1 0 -github.com/muety/wakapi/utils/auth.go:30.45,32.3 1 0 -github.com/muety/wakapi/utils/auth.go:37.65,39.85 2 0 -github.com/muety/wakapi/utils/auth.go:43.2,44.30 2 0 -github.com/muety/wakapi/utils/auth.go:39.85,41.3 1 0 -github.com/muety/wakapi/utils/auth.go:47.94,49.16 2 0 -github.com/muety/wakapi/utils/auth.go:53.2,53.107 1 0 -github.com/muety/wakapi/utils/auth.go:57.2,57.22 1 0 -github.com/muety/wakapi/utils/auth.go:49.16,51.3 1 0 -github.com/muety/wakapi/utils/auth.go:53.107,55.3 1 0 -github.com/muety/wakapi/utils/auth.go:60.56,64.2 3 0 -github.com/muety/wakapi/utils/auth.go:66.55,69.16 3 0 -github.com/muety/wakapi/utils/auth.go:72.2,72.16 1 0 -github.com/muety/wakapi/utils/auth.go:69.16,71.3 1 0 -github.com/muety/wakapi/utils/color.go:8.90,10.32 2 0 -github.com/muety/wakapi/utils/color.go:15.2,15.15 1 0 -github.com/muety/wakapi/utils/color.go:10.32,11.50 1 0 -github.com/muety/wakapi/utils/color.go:11.50,13.4 1 0 -github.com/muety/wakapi/utils/common.go:18.73,19.58 1 0 -github.com/muety/wakapi/utils/common.go:22.2,22.87 1 0 -github.com/muety/wakapi/utils/common.go:25.2,25.64 1 0 -github.com/muety/wakapi/utils/common.go:19.58,21.3 1 0 -github.com/muety/wakapi/utils/common.go:22.87,24.3 1 0 -github.com/muety/wakapi/utils/common.go:28.40,30.2 1 0 -github.com/muety/wakapi/utils/common.go:32.44,34.2 1 0 -github.com/muety/wakapi/utils/common.go:36.49,38.2 1 0 -github.com/muety/wakapi/utils/common.go:40.45,42.2 1 0 -github.com/muety/wakapi/utils/common.go:44.24,46.2 1 0 -github.com/muety/wakapi/utils/common.go:48.56,51.45 3 1 -github.com/muety/wakapi/utils/common.go:54.2,54.40 1 1 -github.com/muety/wakapi/utils/common.go:51.45,53.3 1 1 -github.com/muety/wakapi/utils/db.go:8.34,9.37 1 0 -github.com/muety/wakapi/utils/db.go:17.2,18.14 2 0 -github.com/muety/wakapi/utils/db.go:9.37,11.110 2 0 -github.com/muety/wakapi/utils/db.go:15.3,15.20 1 0 -github.com/muety/wakapi/utils/db.go:11.110,14.4 2 0 -github.com/muety/wakapi/utils/db.go:21.39,22.37 1 0 -github.com/muety/wakapi/utils/db.go:30.2,31.14 2 0 -github.com/muety/wakapi/utils/db.go:22.37,24.119 2 0 -github.com/muety/wakapi/utils/db.go:28.3,28.20 1 0 -github.com/muety/wakapi/utils/db.go:24.119,27.4 2 0 -github.com/muety/wakapi/utils/http.go:9.90,12.58 3 0 -github.com/muety/wakapi/utils/http.go:12.58,14.3 1 0 -github.com/muety/wakapi/utils/template.go:13.41,15.16 2 0 -github.com/muety/wakapi/utils/template.go:18.2,18.23 1 0 -github.com/muety/wakapi/utils/template.go:15.16,17.3 1 0 -github.com/muety/wakapi/utils/template.go:21.37,22.30 1 0 -github.com/muety/wakapi/utils/template.go:25.2,25.10 1 0 -github.com/muety/wakapi/utils/template.go:22.30,24.3 1 0 -github.com/muety/wakapi/utils/template.go:28.83,33.16 4 0 -github.com/muety/wakapi/utils/template.go:37.2,37.29 1 0 -github.com/muety/wakapi/utils/template.go:62.2,62.23 1 0 -github.com/muety/wakapi/utils/template.go:33.16,35.3 1 0 -github.com/muety/wakapi/utils/template.go:37.29,39.51 2 0 -github.com/muety/wakapi/utils/template.go:43.3,44.17 2 0 -github.com/muety/wakapi/utils/template.go:47.3,48.17 2 0 -github.com/muety/wakapi/utils/template.go:52.3,55.17 3 0 -github.com/muety/wakapi/utils/template.go:59.3,59.27 1 0 -github.com/muety/wakapi/utils/template.go:39.51,40.12 1 0 -github.com/muety/wakapi/utils/template.go:44.17,46.4 1 0 -github.com/muety/wakapi/utils/template.go:48.17,50.4 1 0 -github.com/muety/wakapi/utils/template.go:55.17,57.4 1 0 -github.com/muety/wakapi/services/alias.go:19.77,24.2 1 1 -github.com/muety/wakapi/services/alias.go:28.60,29.43 1 1 -github.com/muety/wakapi/services/alias.go:32.2,32.14 1 1 -github.com/muety/wakapi/services/alias.go:29.43,31.3 1 1 -github.com/muety/wakapi/services/alias.go:35.62,37.16 2 1 -github.com/muety/wakapi/services/alias.go:40.2,40.12 1 1 -github.com/muety/wakapi/services/alias.go:37.16,39.3 1 1 -github.com/muety/wakapi/services/alias.go:43.59,44.51 1 1 -github.com/muety/wakapi/services/alias.go:44.51,46.3 1 0 -github.com/muety/wakapi/services/alias.go:49.76,50.32 1 0 -github.com/muety/wakapi/services/alias.go:53.2,53.49 1 0 -github.com/muety/wakapi/services/alias.go:50.32,52.3 1 0 -github.com/muety/wakapi/services/alias.go:53.49,55.3 1 0 -github.com/muety/wakapi/services/alias.go:55.8,57.3 1 0 -github.com/muety/wakapi/services/alias.go:60.102,61.38 1 0 -github.com/muety/wakapi/services/alias.go:64.2,64.39 1 0 -github.com/muety/wakapi/services/alias.go:61.38,63.3 1 0 -github.com/muety/wakapi/services/alias.go:67.113,68.38 1 0 -github.com/muety/wakapi/services/alias.go:71.2,71.39 1 0 -github.com/muety/wakapi/services/alias.go:68.38,70.3 1 0 -github.com/muety/wakapi/services/alias.go:74.108,75.32 1 1 -github.com/muety/wakapi/services/alias.go:79.2,79.49 1 1 -github.com/muety/wakapi/services/alias.go:87.2,87.19 1 1 -github.com/muety/wakapi/services/alias.go:75.32,77.3 1 1 -github.com/muety/wakapi/services/alias.go:79.49,80.47 1 1 -github.com/muety/wakapi/services/alias.go:80.47,81.49 1 1 -github.com/muety/wakapi/services/alias.go:81.49,83.5 1 1 -github.com/muety/wakapi/services/alias.go:90.77,92.16 2 0 -github.com/muety/wakapi/services/alias.go:96.2,100.20 3 0 -github.com/muety/wakapi/services/alias.go:92.16,94.3 1 0 -github.com/muety/wakapi/services/alias.go:103.60,104.24 1 0 -github.com/muety/wakapi/services/alias.go:107.2,110.16 2 0 -github.com/muety/wakapi/services/alias.go:114.2,116.12 2 0 -github.com/muety/wakapi/services/alias.go:104.24,106.3 1 0 -github.com/muety/wakapi/services/alias.go:110.16,112.3 1 0 -github.com/muety/wakapi/services/alias.go:119.69,123.28 3 0 -github.com/muety/wakapi/services/alias.go:131.2,134.16 2 0 -github.com/muety/wakapi/services/alias.go:140.2,140.31 1 0 -github.com/muety/wakapi/services/alias.go:144.2,144.12 1 0 -github.com/muety/wakapi/services/alias.go:123.28,124.21 1 0 -github.com/muety/wakapi/services/alias.go:127.3,128.16 2 0 -github.com/muety/wakapi/services/alias.go:124.21,126.4 1 0 -github.com/muety/wakapi/services/alias.go:134.16,135.29 1 0 -github.com/muety/wakapi/services/alias.go:135.29,137.4 1 0 -github.com/muety/wakapi/services/alias.go:140.31,142.3 1 0 -github.com/muety/wakapi/services/alias.go:147.74,148.14 1 0 -github.com/muety/wakapi/services/alias.go:148.14,149.57 1 0 -github.com/muety/wakapi/services/alias.go:149.57,153.4 3 0 -github.com/muety/wakapi/services/alias.go:154.8,155.57 1 0 -github.com/muety/wakapi/services/alias.go:155.57,157.48 2 0 -github.com/muety/wakapi/services/alias.go:162.4,162.52 1 0 -github.com/muety/wakapi/services/alias.go:157.48,158.26 1 0 -github.com/muety/wakapi/services/alias.go:158.26,160.6 1 0 -github.com/muety/wakapi/services/alias.go:167.116,168.32 1 0 -github.com/muety/wakapi/services/alias.go:171.2,171.49 1 0 -github.com/muety/wakapi/services/alias.go:168.32,170.3 1 0 -github.com/muety/wakapi/services/alias.go:171.49,173.47 2 0 -github.com/muety/wakapi/services/alias.go:178.3,178.30 1 0 -github.com/muety/wakapi/services/alias.go:173.47,174.16 1 0 -github.com/muety/wakapi/services/alias.go:174.16,176.5 1 0 -github.com/muety/wakapi/services/alias.go:179.8,181.3 1 0 -github.com/muety/wakapi/services/duration.go:16.78,22.2 2 1 -github.com/muety/wakapi/services/duration.go:24.123,27.42 2 1 -github.com/muety/wakapi/services/duration.go:33.2,34.16 2 1 -github.com/muety/wakapi/services/duration.go:41.2,46.31 4 1 -github.com/muety/wakapi/services/duration.go:81.2,83.31 2 1 -github.com/muety/wakapi/services/duration.go:96.2,96.49 1 1 -github.com/muety/wakapi/services/duration.go:100.2,100.32 1 1 -github.com/muety/wakapi/services/duration.go:27.42,28.90 1 1 -github.com/muety/wakapi/services/duration.go:28.90,30.4 1 1 -github.com/muety/wakapi/services/duration.go:34.16,36.3 1 0 -github.com/muety/wakapi/services/duration.go:46.31,47.42 1 1 -github.com/muety/wakapi/services/duration.go:51.3,53.62 2 1 -github.com/muety/wakapi/services/duration.go:57.3,57.20 1 1 -github.com/muety/wakapi/services/duration.go:62.3,63.35 2 1 -github.com/muety/wakapi/services/duration.go:66.3,68.72 2 1 -github.com/muety/wakapi/services/duration.go:78.3,78.10 1 1 -github.com/muety/wakapi/services/duration.go:47.42,48.12 1 1 -github.com/muety/wakapi/services/duration.go:53.62,55.4 1 1 -github.com/muety/wakapi/services/duration.go:57.20,59.12 2 1 -github.com/muety/wakapi/services/duration.go:63.35,65.4 1 1 -github.com/muety/wakapi/services/duration.go:68.72,70.41 2 1 -github.com/muety/wakapi/services/duration.go:73.4,73.15 1 1 -github.com/muety/wakapi/services/duration.go:70.41,72.5 1 1 -github.com/muety/wakapi/services/duration.go:74.9,76.4 1 1 -github.com/muety/wakapi/services/duration.go:83.31,84.26 1 1 -github.com/muety/wakapi/services/duration.go:84.26,89.23 1 1 -github.com/muety/wakapi/services/duration.go:92.4,92.36 1 1 -github.com/muety/wakapi/services/duration.go:89.23,91.5 1 1 -github.com/muety/wakapi/services/duration.go:96.49,98.3 1 1 -github.com/muety/wakapi/services/key_value.go:14.89,19.2 1 0 -github.com/muety/wakapi/services/key_value.go:21.83,23.2 1 0 -github.com/muety/wakapi/services/key_value.go:25.78,27.16 2 0 -github.com/muety/wakapi/services/key_value.go:33.2,33.11 1 0 -github.com/muety/wakapi/services/key_value.go:27.16,32.3 1 0 -github.com/muety/wakapi/services/key_value.go:36.72,38.2 1 0 -github.com/muety/wakapi/services/key_value.go:40.60,42.2 1 0 -github.com/muety/wakapi/services/misc.go:21.126,28.2 1 0 -github.com/muety/wakapi/services/misc.go:40.50,42.48 1 0 -github.com/muety/wakapi/services/misc.go:46.2,48.19 3 0 -github.com/muety/wakapi/services/misc.go:42.48,44.3 1 0 -github.com/muety/wakapi/services/misc.go:51.51,53.16 2 0 -github.com/muety/wakapi/services/misc.go:57.2,60.26 3 0 -github.com/muety/wakapi/services/misc.go:66.2,68.40 2 0 -github.com/muety/wakapi/services/misc.go:73.2,75.33 3 0 -github.com/muety/wakapi/services/misc.go:79.2,84.17 2 0 -github.com/muety/wakapi/services/misc.go:88.2,91.17 1 0 -github.com/muety/wakapi/services/misc.go:95.2,95.12 1 0 -github.com/muety/wakapi/services/misc.go:53.16,55.3 1 0 -github.com/muety/wakapi/services/misc.go:60.26,65.3 1 0 -github.com/muety/wakapi/services/misc.go:68.40,70.3 1 0 -github.com/muety/wakapi/services/misc.go:75.33,78.3 2 0 -github.com/muety/wakapi/services/misc.go:84.17,86.3 1 0 -github.com/muety/wakapi/services/misc.go:91.17,93.3 1 0 -github.com/muety/wakapi/services/misc.go:98.116,99.24 1 0 -github.com/muety/wakapi/services/misc.go:99.24,100.156 1 0 -github.com/muety/wakapi/services/misc.go:100.156,102.4 1 0 -github.com/muety/wakapi/services/misc.go:102.9,107.4 1 0 -github.com/muety/wakapi/services/project_label.go:21.111,28.2 1 0 -github.com/muety/wakapi/services/project_label.go:30.80,32.2 1 0 -github.com/muety/wakapi/services/project_label.go:34.90,35.51 1 0 -github.com/muety/wakapi/services/project_label.go:39.2,40.16 2 0 -github.com/muety/wakapi/services/project_label.go:43.2,44.20 2 0 -github.com/muety/wakapi/services/project_label.go:35.51,37.3 1 0 -github.com/muety/wakapi/services/project_label.go:40.16,42.3 1 0 -github.com/muety/wakapi/services/project_label.go:48.108,50.16 2 0 -github.com/muety/wakapi/services/project_label.go:53.2,53.112 1 0 -github.com/muety/wakapi/services/project_label.go:56.2,56.26 1 0 -github.com/muety/wakapi/services/project_label.go:50.16,52.3 1 0 -github.com/muety/wakapi/services/project_label.go:53.112,55.3 1 0 -github.com/muety/wakapi/services/project_label.go:60.116,62.16 2 0 -github.com/muety/wakapi/services/project_label.go:65.2,65.112 1 0 -github.com/muety/wakapi/services/project_label.go:68.2,68.26 1 0 -github.com/muety/wakapi/services/project_label.go:62.16,64.3 1 0 -github.com/muety/wakapi/services/project_label.go:65.112,67.3 1 0 -github.com/muety/wakapi/services/project_label.go:71.98,73.16 2 0 -github.com/muety/wakapi/services/project_label.go:77.2,79.20 3 0 -github.com/muety/wakapi/services/project_label.go:73.16,75.3 1 0 -github.com/muety/wakapi/services/project_label.go:82.74,83.24 1 0 -github.com/muety/wakapi/services/project_label.go:86.2,89.12 4 0 -github.com/muety/wakapi/services/project_label.go:83.24,85.3 1 0 -github.com/muety/wakapi/services/project_label.go:92.89,94.14 2 0 -github.com/muety/wakapi/services/project_label.go:97.2,100.4 1 0 -github.com/muety/wakapi/services/project_label.go:94.14,96.3 1 0 -github.com/muety/wakapi/services/summary.go:29.189,41.33 3 1 -github.com/muety/wakapi/services/summary.go:52.2,52.12 1 1 -github.com/muety/wakapi/services/summary.go:41.33,42.31 1 1 -github.com/muety/wakapi/services/summary.go:42.31,44.39 2 0 -github.com/muety/wakapi/services/summary.go:44.39,45.71 1 0 -github.com/muety/wakapi/services/summary.go:45.71,47.6 1 0 -github.com/muety/wakapi/services/summary.go:58.161,61.66 2 1 -github.com/muety/wakapi/services/summary.go:66.2,71.20 4 1 -github.com/muety/wakapi/services/summary.go:77.2,77.65 1 1 -github.com/muety/wakapi/services/summary.go:82.2,83.16 2 1 -github.com/muety/wakapi/services/summary.go:88.2,93.105 5 1 -github.com/muety/wakapi/services/summary.go:97.2,98.30 2 1 -github.com/muety/wakapi/services/summary.go:61.66,63.3 1 0 -github.com/muety/wakapi/services/summary.go:71.20,74.3 2 1 -github.com/muety/wakapi/services/summary.go:77.65,79.3 1 0 -github.com/muety/wakapi/services/summary.go:83.16,85.3 1 0 -github.com/muety/wakapi/services/summary.go:93.105,95.3 1 1 -github.com/muety/wakapi/services/summary.go:101.126,105.41 2 1 -github.com/muety/wakapi/services/summary.go:116.2,117.44 2 1 -github.com/muety/wakapi/services/summary.go:126.2,127.16 2 1 -github.com/muety/wakapi/services/summary.go:131.2,131.30 1 1 -github.com/muety/wakapi/services/summary.go:105.41,108.17 2 1 -github.com/muety/wakapi/services/summary.go:108.17,110.4 1 1 -github.com/muety/wakapi/services/summary.go:110.9,112.4 1 0 -github.com/muety/wakapi/services/summary.go:117.44,118.87 1 1 -github.com/muety/wakapi/services/summary.go:118.87,120.4 1 1 -github.com/muety/wakapi/services/summary.go:120.9,122.4 1 0 -github.com/muety/wakapi/services/summary.go:127.16,129.3 1 0 -github.com/muety/wakapi/services/summary.go:134.127,137.16 2 1 -github.com/muety/wakapi/services/summary.go:141.2,142.74 2 1 -github.com/muety/wakapi/services/summary.go:146.2,148.26 3 1 -github.com/muety/wakapi/services/summary.go:153.2,160.34 7 1 -github.com/muety/wakapi/services/summary.go:178.2,178.25 1 1 -github.com/muety/wakapi/services/summary.go:183.2,196.30 2 1 -github.com/muety/wakapi/services/summary.go:137.16,139.3 1 0 -github.com/muety/wakapi/services/summary.go:142.74,144.3 1 1 -github.com/muety/wakapi/services/summary.go:148.26,150.3 1 1 -github.com/muety/wakapi/services/summary.go:160.34,162.20 2 1 -github.com/muety/wakapi/services/summary.go:163.30,164.29 1 1 -github.com/muety/wakapi/services/summary.go:165.31,166.30 1 1 -github.com/muety/wakapi/services/summary.go:167.29,168.28 1 1 -github.com/muety/wakapi/services/summary.go:169.25,170.24 1 1 -github.com/muety/wakapi/services/summary.go:171.30,172.29 1 1 -github.com/muety/wakapi/services/summary.go:173.29,174.28 1 1 -github.com/muety/wakapi/services/summary.go:178.25,181.3 2 1 -github.com/muety/wakapi/services/summary.go:201.76,203.2 1 0 -github.com/muety/wakapi/services/summary.go:205.62,208.2 2 0 -github.com/muety/wakapi/services/summary.go:210.66,213.2 2 0 -github.com/muety/wakapi/services/summary.go:217.125,220.30 2 1 -github.com/muety/wakapi/services/summary.go:224.2,225.28 2 1 -github.com/muety/wakapi/services/summary.go:233.2,233.40 1 1 -github.com/muety/wakapi/services/summary.go:237.2,237.67 1 1 -github.com/muety/wakapi/services/summary.go:220.30,222.3 1 1 -github.com/muety/wakapi/services/summary.go:225.28,231.3 1 1 -github.com/muety/wakapi/services/summary.go:233.40,235.3 1 1 -github.com/muety/wakapi/services/summary.go:240.87,241.72 1 1 -github.com/muety/wakapi/services/summary.go:249.2,250.16 2 1 -github.com/muety/wakapi/services/summary.go:255.2,256.37 2 1 -github.com/muety/wakapi/services/summary.go:260.2,262.30 3 1 -github.com/muety/wakapi/services/summary.go:273.2,274.29 2 1 -github.com/muety/wakapi/services/summary.go:279.2,280.16 2 1 -github.com/muety/wakapi/services/summary.go:241.72,247.3 1 1 -github.com/muety/wakapi/services/summary.go:250.16,253.3 2 0 -github.com/muety/wakapi/services/summary.go:256.37,258.3 1 1 -github.com/muety/wakapi/services/summary.go:262.30,263.48 1 1 -github.com/muety/wakapi/services/summary.go:263.48,264.41 1 1 -github.com/muety/wakapi/services/summary.go:267.4,268.29 2 1 -github.com/muety/wakapi/services/summary.go:264.41,266.5 1 1 -github.com/muety/wakapi/services/summary.go:274.29,275.18 1 1 -github.com/muety/wakapi/services/summary.go:275.18,277.4 1 1 -github.com/muety/wakapi/services/summary.go:283.97,284.24 1 1 -github.com/muety/wakapi/services/summary.go:288.2,304.30 5 1 -github.com/muety/wakapi/services/summary.go:335.2,338.26 3 1 -github.com/muety/wakapi/services/summary.go:284.24,286.3 1 0 -github.com/muety/wakapi/services/summary.go:304.30,306.41 2 1 -github.com/muety/wakapi/services/summary.go:311.3,311.38 1 1 -github.com/muety/wakapi/services/summary.go:315.3,315.37 1 1 -github.com/muety/wakapi/services/summary.go:319.3,319.34 1 1 -github.com/muety/wakapi/services/summary.go:323.3,332.25 9 1 -github.com/muety/wakapi/services/summary.go:306.41,308.12 2 1 -github.com/muety/wakapi/services/summary.go:311.38,313.4 1 0 -github.com/muety/wakapi/services/summary.go:315.37,317.4 1 1 -github.com/muety/wakapi/services/summary.go:319.34,321.4 1 1 -github.com/muety/wakapi/services/summary.go:341.127,345.32 2 1 -github.com/muety/wakapi/services/summary.go:349.2,349.27 1 1 -github.com/muety/wakapi/services/summary.go:357.2,359.26 3 1 -github.com/muety/wakapi/services/summary.go:364.2,364.43 1 1 -github.com/muety/wakapi/services/summary.go:368.2,368.17 1 1 -github.com/muety/wakapi/services/summary.go:345.32,347.3 1 1 -github.com/muety/wakapi/services/summary.go:349.27,350.37 1 1 -github.com/muety/wakapi/services/summary.go:350.37,352.4 1 1 -github.com/muety/wakapi/services/summary.go:352.9,354.4 1 1 -github.com/muety/wakapi/services/summary.go:359.26,362.3 2 1 -github.com/muety/wakapi/services/summary.go:364.43,366.3 1 1 -github.com/muety/wakapi/services/summary.go:371.116,372.25 1 1 -github.com/muety/wakapi/services/summary.go:376.2,379.44 2 1 -github.com/muety/wakapi/services/summary.go:384.2,384.40 1 1 -github.com/muety/wakapi/services/summary.go:409.2,409.54 1 1 -github.com/muety/wakapi/services/summary.go:413.2,413.18 1 1 -github.com/muety/wakapi/services/summary.go:372.25,374.3 1 0 -github.com/muety/wakapi/services/summary.go:379.44,381.3 1 1 -github.com/muety/wakapi/services/summary.go:384.40,386.19 2 1 -github.com/muety/wakapi/services/summary.go:393.3,398.34 3 1 -github.com/muety/wakapi/services/summary.go:403.3,403.22 1 1 -github.com/muety/wakapi/services/summary.go:386.19,387.12 1 1 -github.com/muety/wakapi/services/summary.go:398.34,400.4 1 1 -github.com/muety/wakapi/services/summary.go:403.22,405.4 1 1 -github.com/muety/wakapi/services/summary.go:409.54,411.3 1 1 -github.com/muety/wakapi/services/summary.go:416.59,418.2 1 1 -github.com/muety/wakapi/services/summary.go:420.63,421.37 1 0 -github.com/muety/wakapi/services/summary.go:421.37,422.36 1 0 -github.com/muety/wakapi/services/summary.go:422.36,424.4 1 0 -github.com/muety/wakapi/services/summary.go:428.85,429.40 1 1 -github.com/muety/wakapi/services/summary.go:429.40,432.3 2 1 -github.com/muety/wakapi/services/summary.go:435.99,436.42 1 1 -github.com/muety/wakapi/services/summary.go:436.42,438.17 2 1 -github.com/muety/wakapi/services/summary.go:441.3,442.29 2 1 -github.com/muety/wakapi/services/summary.go:445.3,445.22 1 1 -github.com/muety/wakapi/services/summary.go:438.17,440.4 1 0 -github.com/muety/wakapi/services/summary.go:442.29,444.4 1 1 -github.com/muety/wakapi/services/summary.go:449.114,450.33 1 1 -github.com/muety/wakapi/services/summary.go:450.33,453.17 3 1 -github.com/muety/wakapi/services/summary.go:458.3,459.28 2 1 -github.com/muety/wakapi/services/summary.go:462.3,462.24 1 1 -github.com/muety/wakapi/services/summary.go:453.17,454.33 1 1 -github.com/muety/wakapi/services/summary.go:454.33,456.5 1 1 -github.com/muety/wakapi/services/summary.go:459.28,461.4 1 1 -github.com/muety/wakapi/services/aggregation.go:30.142,38.2 1 0 -github.com/muety/wakapi/services/aggregation.go:47.43,49.64 1 0 -github.com/muety/wakapi/services/aggregation.go:53.2,55.19 3 0 -github.com/muety/wakapi/services/aggregation.go:49.64,51.3 1 0 -github.com/muety/wakapi/services/aggregation.go:58.77,59.47 1 0 -github.com/muety/wakapi/services/aggregation.go:62.2,67.40 4 0 -github.com/muety/wakapi/services/aggregation.go:71.2,71.50 1 0 -github.com/muety/wakapi/services/aggregation.go:76.2,76.60 1 0 -github.com/muety/wakapi/services/aggregation.go:82.2,82.35 1 0 -github.com/muety/wakapi/services/aggregation.go:59.47,61.3 1 0 -github.com/muety/wakapi/services/aggregation.go:67.40,69.3 1 0 -github.com/muety/wakapi/services/aggregation.go:71.50,73.3 1 0 -github.com/muety/wakapi/services/aggregation.go:76.60,80.3 3 0 -github.com/muety/wakapi/services/aggregation.go:85.109,86.24 1 0 -github.com/muety/wakapi/services/aggregation.go:86.24,87.116 1 0 -github.com/muety/wakapi/services/aggregation.go:87.116,89.4 1 0 -github.com/muety/wakapi/services/aggregation.go:89.9,92.4 2 0 -github.com/muety/wakapi/services/aggregation.go:96.80,97.33 1 0 -github.com/muety/wakapi/services/aggregation.go:97.33,98.60 1 0 -github.com/muety/wakapi/services/aggregation.go:98.60,100.4 1 0 -github.com/muety/wakapi/services/aggregation.go:104.110,109.16 3 0 -github.com/muety/wakapi/services/aggregation.go:115.2,116.16 2 0 -github.com/muety/wakapi/services/aggregation.go:122.2,123.44 2 0 -github.com/muety/wakapi/services/aggregation.go:128.2,128.41 1 0 -github.com/muety/wakapi/services/aggregation.go:146.2,146.12 1 0 -github.com/muety/wakapi/services/aggregation.go:109.16,112.3 2 0 -github.com/muety/wakapi/services/aggregation.go:116.16,119.3 2 0 -github.com/muety/wakapi/services/aggregation.go:123.44,125.3 1 0 -github.com/muety/wakapi/services/aggregation.go:128.41,129.71 1 0 -github.com/muety/wakapi/services/aggregation.go:133.3,133.21 1 0 -github.com/muety/wakapi/services/aggregation.go:129.71,130.12 1 0 -github.com/muety/wakapi/services/aggregation.go:133.21,137.4 1 0 -github.com/muety/wakapi/services/aggregation.go:137.9,137.62 1 0 -github.com/muety/wakapi/services/aggregation.go:137.62,141.4 1 0 -github.com/muety/wakapi/services/aggregation.go:149.83,152.27 3 0 -github.com/muety/wakapi/services/aggregation.go:157.2,158.12 2 0 -github.com/muety/wakapi/services/aggregation.go:152.27,153.34 1 0 -github.com/muety/wakapi/services/aggregation.go:153.34,155.4 1 0 -github.com/muety/wakapi/services/aggregation.go:161.79,164.27 3 0 -github.com/muety/wakapi/services/aggregation.go:164.27,166.3 1 0 -github.com/muety/wakapi/services/aggregation.go:169.83,184.41 5 0 -github.com/muety/wakapi/services/aggregation.go:184.41,194.3 3 0 -github.com/muety/wakapi/services/aggregation.go:197.34,200.2 2 0 +github.com/muety/wakapi/routes/compat/shields/v1/badge.go:25.112,32.2 1 0 +github.com/muety/wakapi/routes/compat/shields/v1/badge.go:34.59,38.2 2 0 +github.com/muety/wakapi/routes/compat/shields/v1/badge.go:50.68,52.16 2 0 +github.com/muety/wakapi/routes/compat/shields/v1/badge.go:57.2,58.16 2 0 +github.com/muety/wakapi/routes/compat/shields/v1/badge.go:64.2,65.50 2 0 +github.com/muety/wakapi/routes/compat/shields/v1/badge.go:70.2,78.16 3 0 +github.com/muety/wakapi/routes/compat/shields/v1/badge.go:84.2,86.44 3 0 +github.com/muety/wakapi/routes/compat/shields/v1/badge.go:52.16,55.3 2 0 +github.com/muety/wakapi/routes/compat/shields/v1/badge.go:58.16,62.3 3 0 +github.com/muety/wakapi/routes/compat/shields/v1/badge.go:65.50,68.3 2 0 +github.com/muety/wakapi/routes/compat/shields/v1/badge.go:78.16,82.3 3 0 +github.com/muety/wakapi/routes/compat/shields/v1/badge.go:89.144,91.16 2 0 +github.com/muety/wakapi/routes/compat/shields/v1/badge.go:95.2,102.29 3 0 +github.com/muety/wakapi/routes/compat/shields/v1/badge.go:106.2,114.16 2 0 +github.com/muety/wakapi/routes/compat/shields/v1/badge.go:118.2,118.36 1 0 +github.com/muety/wakapi/routes/compat/shields/v1/badge.go:91.16,93.3 1 0 +github.com/muety/wakapi/routes/compat/shields/v1/badge.go:102.29,104.3 1 0 +github.com/muety/wakapi/routes/compat/shields/v1/badge.go:114.16,116.3 1 0 github.com/muety/wakapi/services/heartbeat.go:26.141,40.33 3 0 github.com/muety/wakapi/services/heartbeat.go:48.2,48.12 1 0 github.com/muety/wakapi/services/heartbeat.go:40.33,41.31 1 0 @@ -1119,25 +778,27 @@ github.com/muety/wakapi/services/heartbeat.go:255.94,257.42 2 0 github.com/muety/wakapi/services/heartbeat.go:263.2,263.18 1 0 github.com/muety/wakapi/services/heartbeat.go:257.42,259.18 2 0 github.com/muety/wakapi/services/heartbeat.go:259.18,261.4 1 0 -github.com/muety/wakapi/services/language_mapping.go:18.118,24.2 1 0 -github.com/muety/wakapi/services/language_mapping.go:26.86,28.2 1 0 -github.com/muety/wakapi/services/language_mapping.go:30.96,31.53 1 0 -github.com/muety/wakapi/services/language_mapping.go:35.2,36.16 2 0 -github.com/muety/wakapi/services/language_mapping.go:39.2,40.22 2 0 -github.com/muety/wakapi/services/language_mapping.go:31.53,33.3 1 0 -github.com/muety/wakapi/services/language_mapping.go:36.16,38.3 1 0 -github.com/muety/wakapi/services/language_mapping.go:43.92,46.16 3 0 -github.com/muety/wakapi/services/language_mapping.go:50.2,50.33 1 0 -github.com/muety/wakapi/services/language_mapping.go:53.2,53.22 1 0 -github.com/muety/wakapi/services/language_mapping.go:46.16,48.3 1 0 -github.com/muety/wakapi/services/language_mapping.go:50.33,52.3 1 0 -github.com/muety/wakapi/services/language_mapping.go:56.109,58.16 2 0 -github.com/muety/wakapi/services/language_mapping.go:62.2,63.20 2 0 -github.com/muety/wakapi/services/language_mapping.go:58.16,60.3 1 0 -github.com/muety/wakapi/services/language_mapping.go:66.82,67.26 1 0 -github.com/muety/wakapi/services/language_mapping.go:70.2,72.12 3 0 -github.com/muety/wakapi/services/language_mapping.go:67.26,69.3 1 0 -github.com/muety/wakapi/services/language_mapping.go:75.74,78.2 1 0 +github.com/muety/wakapi/services/misc.go:21.126,28.2 1 0 +github.com/muety/wakapi/services/misc.go:40.50,42.48 1 0 +github.com/muety/wakapi/services/misc.go:46.2,48.19 3 0 +github.com/muety/wakapi/services/misc.go:42.48,44.3 1 0 +github.com/muety/wakapi/services/misc.go:51.51,53.16 2 0 +github.com/muety/wakapi/services/misc.go:57.2,60.26 3 0 +github.com/muety/wakapi/services/misc.go:66.2,68.40 2 0 +github.com/muety/wakapi/services/misc.go:73.2,75.33 3 0 +github.com/muety/wakapi/services/misc.go:79.2,84.17 2 0 +github.com/muety/wakapi/services/misc.go:88.2,91.17 1 0 +github.com/muety/wakapi/services/misc.go:95.2,95.12 1 0 +github.com/muety/wakapi/services/misc.go:53.16,55.3 1 0 +github.com/muety/wakapi/services/misc.go:60.26,65.3 1 0 +github.com/muety/wakapi/services/misc.go:68.40,70.3 1 0 +github.com/muety/wakapi/services/misc.go:75.33,78.3 2 0 +github.com/muety/wakapi/services/misc.go:84.17,86.3 1 0 +github.com/muety/wakapi/services/misc.go:91.17,93.3 1 0 +github.com/muety/wakapi/services/misc.go:98.116,99.24 1 0 +github.com/muety/wakapi/services/misc.go:99.24,100.156 1 0 +github.com/muety/wakapi/services/misc.go:100.156,102.4 1 0 +github.com/muety/wakapi/services/misc.go:102.9,107.4 1 0 github.com/muety/wakapi/services/report.go:30.122,44.33 4 0 github.com/muety/wakapi/services/report.go:50.2,50.12 1 0 github.com/muety/wakapi/services/report.go:44.33,45.31 1 0 @@ -1167,56 +828,371 @@ github.com/muety/wakapi/services/report.go:145.2,145.12 1 0 github.com/muety/wakapi/services/report.go:138.41,139.30 1 0 github.com/muety/wakapi/services/report.go:139.30,140.16 1 0 github.com/muety/wakapi/services/report.go:140.16,142.5 1 0 -github.com/muety/wakapi/services/user.go:24.99,34.33 3 0 -github.com/muety/wakapi/services/user.go:55.2,55.12 1 0 -github.com/muety/wakapi/services/user.go:34.33,35.31 1 0 -github.com/muety/wakapi/services/user.go:35.31,41.73 4 0 -github.com/muety/wakapi/services/user.go:45.4,45.24 1 0 -github.com/muety/wakapi/services/user.go:41.73,43.5 1 0 -github.com/muety/wakapi/services/user.go:45.24,46.80 1 0 -github.com/muety/wakapi/services/user.go:46.80,48.6 1 0 -github.com/muety/wakapi/services/user.go:48.11,50.6 1 0 -github.com/muety/wakapi/services/user.go:58.74,59.40 1 0 -github.com/muety/wakapi/services/user.go:63.2,64.16 2 0 -github.com/muety/wakapi/services/user.go:68.2,69.15 2 0 -github.com/muety/wakapi/services/user.go:59.40,61.3 1 0 -github.com/muety/wakapi/services/user.go:64.16,66.3 1 0 -github.com/muety/wakapi/services/user.go:72.72,73.37 1 0 -github.com/muety/wakapi/services/user.go:77.2,78.16 2 0 -github.com/muety/wakapi/services/user.go:82.2,83.15 2 0 -github.com/muety/wakapi/services/user.go:73.37,75.3 1 0 -github.com/muety/wakapi/services/user.go:78.16,80.3 1 0 -github.com/muety/wakapi/services/user.go:86.76,88.2 1 0 -github.com/muety/wakapi/services/user.go:90.86,92.2 1 0 -github.com/muety/wakapi/services/user.go:94.58,96.2 1 0 -github.com/muety/wakapi/services/user.go:98.86,100.2 1 0 -github.com/muety/wakapi/services/user.go:102.71,104.12 2 0 -github.com/muety/wakapi/services/user.go:108.2,109.42 2 0 -github.com/muety/wakapi/services/user.go:113.2,114.16 2 0 -github.com/muety/wakapi/services/user.go:118.2,119.21 2 0 -github.com/muety/wakapi/services/user.go:104.12,106.3 1 0 -github.com/muety/wakapi/services/user.go:109.42,111.3 1 0 -github.com/muety/wakapi/services/user.go:114.16,116.3 1 0 -github.com/muety/wakapi/services/user.go:122.48,124.2 1 0 -github.com/muety/wakapi/services/user.go:126.102,136.93 2 0 -github.com/muety/wakapi/services/user.go:142.2,142.38 1 0 -github.com/muety/wakapi/services/user.go:136.93,138.3 1 0 -github.com/muety/wakapi/services/user.go:138.8,140.3 1 0 -github.com/muety/wakapi/services/user.go:145.73,149.2 3 0 -github.com/muety/wakapi/services/user.go:151.78,155.2 3 0 -github.com/muety/wakapi/services/user.go:157.122,160.35 2 0 -github.com/muety/wakapi/services/user.go:166.2,166.35 1 0 -github.com/muety/wakapi/services/user.go:170.2,170.18 1 0 -github.com/muety/wakapi/services/user.go:160.35,161.89 1 0 -github.com/muety/wakapi/services/user.go:161.89,163.4 1 0 -github.com/muety/wakapi/services/user.go:166.35,168.3 1 0 -github.com/muety/wakapi/services/user.go:173.106,176.96 3 0 -github.com/muety/wakapi/services/user.go:181.2,181.68 1 0 -github.com/muety/wakapi/services/user.go:176.96,178.3 1 0 -github.com/muety/wakapi/services/user.go:178.8,180.3 1 0 -github.com/muety/wakapi/services/user.go:184.85,186.2 1 0 -github.com/muety/wakapi/services/user.go:188.57,195.2 4 0 -github.com/muety/wakapi/services/user.go:197.38,199.2 1 0 -github.com/muety/wakapi/services/user.go:201.57,206.2 1 0 +github.com/muety/wakapi/services/user.go:25.99,35.33 3 0 +github.com/muety/wakapi/services/user.go:56.2,56.12 1 0 +github.com/muety/wakapi/services/user.go:35.33,36.31 1 0 +github.com/muety/wakapi/services/user.go:36.31,42.73 4 0 +github.com/muety/wakapi/services/user.go:46.4,46.24 1 0 +github.com/muety/wakapi/services/user.go:42.73,44.5 1 0 +github.com/muety/wakapi/services/user.go:46.24,47.80 1 0 +github.com/muety/wakapi/services/user.go:47.80,49.6 1 0 +github.com/muety/wakapi/services/user.go:49.11,51.6 1 0 +github.com/muety/wakapi/services/user.go:59.74,60.40 1 0 +github.com/muety/wakapi/services/user.go:64.2,65.16 2 0 +github.com/muety/wakapi/services/user.go:69.2,70.15 2 0 +github.com/muety/wakapi/services/user.go:60.40,62.3 1 0 +github.com/muety/wakapi/services/user.go:65.16,67.3 1 0 +github.com/muety/wakapi/services/user.go:73.72,74.37 1 0 +github.com/muety/wakapi/services/user.go:78.2,79.16 2 0 +github.com/muety/wakapi/services/user.go:83.2,84.15 2 0 +github.com/muety/wakapi/services/user.go:74.37,76.3 1 0 +github.com/muety/wakapi/services/user.go:79.16,81.3 1 0 +github.com/muety/wakapi/services/user.go:87.76,89.2 1 0 +github.com/muety/wakapi/services/user.go:91.86,93.2 1 0 +github.com/muety/wakapi/services/user.go:95.58,97.2 1 0 +github.com/muety/wakapi/services/user.go:99.86,101.2 1 0 +github.com/muety/wakapi/services/user.go:103.71,105.12 2 0 +github.com/muety/wakapi/services/user.go:109.2,110.42 2 0 +github.com/muety/wakapi/services/user.go:114.2,115.16 2 0 +github.com/muety/wakapi/services/user.go:119.2,120.21 2 0 +github.com/muety/wakapi/services/user.go:105.12,107.3 1 0 +github.com/muety/wakapi/services/user.go:110.42,112.3 1 0 +github.com/muety/wakapi/services/user.go:115.16,117.3 1 0 +github.com/muety/wakapi/services/user.go:123.48,125.2 1 0 +github.com/muety/wakapi/services/user.go:127.102,137.93 2 0 +github.com/muety/wakapi/services/user.go:143.2,143.38 1 0 +github.com/muety/wakapi/services/user.go:137.93,139.3 1 0 +github.com/muety/wakapi/services/user.go:139.8,141.3 1 0 +github.com/muety/wakapi/services/user.go:146.73,150.2 3 0 +github.com/muety/wakapi/services/user.go:152.78,156.2 3 0 +github.com/muety/wakapi/services/user.go:158.122,161.35 2 0 +github.com/muety/wakapi/services/user.go:167.2,167.35 1 0 +github.com/muety/wakapi/services/user.go:171.2,171.18 1 0 +github.com/muety/wakapi/services/user.go:161.35,162.89 1 0 +github.com/muety/wakapi/services/user.go:162.89,164.4 1 0 +github.com/muety/wakapi/services/user.go:167.35,169.3 1 0 +github.com/muety/wakapi/services/user.go:174.106,177.96 3 0 +github.com/muety/wakapi/services/user.go:182.2,182.68 1 0 +github.com/muety/wakapi/services/user.go:177.96,179.3 1 0 +github.com/muety/wakapi/services/user.go:179.8,181.3 1 0 +github.com/muety/wakapi/services/user.go:185.85,187.2 1 0 +github.com/muety/wakapi/services/user.go:189.57,196.2 4 0 +github.com/muety/wakapi/services/user.go:198.38,200.2 1 0 +github.com/muety/wakapi/services/user.go:202.57,207.2 1 0 +github.com/muety/wakapi/services/duration.go:16.78,22.2 2 1 +github.com/muety/wakapi/services/duration.go:24.123,27.42 2 1 +github.com/muety/wakapi/services/duration.go:33.2,34.16 2 1 +github.com/muety/wakapi/services/duration.go:41.2,46.31 4 1 +github.com/muety/wakapi/services/duration.go:81.2,83.31 2 1 +github.com/muety/wakapi/services/duration.go:96.2,96.49 1 1 +github.com/muety/wakapi/services/duration.go:100.2,100.32 1 1 +github.com/muety/wakapi/services/duration.go:27.42,28.90 1 1 +github.com/muety/wakapi/services/duration.go:28.90,30.4 1 1 +github.com/muety/wakapi/services/duration.go:34.16,36.3 1 0 +github.com/muety/wakapi/services/duration.go:46.31,47.42 1 1 +github.com/muety/wakapi/services/duration.go:51.3,53.62 2 1 +github.com/muety/wakapi/services/duration.go:57.3,57.20 1 1 +github.com/muety/wakapi/services/duration.go:62.3,63.35 2 1 +github.com/muety/wakapi/services/duration.go:66.3,68.72 2 1 +github.com/muety/wakapi/services/duration.go:78.3,78.10 1 1 +github.com/muety/wakapi/services/duration.go:47.42,48.12 1 1 +github.com/muety/wakapi/services/duration.go:53.62,55.4 1 1 +github.com/muety/wakapi/services/duration.go:57.20,59.12 2 1 +github.com/muety/wakapi/services/duration.go:63.35,65.4 1 1 +github.com/muety/wakapi/services/duration.go:68.72,70.41 2 1 +github.com/muety/wakapi/services/duration.go:73.4,73.15 1 1 +github.com/muety/wakapi/services/duration.go:70.41,72.5 1 1 +github.com/muety/wakapi/services/duration.go:74.9,76.4 1 1 +github.com/muety/wakapi/services/duration.go:83.31,84.26 1 1 +github.com/muety/wakapi/services/duration.go:84.26,89.23 1 1 +github.com/muety/wakapi/services/duration.go:92.4,92.36 1 1 +github.com/muety/wakapi/services/duration.go:89.23,91.5 1 1 +github.com/muety/wakapi/services/duration.go:96.49,98.3 1 1 +github.com/muety/wakapi/services/alias.go:19.77,24.2 1 1 +github.com/muety/wakapi/services/alias.go:28.60,29.43 1 1 +github.com/muety/wakapi/services/alias.go:32.2,32.14 1 1 +github.com/muety/wakapi/services/alias.go:29.43,31.3 1 1 +github.com/muety/wakapi/services/alias.go:35.62,37.16 2 1 +github.com/muety/wakapi/services/alias.go:40.2,40.12 1 1 +github.com/muety/wakapi/services/alias.go:37.16,39.3 1 1 +github.com/muety/wakapi/services/alias.go:43.59,44.51 1 1 +github.com/muety/wakapi/services/alias.go:44.51,46.3 1 0 +github.com/muety/wakapi/services/alias.go:49.76,50.32 1 0 +github.com/muety/wakapi/services/alias.go:53.2,53.49 1 0 +github.com/muety/wakapi/services/alias.go:50.32,52.3 1 0 +github.com/muety/wakapi/services/alias.go:53.49,55.3 1 0 +github.com/muety/wakapi/services/alias.go:55.8,57.3 1 0 +github.com/muety/wakapi/services/alias.go:60.102,61.38 1 0 +github.com/muety/wakapi/services/alias.go:64.2,64.39 1 0 +github.com/muety/wakapi/services/alias.go:61.38,63.3 1 0 +github.com/muety/wakapi/services/alias.go:67.113,68.38 1 0 +github.com/muety/wakapi/services/alias.go:71.2,71.39 1 0 +github.com/muety/wakapi/services/alias.go:68.38,70.3 1 0 +github.com/muety/wakapi/services/alias.go:74.108,75.32 1 1 +github.com/muety/wakapi/services/alias.go:79.2,79.49 1 1 +github.com/muety/wakapi/services/alias.go:87.2,87.19 1 1 +github.com/muety/wakapi/services/alias.go:75.32,77.3 1 1 +github.com/muety/wakapi/services/alias.go:79.49,80.47 1 1 +github.com/muety/wakapi/services/alias.go:80.47,81.49 1 1 +github.com/muety/wakapi/services/alias.go:81.49,83.5 1 1 +github.com/muety/wakapi/services/alias.go:90.77,92.16 2 0 +github.com/muety/wakapi/services/alias.go:96.2,100.20 3 0 +github.com/muety/wakapi/services/alias.go:92.16,94.3 1 0 +github.com/muety/wakapi/services/alias.go:103.60,104.24 1 0 +github.com/muety/wakapi/services/alias.go:107.2,110.16 2 0 +github.com/muety/wakapi/services/alias.go:114.2,116.12 2 0 +github.com/muety/wakapi/services/alias.go:104.24,106.3 1 0 +github.com/muety/wakapi/services/alias.go:110.16,112.3 1 0 +github.com/muety/wakapi/services/alias.go:119.69,123.28 3 0 +github.com/muety/wakapi/services/alias.go:131.2,134.16 2 0 +github.com/muety/wakapi/services/alias.go:140.2,140.31 1 0 +github.com/muety/wakapi/services/alias.go:144.2,144.12 1 0 +github.com/muety/wakapi/services/alias.go:123.28,124.21 1 0 +github.com/muety/wakapi/services/alias.go:127.3,128.16 2 0 +github.com/muety/wakapi/services/alias.go:124.21,126.4 1 0 +github.com/muety/wakapi/services/alias.go:134.16,135.29 1 0 +github.com/muety/wakapi/services/alias.go:135.29,137.4 1 0 +github.com/muety/wakapi/services/alias.go:140.31,142.3 1 0 +github.com/muety/wakapi/services/alias.go:147.74,148.14 1 0 +github.com/muety/wakapi/services/alias.go:148.14,149.57 1 0 +github.com/muety/wakapi/services/alias.go:149.57,153.4 3 0 +github.com/muety/wakapi/services/alias.go:154.8,155.57 1 0 +github.com/muety/wakapi/services/alias.go:155.57,157.48 2 0 +github.com/muety/wakapi/services/alias.go:162.4,162.52 1 0 +github.com/muety/wakapi/services/alias.go:157.48,158.26 1 0 +github.com/muety/wakapi/services/alias.go:158.26,160.6 1 0 +github.com/muety/wakapi/services/alias.go:167.116,168.32 1 0 +github.com/muety/wakapi/services/alias.go:171.2,171.49 1 0 +github.com/muety/wakapi/services/alias.go:168.32,170.3 1 0 +github.com/muety/wakapi/services/alias.go:171.49,173.47 2 0 +github.com/muety/wakapi/services/alias.go:178.3,178.30 1 0 +github.com/muety/wakapi/services/alias.go:173.47,174.16 1 0 +github.com/muety/wakapi/services/alias.go:174.16,176.5 1 0 +github.com/muety/wakapi/services/alias.go:179.8,181.3 1 0 github.com/muety/wakapi/services/diagnostics.go:14.101,19.2 1 0 github.com/muety/wakapi/services/diagnostics.go:21.101,23.2 1 0 +github.com/muety/wakapi/services/key_value.go:14.89,19.2 1 0 +github.com/muety/wakapi/services/key_value.go:21.83,23.2 1 0 +github.com/muety/wakapi/services/key_value.go:25.78,27.16 2 0 +github.com/muety/wakapi/services/key_value.go:33.2,33.11 1 0 +github.com/muety/wakapi/services/key_value.go:27.16,32.3 1 0 +github.com/muety/wakapi/services/key_value.go:36.72,38.2 1 0 +github.com/muety/wakapi/services/key_value.go:40.60,42.2 1 0 +github.com/muety/wakapi/services/language_mapping.go:18.118,24.2 1 0 +github.com/muety/wakapi/services/language_mapping.go:26.86,28.2 1 0 +github.com/muety/wakapi/services/language_mapping.go:30.96,31.53 1 0 +github.com/muety/wakapi/services/language_mapping.go:35.2,36.16 2 0 +github.com/muety/wakapi/services/language_mapping.go:39.2,40.22 2 0 +github.com/muety/wakapi/services/language_mapping.go:31.53,33.3 1 0 +github.com/muety/wakapi/services/language_mapping.go:36.16,38.3 1 0 +github.com/muety/wakapi/services/language_mapping.go:43.92,46.16 3 0 +github.com/muety/wakapi/services/language_mapping.go:50.2,50.33 1 0 +github.com/muety/wakapi/services/language_mapping.go:53.2,53.22 1 0 +github.com/muety/wakapi/services/language_mapping.go:46.16,48.3 1 0 +github.com/muety/wakapi/services/language_mapping.go:50.33,52.3 1 0 +github.com/muety/wakapi/services/language_mapping.go:56.109,58.16 2 0 +github.com/muety/wakapi/services/language_mapping.go:62.2,63.20 2 0 +github.com/muety/wakapi/services/language_mapping.go:58.16,60.3 1 0 +github.com/muety/wakapi/services/language_mapping.go:66.82,67.26 1 0 +github.com/muety/wakapi/services/language_mapping.go:70.2,72.12 3 0 +github.com/muety/wakapi/services/language_mapping.go:67.26,69.3 1 0 +github.com/muety/wakapi/services/language_mapping.go:75.74,78.2 1 0 +github.com/muety/wakapi/services/project_label.go:21.111,28.2 1 0 +github.com/muety/wakapi/services/project_label.go:30.80,32.2 1 0 +github.com/muety/wakapi/services/project_label.go:34.90,35.51 1 0 +github.com/muety/wakapi/services/project_label.go:39.2,40.16 2 0 +github.com/muety/wakapi/services/project_label.go:43.2,44.20 2 0 +github.com/muety/wakapi/services/project_label.go:35.51,37.3 1 0 +github.com/muety/wakapi/services/project_label.go:40.16,42.3 1 0 +github.com/muety/wakapi/services/project_label.go:48.108,50.16 2 0 +github.com/muety/wakapi/services/project_label.go:53.2,53.112 1 0 +github.com/muety/wakapi/services/project_label.go:56.2,56.26 1 0 +github.com/muety/wakapi/services/project_label.go:50.16,52.3 1 0 +github.com/muety/wakapi/services/project_label.go:53.112,55.3 1 0 +github.com/muety/wakapi/services/project_label.go:60.116,62.16 2 0 +github.com/muety/wakapi/services/project_label.go:65.2,65.112 1 0 +github.com/muety/wakapi/services/project_label.go:68.2,68.26 1 0 +github.com/muety/wakapi/services/project_label.go:62.16,64.3 1 0 +github.com/muety/wakapi/services/project_label.go:65.112,67.3 1 0 +github.com/muety/wakapi/services/project_label.go:71.98,73.16 2 0 +github.com/muety/wakapi/services/project_label.go:77.2,79.20 3 0 +github.com/muety/wakapi/services/project_label.go:73.16,75.3 1 0 +github.com/muety/wakapi/services/project_label.go:82.74,83.24 1 0 +github.com/muety/wakapi/services/project_label.go:86.2,89.12 4 0 +github.com/muety/wakapi/services/project_label.go:83.24,85.3 1 0 +github.com/muety/wakapi/services/project_label.go:92.89,94.14 2 0 +github.com/muety/wakapi/services/project_label.go:97.2,100.4 1 0 +github.com/muety/wakapi/services/project_label.go:94.14,96.3 1 0 +github.com/muety/wakapi/services/summary.go:30.189,42.33 3 1 +github.com/muety/wakapi/services/summary.go:53.2,53.12 1 1 +github.com/muety/wakapi/services/summary.go:42.33,43.31 1 1 +github.com/muety/wakapi/services/summary.go:43.31,45.39 2 0 +github.com/muety/wakapi/services/summary.go:45.39,46.71 1 0 +github.com/muety/wakapi/services/summary.go:46.71,48.6 1 0 +github.com/muety/wakapi/services/summary.go:59.161,62.66 2 1 +github.com/muety/wakapi/services/summary.go:67.2,72.20 4 1 +github.com/muety/wakapi/services/summary.go:78.2,78.65 1 1 +github.com/muety/wakapi/services/summary.go:83.2,84.16 2 1 +github.com/muety/wakapi/services/summary.go:89.2,94.105 5 1 +github.com/muety/wakapi/services/summary.go:98.2,99.30 2 1 +github.com/muety/wakapi/services/summary.go:62.66,64.3 1 0 +github.com/muety/wakapi/services/summary.go:72.20,75.3 2 1 +github.com/muety/wakapi/services/summary.go:78.65,80.3 1 0 +github.com/muety/wakapi/services/summary.go:84.16,86.3 1 0 +github.com/muety/wakapi/services/summary.go:94.105,96.3 1 1 +github.com/muety/wakapi/services/summary.go:102.126,106.41 2 1 +github.com/muety/wakapi/services/summary.go:117.2,118.44 2 1 +github.com/muety/wakapi/services/summary.go:133.2,134.16 2 1 +github.com/muety/wakapi/services/summary.go:138.2,138.30 1 1 +github.com/muety/wakapi/services/summary.go:106.41,109.17 2 1 +github.com/muety/wakapi/services/summary.go:109.17,111.4 1 1 +github.com/muety/wakapi/services/summary.go:111.9,113.4 1 0 +github.com/muety/wakapi/services/summary.go:118.44,119.87 1 1 +github.com/muety/wakapi/services/summary.go:119.87,120.71 1 1 +github.com/muety/wakapi/services/summary.go:126.4,126.36 1 1 +github.com/muety/wakapi/services/summary.go:120.71,124.13 1 0 +github.com/muety/wakapi/services/summary.go:127.9,129.4 1 0 +github.com/muety/wakapi/services/summary.go:134.16,136.3 1 0 +github.com/muety/wakapi/services/summary.go:141.127,144.16 2 1 +github.com/muety/wakapi/services/summary.go:148.2,149.74 2 1 +github.com/muety/wakapi/services/summary.go:153.2,155.26 3 1 +github.com/muety/wakapi/services/summary.go:160.2,167.34 7 1 +github.com/muety/wakapi/services/summary.go:185.2,185.25 1 1 +github.com/muety/wakapi/services/summary.go:190.2,203.30 2 1 +github.com/muety/wakapi/services/summary.go:144.16,146.3 1 0 +github.com/muety/wakapi/services/summary.go:149.74,151.3 1 1 +github.com/muety/wakapi/services/summary.go:155.26,157.3 1 1 +github.com/muety/wakapi/services/summary.go:167.34,169.20 2 1 +github.com/muety/wakapi/services/summary.go:170.30,171.29 1 1 +github.com/muety/wakapi/services/summary.go:172.31,173.30 1 1 +github.com/muety/wakapi/services/summary.go:174.29,175.28 1 1 +github.com/muety/wakapi/services/summary.go:176.25,177.24 1 1 +github.com/muety/wakapi/services/summary.go:178.30,179.29 1 1 +github.com/muety/wakapi/services/summary.go:180.29,181.28 1 1 +github.com/muety/wakapi/services/summary.go:185.25,188.3 2 1 +github.com/muety/wakapi/services/summary.go:208.76,210.2 1 0 +github.com/muety/wakapi/services/summary.go:212.62,215.2 2 0 +github.com/muety/wakapi/services/summary.go:217.66,220.2 2 0 +github.com/muety/wakapi/services/summary.go:224.125,227.30 2 1 +github.com/muety/wakapi/services/summary.go:231.2,232.28 2 1 +github.com/muety/wakapi/services/summary.go:240.2,240.40 1 1 +github.com/muety/wakapi/services/summary.go:244.2,244.67 1 1 +github.com/muety/wakapi/services/summary.go:227.30,229.3 1 1 +github.com/muety/wakapi/services/summary.go:232.28,238.3 1 1 +github.com/muety/wakapi/services/summary.go:240.40,242.3 1 1 +github.com/muety/wakapi/services/summary.go:247.87,248.72 1 1 +github.com/muety/wakapi/services/summary.go:256.2,257.16 2 1 +github.com/muety/wakapi/services/summary.go:262.2,263.37 2 1 +github.com/muety/wakapi/services/summary.go:267.2,269.30 3 1 +github.com/muety/wakapi/services/summary.go:280.2,281.29 2 1 +github.com/muety/wakapi/services/summary.go:286.2,287.16 2 1 +github.com/muety/wakapi/services/summary.go:248.72,254.3 1 1 +github.com/muety/wakapi/services/summary.go:257.16,260.3 2 0 +github.com/muety/wakapi/services/summary.go:263.37,265.3 1 1 +github.com/muety/wakapi/services/summary.go:269.30,270.48 1 1 +github.com/muety/wakapi/services/summary.go:270.48,271.41 1 1 +github.com/muety/wakapi/services/summary.go:274.4,275.29 2 1 +github.com/muety/wakapi/services/summary.go:271.41,273.5 1 1 +github.com/muety/wakapi/services/summary.go:281.29,282.18 1 1 +github.com/muety/wakapi/services/summary.go:282.18,284.4 1 1 +github.com/muety/wakapi/services/summary.go:290.97,291.24 1 1 +github.com/muety/wakapi/services/summary.go:295.2,311.30 5 1 +github.com/muety/wakapi/services/summary.go:342.2,345.26 3 1 +github.com/muety/wakapi/services/summary.go:291.24,293.3 1 0 +github.com/muety/wakapi/services/summary.go:311.30,313.41 2 1 +github.com/muety/wakapi/services/summary.go:318.3,318.38 1 1 +github.com/muety/wakapi/services/summary.go:322.3,322.37 1 1 +github.com/muety/wakapi/services/summary.go:326.3,326.34 1 1 +github.com/muety/wakapi/services/summary.go:330.3,339.25 9 1 +github.com/muety/wakapi/services/summary.go:313.41,315.12 2 1 +github.com/muety/wakapi/services/summary.go:318.38,320.4 1 0 +github.com/muety/wakapi/services/summary.go:322.37,324.4 1 1 +github.com/muety/wakapi/services/summary.go:326.34,328.4 1 1 +github.com/muety/wakapi/services/summary.go:348.127,352.32 2 1 +github.com/muety/wakapi/services/summary.go:356.2,356.27 1 1 +github.com/muety/wakapi/services/summary.go:364.2,366.26 3 1 +github.com/muety/wakapi/services/summary.go:371.2,371.43 1 1 +github.com/muety/wakapi/services/summary.go:375.2,375.17 1 1 +github.com/muety/wakapi/services/summary.go:352.32,354.3 1 1 +github.com/muety/wakapi/services/summary.go:356.27,357.37 1 1 +github.com/muety/wakapi/services/summary.go:357.37,359.4 1 1 +github.com/muety/wakapi/services/summary.go:359.9,361.4 1 1 +github.com/muety/wakapi/services/summary.go:366.26,369.3 2 1 +github.com/muety/wakapi/services/summary.go:371.43,373.3 1 1 +github.com/muety/wakapi/services/summary.go:378.130,379.25 1 1 +github.com/muety/wakapi/services/summary.go:383.2,386.44 2 1 +github.com/muety/wakapi/services/summary.go:391.2,391.40 1 1 +github.com/muety/wakapi/services/summary.go:422.2,422.54 1 1 +github.com/muety/wakapi/services/summary.go:426.2,426.18 1 1 +github.com/muety/wakapi/services/summary.go:379.25,381.3 1 0 +github.com/muety/wakapi/services/summary.go:386.44,388.3 1 1 +github.com/muety/wakapi/services/summary.go:391.40,393.51 2 1 +github.com/muety/wakapi/services/summary.go:397.3,404.15 3 1 +github.com/muety/wakapi/services/summary.go:416.3,416.22 1 1 +github.com/muety/wakapi/services/summary.go:393.51,394.12 1 1 +github.com/muety/wakapi/services/summary.go:404.15,410.38 3 1 +github.com/muety/wakapi/services/summary.go:410.38,412.5 1 0 +github.com/muety/wakapi/services/summary.go:416.22,418.4 1 1 +github.com/muety/wakapi/services/summary.go:422.54,424.3 1 1 +github.com/muety/wakapi/services/summary.go:429.59,431.2 1 1 +github.com/muety/wakapi/services/summary.go:433.63,434.37 1 0 +github.com/muety/wakapi/services/summary.go:434.37,435.36 1 0 +github.com/muety/wakapi/services/summary.go:435.36,437.4 1 0 +github.com/muety/wakapi/services/summary.go:441.85,442.40 1 1 +github.com/muety/wakapi/services/summary.go:442.40,445.3 2 1 +github.com/muety/wakapi/services/summary.go:448.99,449.42 1 1 +github.com/muety/wakapi/services/summary.go:449.42,451.17 2 1 +github.com/muety/wakapi/services/summary.go:454.3,455.29 2 1 +github.com/muety/wakapi/services/summary.go:458.3,458.22 1 1 +github.com/muety/wakapi/services/summary.go:451.17,453.4 1 0 +github.com/muety/wakapi/services/summary.go:455.29,457.4 1 1 +github.com/muety/wakapi/services/summary.go:462.114,463.33 1 1 +github.com/muety/wakapi/services/summary.go:463.33,466.17 3 1 +github.com/muety/wakapi/services/summary.go:471.3,472.28 2 1 +github.com/muety/wakapi/services/summary.go:475.3,475.24 1 1 +github.com/muety/wakapi/services/summary.go:466.17,467.33 1 1 +github.com/muety/wakapi/services/summary.go:467.33,469.5 1 1 +github.com/muety/wakapi/services/summary.go:472.28,474.4 1 1 +github.com/muety/wakapi/services/aggregation.go:30.142,38.2 1 0 +github.com/muety/wakapi/services/aggregation.go:47.43,49.64 1 0 +github.com/muety/wakapi/services/aggregation.go:53.2,55.19 3 0 +github.com/muety/wakapi/services/aggregation.go:49.64,51.3 1 0 +github.com/muety/wakapi/services/aggregation.go:58.77,59.47 1 0 +github.com/muety/wakapi/services/aggregation.go:62.2,67.40 4 0 +github.com/muety/wakapi/services/aggregation.go:71.2,71.50 1 0 +github.com/muety/wakapi/services/aggregation.go:76.2,76.60 1 0 +github.com/muety/wakapi/services/aggregation.go:82.2,82.35 1 0 +github.com/muety/wakapi/services/aggregation.go:59.47,61.3 1 0 +github.com/muety/wakapi/services/aggregation.go:67.40,69.3 1 0 +github.com/muety/wakapi/services/aggregation.go:71.50,73.3 1 0 +github.com/muety/wakapi/services/aggregation.go:76.60,80.3 3 0 +github.com/muety/wakapi/services/aggregation.go:85.109,86.24 1 0 +github.com/muety/wakapi/services/aggregation.go:86.24,87.116 1 0 +github.com/muety/wakapi/services/aggregation.go:87.116,89.4 1 0 +github.com/muety/wakapi/services/aggregation.go:89.9,92.4 2 0 +github.com/muety/wakapi/services/aggregation.go:96.80,97.33 1 0 +github.com/muety/wakapi/services/aggregation.go:97.33,98.60 1 0 +github.com/muety/wakapi/services/aggregation.go:98.60,100.4 1 0 +github.com/muety/wakapi/services/aggregation.go:104.110,109.16 3 0 +github.com/muety/wakapi/services/aggregation.go:115.2,116.16 2 0 +github.com/muety/wakapi/services/aggregation.go:122.2,123.44 2 0 +github.com/muety/wakapi/services/aggregation.go:128.2,128.41 1 0 +github.com/muety/wakapi/services/aggregation.go:146.2,146.12 1 0 +github.com/muety/wakapi/services/aggregation.go:109.16,112.3 2 0 +github.com/muety/wakapi/services/aggregation.go:116.16,119.3 2 0 +github.com/muety/wakapi/services/aggregation.go:123.44,125.3 1 0 +github.com/muety/wakapi/services/aggregation.go:128.41,129.71 1 0 +github.com/muety/wakapi/services/aggregation.go:133.3,133.21 1 0 +github.com/muety/wakapi/services/aggregation.go:129.71,130.12 1 0 +github.com/muety/wakapi/services/aggregation.go:133.21,137.4 1 0 +github.com/muety/wakapi/services/aggregation.go:137.9,137.62 1 0 +github.com/muety/wakapi/services/aggregation.go:137.62,141.4 1 0 +github.com/muety/wakapi/services/aggregation.go:149.83,152.27 3 0 +github.com/muety/wakapi/services/aggregation.go:157.2,158.12 2 0 +github.com/muety/wakapi/services/aggregation.go:152.27,153.34 1 0 +github.com/muety/wakapi/services/aggregation.go:153.34,155.4 1 0 +github.com/muety/wakapi/services/aggregation.go:161.79,164.27 3 0 +github.com/muety/wakapi/services/aggregation.go:164.27,166.3 1 0 +github.com/muety/wakapi/services/aggregation.go:169.83,184.41 5 0 +github.com/muety/wakapi/services/aggregation.go:184.41,194.3 3 0 +github.com/muety/wakapi/services/aggregation.go:197.34,200.2 2 0 diff --git a/main.go b/main.go index fc8e950..c2a62c3 100644 --- a/main.go +++ b/main.go @@ -2,6 +2,7 @@ package main import ( "embed" + "github.com/muety/wakapi/migrations" "io/fs" "log" "net" @@ -16,7 +17,6 @@ import ( "github.com/emvi/logbuch" "github.com/gorilla/handlers" conf "github.com/muety/wakapi/config" - "github.com/muety/wakapi/migrations" "github.com/muety/wakapi/repositories" "github.com/muety/wakapi/routes/api" "github.com/muety/wakapi/services/mail" @@ -138,7 +138,9 @@ func main() { defer sqlDb.Close() // Migrate database schema - migrations.Run(db, config) + if !config.SkipMigrations { + migrations.Run(db, config) + } // Repositories aliasRepository = repositories.NewAliasRepository(db) diff --git a/routes/utils/badge_utils.go b/routes/utils/badge_utils.go index 7b36f74..7a82a81 100644 --- a/routes/utils/badge_utils.go +++ b/routes/utils/badge_utils.go @@ -74,6 +74,7 @@ func GetBadgeParams(r *http.Request, requestedUser *models.User) (*models.KeyedI default: // non-entity-specific request, just a general, in-total query permitEntity = true + filters = &models.Filters{} } if !permitEntity { diff --git a/services/summary.go b/services/summary.go index 1e22269..9be0fc4 100644 --- a/services/summary.go +++ b/services/summary.go @@ -117,6 +117,12 @@ func (srv *SummaryService) Retrieve(from, to time.Time, user *models.User, filte missingIntervals := srv.getMissingIntervals(from, to, summaries, false) for _, interval := range missingIntervals { if s, err := srv.Summarize(interval.Start, interval.End, user, filters); err == nil { + if len(missingIntervals) > 2 && s.FromTime.T().Equal(s.ToTime.T()) { + // little hack here: GetAllWithin will query for >= from_date + // however, for "in-between" / intra-day missing intervals, we want strictly > from_date to prevent double-counting + // to not have to rewrite many interfaces, we skip these summaries here + continue + } summaries = append(summaries, s) } else { return nil, err @@ -384,7 +390,7 @@ func (srv *SummaryService) getMissingIntervals(from, to time.Time, summaries []* // Between for i := 0; i < len(summaries)-1; i++ { t1, t2 := summaries[i].ToTime.T(), summaries[i+1].FromTime.T() - if t1.Equal(t2) || t1.Equal(to) || t1.After(to) { + if t1.Equal(t2) || t1.Equal(to) || t1.After(to) { // TODO: check after continue } @@ -401,14 +407,14 @@ func (srv *SummaryService) getMissingIntervals(from, to time.Time, summaries []* // we always want to jump to beginning of next day // however, if left summary ends already at midnight, we would instead jump to beginning of second-next day -> go back again - if td1.Sub(t1) == 24*time.Hour { + if td1.AddDate(0, 0, 1).Equal(t1) { td1 = td1.Add(-1 * time.Hour) } } // one or more day missing in between? if td1.Before(td2) { - intervals = append(intervals, &models.Interval{Start: summaries[i].ToTime.T(), End: summaries[i+1].FromTime.T()}) + intervals = append(intervals, &models.Interval{Start: t1, End: t2}) } } diff --git a/services/summary_test.go b/services/summary_test.go index 0c9f61b..b9d591d 100644 --- a/services/summary_test.go +++ b/services/summary_test.go @@ -318,7 +318,7 @@ func (suite *SummaryServiceTestSuite) TestSummaryService_Retrieve() { assert.Equal(suite.T(), 45*time.Minute, result.TotalTimeByKey(models.SummaryProject, TestProject1)) assert.Equal(suite.T(), 45*time.Minute, result.TotalTimeByKey(models.SummaryProject, TestProject2)) assert.Equal(suite.T(), 200, result.NumHeartbeats) - suite.DurationService.AssertNumberOfCalls(suite.T(), "Get", 2+1+1) + suite.DurationService.AssertNumberOfCalls(suite.T(), "Get", 2+1) } func (suite *SummaryServiceTestSuite) TestSummaryService_Retrieve_DuplicateSummaries() { From 91c765202c807bd9706edb40c1b3e18eb22ca6b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ferdinand=20M=C3=BCtsch?= Date: Mon, 18 Apr 2022 16:06:32 +0200 Subject: [PATCH 07/14] fix: prevent large difference between aggregated and recomputed summaries (resolve #354) --- services/duration.go | 22 ++++++++++++++++++---- services/summary.go | 2 +- 2 files changed, 19 insertions(+), 5 deletions(-) diff --git a/services/duration.go b/services/duration.go index 1b40220..af2aa86 100644 --- a/services/duration.go +++ b/services/duration.go @@ -1,6 +1,7 @@ package services import ( + "github.com/duke-git/lancet/v2/mathutil" "github.com/muety/wakapi/config" "github.com/muety/wakapi/models" "time" @@ -59,13 +60,26 @@ func (srv *DurationService) Get(from, to time.Time, user *models.User, filters * continue } - dur := d1.Time.T().Sub(latest.Time.T().Add(latest.Duration)) - if dur > HeartbeatDiffThreshold { - dur = HeartbeatDiffThreshold + sameDay := d1.Time.T().Day() == latest.Time.T().Day() + dur := time.Duration(mathutil.Min( + int64(d1.Time.T().Sub(latest.Time.T().Add(latest.Duration))), + int64(HeartbeatDiffThreshold), + )) + + // skip heartbeats that span across two adjacent summaries (assuming there are no more than 1 summary per day) + // this is relevant to prevent the time difference between generating summaries from raw heartbeats and aggregating pre-generated summaries + // for the latter case, the very last heartbeat of a day won't be counted, so we don't want to count it here either + // another option would be to adapt the Summarize() method to always append up to HeartbeatDiffThreshold seconds to a day's very last duration + if !sameDay { + dur = 0 } latest.Duration += dur - if dur >= HeartbeatDiffThreshold || latest.GroupHash != d1.GroupHash { + // start new "group" if: + // (a) heartbeats were too far apart each other, + // (b) if they are of a different entity or, + // (c) if they span across two days + if dur >= HeartbeatDiffThreshold || latest.GroupHash != d1.GroupHash || !sameDay { list := mapping[d1.GroupHash] if d0 := list[len(list)-1]; d0 != d1 { mapping[d1.GroupHash] = append(mapping[d1.GroupHash], d1) diff --git a/services/summary.go b/services/summary.go index 9be0fc4..4dfbe6f 100644 --- a/services/summary.go +++ b/services/summary.go @@ -390,7 +390,7 @@ func (srv *SummaryService) getMissingIntervals(from, to time.Time, summaries []* // Between for i := 0; i < len(summaries)-1; i++ { t1, t2 := summaries[i].ToTime.T(), summaries[i+1].FromTime.T() - if t1.Equal(t2) || t1.Equal(to) || t1.After(to) { // TODO: check after + if t1.Equal(t2) || t1.Equal(to) || t1.After(to) { continue } From 15c391d1d466ccd2951eb803a7e6eaa7ccfa2fa3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ferdinand=20M=C3=BCtsch?= Date: Mon, 18 Apr 2022 16:07:52 +0200 Subject: [PATCH 08/14] chore: downgrade postgres driver --- go.mod | 2 +- go.sum | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/go.mod b/go.mod index 2b4e343..b7252e9 100644 --- a/go.mod +++ b/go.mod @@ -29,7 +29,7 @@ require ( golang.org/x/crypto v0.0.0-20220411220226-7b82a4e95df4 golang.org/x/sync v0.0.0-20210220032951-036812b2e83c gorm.io/driver/mysql v1.3.3 - gorm.io/driver/postgres v1.3.4 + gorm.io/driver/postgres v1.3.3 gorm.io/driver/sqlite v1.3.1 gorm.io/gorm v1.23.4 ) diff --git a/go.sum b/go.sum index 347bdae..f1eb644 100644 --- a/go.sum +++ b/go.sum @@ -331,6 +331,8 @@ gorm.io/driver/mysql v1.3.3 h1:jXG9ANrwBc4+bMvBcSl8zCfPBaVoPyBEBshA8dA93X8= gorm.io/driver/mysql v1.3.3/go.mod h1:ChK6AHbHgDCFZyJp0F+BmVGb06PSIoh9uVYKAlRbb2U= gorm.io/driver/postgres v1.3.2 h1:1URWk4lHWJkcudB+9bxOcNNt3uk5VfB8V2mzTPOqjRg= gorm.io/driver/postgres v1.3.2/go.mod h1:y0vEuInFKJtijuSGu9e5bs5hzzSzPK+LancpKpvbRBw= +gorm.io/driver/postgres v1.3.3 h1:y6DU2kJgDNisxfAlmxRaQZOIy4ytnuYrpzpSFYnSfCY= +gorm.io/driver/postgres v1.3.3/go.mod h1:y0vEuInFKJtijuSGu9e5bs5hzzSzPK+LancpKpvbRBw= gorm.io/driver/postgres v1.3.4 h1:evZ7plF+Bp+Lr1mO5NdPvd6M/N98XtwHixGB+y7fdEQ= gorm.io/driver/postgres v1.3.4/go.mod h1:y0vEuInFKJtijuSGu9e5bs5hzzSzPK+LancpKpvbRBw= gorm.io/driver/sqlite v1.3.1 h1:bwfE+zTEWklBYoEodIOIBwuWHpnx52Z9zJFW5F33WLk= From e6441f124c61a01ab6fc0246ee3f1e874fe04058 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ferdinand=20M=C3=BCtsch?= Date: Mon, 18 Apr 2022 16:14:58 +0200 Subject: [PATCH 09/14] chore: adapt tests --- coverage/coverage.out | 1026 ++++++++--------- .../wakapi_api_tests.postman_collection.json | 2 +- 2 files changed, 514 insertions(+), 514 deletions(-) diff --git a/coverage/coverage.out b/coverage/coverage.out index 4e822b8..a073b0c 100644 --- a/coverage/coverage.out +++ b/coverage/coverage.out @@ -1,4 +1,157 @@ mode: set +github.com/muety/wakapi/models/duration.go:24.55,38.2 2 0 +github.com/muety/wakapi/models/duration.go:40.39,42.16 2 0 +github.com/muety/wakapi/models/duration.go:45.2,46.10 2 0 +github.com/muety/wakapi/models/duration.go:42.16,44.3 1 0 +github.com/muety/wakapi/models/duration.go:49.49,50.11 1 0 +github.com/muety/wakapi/models/duration.go:65.2,65.15 1 0 +github.com/muety/wakapi/models/duration.go:69.2,69.12 1 0 +github.com/muety/wakapi/models/duration.go:51.22,52.18 1 0 +github.com/muety/wakapi/models/duration.go:53.21,54.17 1 0 +github.com/muety/wakapi/models/duration.go:55.23,56.19 1 0 +github.com/muety/wakapi/models/duration.go:57.17,58.26 1 0 +github.com/muety/wakapi/models/duration.go:59.22,60.18 1 0 +github.com/muety/wakapi/models/duration.go:61.21,62.17 1 0 +github.com/muety/wakapi/models/duration.go:65.15,67.3 1 0 +github.com/muety/wakapi/models/heartbeats.go:7.31,9.2 1 0 +github.com/muety/wakapi/models/heartbeats.go:11.41,13.2 1 0 +github.com/muety/wakapi/models/heartbeats.go:15.36,17.2 1 0 +github.com/muety/wakapi/models/heartbeats.go:19.43,22.2 2 0 +github.com/muety/wakapi/models/heartbeats.go:24.41,26.18 1 0 +github.com/muety/wakapi/models/heartbeats.go:29.2,29.16 1 0 +github.com/muety/wakapi/models/heartbeats.go:26.18,28.3 1 0 +github.com/muety/wakapi/models/heartbeats.go:32.40,34.18 1 0 +github.com/muety/wakapi/models/heartbeats.go:37.2,37.24 1 0 +github.com/muety/wakapi/models/heartbeats.go:34.18,36.3 1 0 +github.com/muety/wakapi/models/mail_address.go:15.13,18.2 2 1 +github.com/muety/wakapi/models/mail_address.go:24.38,26.2 1 0 +github.com/muety/wakapi/models/mail_address.go:28.35,30.21 2 1 +github.com/muety/wakapi/models/mail_address.go:36.2,36.11 1 1 +github.com/muety/wakapi/models/mail_address.go:30.21,31.21 1 1 +github.com/muety/wakapi/models/mail_address.go:34.3,34.18 1 1 +github.com/muety/wakapi/models/mail_address.go:31.21,33.4 1 1 +github.com/muety/wakapi/models/mail_address.go:39.35,41.2 1 1 +github.com/muety/wakapi/models/mail_address.go:43.43,45.22 2 0 +github.com/muety/wakapi/models/mail_address.go:48.2,48.12 1 0 +github.com/muety/wakapi/models/mail_address.go:45.22,47.3 1 0 +github.com/muety/wakapi/models/mail_address.go:51.46,53.22 2 1 +github.com/muety/wakapi/models/mail_address.go:56.2,56.12 1 1 +github.com/muety/wakapi/models/mail_address.go:53.22,55.3 1 1 +github.com/muety/wakapi/models/mail_address.go:59.40,60.22 1 1 +github.com/muety/wakapi/models/mail_address.go:65.2,65.13 1 1 +github.com/muety/wakapi/models/mail_address.go:60.22,61.17 1 1 +github.com/muety/wakapi/models/mail_address.go:61.17,63.4 1 1 +github.com/muety/wakapi/models/models.go:3.14,5.2 0 1 +github.com/muety/wakapi/models/shared.go:40.52,42.2 1 0 +github.com/muety/wakapi/models/shared.go:44.52,47.16 3 0 +github.com/muety/wakapi/models/shared.go:50.2,52.12 3 0 +github.com/muety/wakapi/models/shared.go:47.16,49.3 1 0 +github.com/muety/wakapi/models/shared.go:55.52,61.22 2 0 +github.com/muety/wakapi/models/shared.go:76.2,79.12 3 0 +github.com/muety/wakapi/models/shared.go:62.14,66.17 2 0 +github.com/muety/wakapi/models/shared.go:69.17,71.8 2 0 +github.com/muety/wakapi/models/shared.go:72.10,73.64 1 0 +github.com/muety/wakapi/models/shared.go:66.17,68.4 1 0 +github.com/muety/wakapi/models/shared.go:82.51,85.2 2 0 +github.com/muety/wakapi/models/shared.go:87.45,89.2 1 0 +github.com/muety/wakapi/models/shared.go:91.37,93.2 1 0 +github.com/muety/wakapi/models/shared.go:95.35,97.2 1 0 +github.com/muety/wakapi/models/shared.go:99.34,101.2 1 0 +github.com/muety/wakapi/models/alias.go:18.32,20.2 1 0 +github.com/muety/wakapi/models/alias.go:22.37,23.35 1 0 +github.com/muety/wakapi/models/alias.go:28.2,28.14 1 0 +github.com/muety/wakapi/models/alias.go:23.35,24.18 1 0 +github.com/muety/wakapi/models/alias.go:24.18,26.4 1 0 +github.com/muety/wakapi/models/filters.go:21.33,23.2 1 1 +github.com/muety/wakapi/models/filters.go:25.48,26.22 1 1 +github.com/muety/wakapi/models/filters.go:31.2,31.14 1 1 +github.com/muety/wakapi/models/filters.go:26.22,27.18 1 1 +github.com/muety/wakapi/models/filters.go:27.18,29.4 1 1 +github.com/muety/wakapi/models/filters.go:39.56,41.2 1 1 +github.com/muety/wakapi/models/filters.go:43.66,46.2 2 1 +github.com/muety/wakapi/models/filters.go:48.59,50.2 1 1 +github.com/muety/wakapi/models/filters.go:52.70,53.16 1 1 +github.com/muety/wakapi/models/filters.go:69.2,69.10 1 1 +github.com/muety/wakapi/models/filters.go:54.22,55.41 1 1 +github.com/muety/wakapi/models/filters.go:56.17,57.31 1 0 +github.com/muety/wakapi/models/filters.go:58.23,59.43 1 1 +github.com/muety/wakapi/models/filters.go:60.21,61.39 1 0 +github.com/muety/wakapi/models/filters.go:62.22,63.41 1 0 +github.com/muety/wakapi/models/filters.go:64.20,65.37 1 1 +github.com/muety/wakapi/models/filters.go:66.21,67.39 1 0 +github.com/muety/wakapi/models/filters.go:72.49,73.44 1 1 +github.com/muety/wakapi/models/filters.go:88.2,88.29 1 1 +github.com/muety/wakapi/models/filters.go:73.44,75.3 1 1 +github.com/muety/wakapi/models/filters.go:75.8,75.41 1 1 +github.com/muety/wakapi/models/filters.go:75.41,77.3 1 0 +github.com/muety/wakapi/models/filters.go:77.8,77.53 1 1 +github.com/muety/wakapi/models/filters.go:77.53,79.3 1 1 +github.com/muety/wakapi/models/filters.go:79.8,79.49 1 1 +github.com/muety/wakapi/models/filters.go:79.49,81.3 1 0 +github.com/muety/wakapi/models/filters.go:81.8,81.51 1 1 +github.com/muety/wakapi/models/filters.go:81.51,83.3 1 0 +github.com/muety/wakapi/models/filters.go:83.8,83.47 1 1 +github.com/muety/wakapi/models/filters.go:83.47,85.3 1 0 +github.com/muety/wakapi/models/filters.go:85.8,85.49 1 1 +github.com/muety/wakapi/models/filters.go:85.49,87.3 1 0 +github.com/muety/wakapi/models/filters.go:91.46,92.30 1 1 +github.com/muety/wakapi/models/filters.go:95.2,95.66 1 0 +github.com/muety/wakapi/models/filters.go:92.30,94.3 1 1 +github.com/muety/wakapi/models/filters.go:98.34,101.2 2 1 +github.com/muety/wakapi/models/filters.go:103.31,105.51 2 0 +github.com/muety/wakapi/models/filters.go:108.2,108.14 1 0 +github.com/muety/wakapi/models/filters.go:105.51,107.3 1 0 +github.com/muety/wakapi/models/filters.go:111.51,113.2 1 0 +github.com/muety/wakapi/models/filters.go:115.37,117.51 2 0 +github.com/muety/wakapi/models/filters.go:122.2,122.14 1 0 +github.com/muety/wakapi/models/filters.go:117.51,118.37 1 0 +github.com/muety/wakapi/models/filters.go:118.37,120.4 1 0 +github.com/muety/wakapi/models/filters.go:125.59,126.18 1 0 +github.com/muety/wakapi/models/filters.go:127.22,128.20 1 0 +github.com/muety/wakapi/models/filters.go:129.23,130.21 1 0 +github.com/muety/wakapi/models/filters.go:131.21,132.19 1 0 +github.com/muety/wakapi/models/filters.go:133.17,134.15 1 0 +github.com/muety/wakapi/models/filters.go:135.22,136.20 1 0 +github.com/muety/wakapi/models/filters.go:137.20,138.18 1 0 +github.com/muety/wakapi/models/filters.go:139.21,140.19 1 0 +github.com/muety/wakapi/models/filters.go:141.10,142.21 1 0 +github.com/muety/wakapi/models/filters.go:146.33,148.16 2 0 +github.com/muety/wakapi/models/filters.go:151.2,151.32 1 0 +github.com/muety/wakapi/models/filters.go:148.16,150.3 1 0 +github.com/muety/wakapi/models/filters.go:154.44,160.2 1 1 +github.com/muety/wakapi/models/filters.go:163.70,164.22 1 1 +github.com/muety/wakapi/models/filters.go:172.2,172.17 1 1 +github.com/muety/wakapi/models/filters.go:180.2,180.23 1 1 +github.com/muety/wakapi/models/filters.go:188.2,188.21 1 1 +github.com/muety/wakapi/models/filters.go:196.2,196.22 1 1 +github.com/muety/wakapi/models/filters.go:204.2,204.21 1 1 +github.com/muety/wakapi/models/filters.go:212.2,212.10 1 1 +github.com/muety/wakapi/models/filters.go:164.22,166.31 2 1 +github.com/muety/wakapi/models/filters.go:170.3,170.22 1 1 +github.com/muety/wakapi/models/filters.go:166.31,169.4 2 1 +github.com/muety/wakapi/models/filters.go:172.17,174.26 2 0 +github.com/muety/wakapi/models/filters.go:178.3,178.17 1 0 +github.com/muety/wakapi/models/filters.go:174.26,177.4 2 0 +github.com/muety/wakapi/models/filters.go:180.23,182.32 2 1 +github.com/muety/wakapi/models/filters.go:186.3,186.23 1 1 +github.com/muety/wakapi/models/filters.go:182.32,185.4 2 1 +github.com/muety/wakapi/models/filters.go:188.21,190.30 2 0 +github.com/muety/wakapi/models/filters.go:194.3,194.21 1 0 +github.com/muety/wakapi/models/filters.go:190.30,193.4 2 0 +github.com/muety/wakapi/models/filters.go:196.22,198.31 2 0 +github.com/muety/wakapi/models/filters.go:202.3,202.22 1 0 +github.com/muety/wakapi/models/filters.go:198.31,201.4 2 0 +github.com/muety/wakapi/models/filters.go:204.21,206.30 2 0 +github.com/muety/wakapi/models/filters.go:210.3,210.21 1 0 +github.com/muety/wakapi/models/filters.go:206.30,209.4 2 0 +github.com/muety/wakapi/models/filters.go:215.83,216.41 1 1 +github.com/muety/wakapi/models/filters.go:219.2,219.28 1 1 +github.com/muety/wakapi/models/filters.go:222.2,222.10 1 1 +github.com/muety/wakapi/models/filters.go:216.41,218.3 1 0 +github.com/muety/wakapi/models/filters.go:219.28,221.3 1 1 +github.com/muety/wakapi/models/language_mapping.go:11.42,13.2 1 0 +github.com/muety/wakapi/models/language_mapping.go:15.51,17.2 1 0 +github.com/muety/wakapi/models/language_mapping.go:19.52,21.2 1 0 github.com/muety/wakapi/models/summary.go:64.29,66.2 1 1 github.com/muety/wakapi/models/summary.go:68.35,70.2 1 0 github.com/muety/wakapi/models/summary.go:72.38,74.2 1 0 @@ -97,44 +250,29 @@ github.com/muety/wakapi/models/summary.go:359.50,363.2 1 1 github.com/muety/wakapi/models/summary.go:365.33,367.2 1 1 github.com/muety/wakapi/models/summary.go:369.43,371.2 1 1 github.com/muety/wakapi/models/summary.go:373.38,375.2 1 1 -github.com/muety/wakapi/models/duration.go:24.55,38.2 2 0 -github.com/muety/wakapi/models/duration.go:40.39,42.16 2 0 -github.com/muety/wakapi/models/duration.go:45.2,46.10 2 0 -github.com/muety/wakapi/models/duration.go:42.16,44.3 1 0 -github.com/muety/wakapi/models/duration.go:49.49,50.11 1 0 -github.com/muety/wakapi/models/duration.go:65.2,65.15 1 0 -github.com/muety/wakapi/models/duration.go:69.2,69.12 1 0 -github.com/muety/wakapi/models/duration.go:51.22,52.18 1 0 -github.com/muety/wakapi/models/duration.go:53.21,54.17 1 0 -github.com/muety/wakapi/models/duration.go:55.23,56.19 1 0 -github.com/muety/wakapi/models/duration.go:57.17,58.26 1 0 -github.com/muety/wakapi/models/duration.go:59.22,60.18 1 0 -github.com/muety/wakapi/models/duration.go:61.21,62.17 1 0 -github.com/muety/wakapi/models/duration.go:65.15,67.3 1 0 -github.com/muety/wakapi/models/heartbeats.go:7.31,9.2 1 0 -github.com/muety/wakapi/models/heartbeats.go:11.41,13.2 1 0 -github.com/muety/wakapi/models/heartbeats.go:15.36,17.2 1 0 -github.com/muety/wakapi/models/heartbeats.go:19.43,22.2 2 0 -github.com/muety/wakapi/models/heartbeats.go:24.41,26.18 1 0 -github.com/muety/wakapi/models/heartbeats.go:29.2,29.16 1 0 -github.com/muety/wakapi/models/heartbeats.go:26.18,28.3 1 0 -github.com/muety/wakapi/models/heartbeats.go:32.40,34.18 1 0 -github.com/muety/wakapi/models/heartbeats.go:37.2,37.24 1 0 -github.com/muety/wakapi/models/heartbeats.go:34.18,36.3 1 0 -github.com/muety/wakapi/models/language_mapping.go:11.42,13.2 1 0 -github.com/muety/wakapi/models/language_mapping.go:15.51,17.2 1 0 -github.com/muety/wakapi/models/language_mapping.go:19.52,21.2 1 0 -github.com/muety/wakapi/models/mail.go:19.44,23.2 3 0 -github.com/muety/wakapi/models/mail.go:25.44,29.2 3 0 -github.com/muety/wakapi/models/mail.go:31.32,44.2 1 0 -github.com/muety/wakapi/models/mail.go:46.41,48.2 1 0 -github.com/muety/wakapi/models/models.go:3.14,5.2 0 1 -github.com/muety/wakapi/models/project_label.go:14.39,16.2 1 0 -github.com/muety/wakapi/models/alias.go:18.32,20.2 1 0 -github.com/muety/wakapi/models/alias.go:22.37,23.35 1 0 -github.com/muety/wakapi/models/alias.go:28.2,28.14 1 0 -github.com/muety/wakapi/models/alias.go:23.35,24.18 1 0 -github.com/muety/wakapi/models/alias.go:24.18,26.4 1 0 +github.com/muety/wakapi/models/user.go:11.13,13.2 1 1 +github.com/muety/wakapi/models/user.go:83.36,84.22 1 1 +github.com/muety/wakapi/models/user.go:87.2,88.16 2 1 +github.com/muety/wakapi/models/user.go:91.2,91.11 1 1 +github.com/muety/wakapi/models/user.go:84.22,86.3 1 1 +github.com/muety/wakapi/models/user.go:88.16,90.3 1 0 +github.com/muety/wakapi/models/user.go:96.41,99.2 2 1 +github.com/muety/wakapi/models/user.go:101.53,104.54 3 0 +github.com/muety/wakapi/models/user.go:107.2,107.51 1 0 +github.com/muety/wakapi/models/user.go:110.2,110.20 1 0 +github.com/muety/wakapi/models/user.go:104.54,106.3 1 0 +github.com/muety/wakapi/models/user.go:107.51,109.3 1 0 +github.com/muety/wakapi/models/user.go:114.52,115.28 1 0 +github.com/muety/wakapi/models/user.go:118.2,118.17 1 0 +github.com/muety/wakapi/models/user.go:115.28,117.3 1 0 +github.com/muety/wakapi/models/user.go:121.43,124.2 1 0 +github.com/muety/wakapi/models/user.go:126.45,129.2 1 0 +github.com/muety/wakapi/models/user.go:131.33,136.2 1 0 +github.com/muety/wakapi/models/user.go:138.41,140.2 1 0 +github.com/muety/wakapi/models/user.go:142.45,144.2 1 0 +github.com/muety/wakapi/models/user.go:146.45,148.2 1 0 +github.com/muety/wakapi/models/user.go:150.39,152.2 1 0 +github.com/muety/wakapi/models/user.go:154.39,157.2 2 0 github.com/muety/wakapi/models/durations.go:7.30,9.2 1 0 github.com/muety/wakapi/models/durations.go:11.40,13.2 1 0 github.com/muety/wakapi/models/durations.go:15.35,17.2 1 0 @@ -148,126 +286,11 @@ github.com/muety/wakapi/models/durations.go:34.18,36.3 1 0 github.com/muety/wakapi/models/durations.go:40.38,42.18 1 0 github.com/muety/wakapi/models/durations.go:45.2,45.24 1 0 github.com/muety/wakapi/models/durations.go:42.18,44.3 1 0 -github.com/muety/wakapi/models/filters.go:21.33,23.2 1 1 -github.com/muety/wakapi/models/filters.go:25.48,26.22 1 1 -github.com/muety/wakapi/models/filters.go:31.2,31.14 1 1 -github.com/muety/wakapi/models/filters.go:26.22,27.18 1 1 -github.com/muety/wakapi/models/filters.go:27.18,29.4 1 1 -github.com/muety/wakapi/models/filters.go:39.56,41.2 1 1 -github.com/muety/wakapi/models/filters.go:43.66,46.2 2 1 -github.com/muety/wakapi/models/filters.go:48.59,50.2 1 1 -github.com/muety/wakapi/models/filters.go:52.70,53.16 1 1 -github.com/muety/wakapi/models/filters.go:69.2,69.10 1 1 -github.com/muety/wakapi/models/filters.go:54.22,55.41 1 1 -github.com/muety/wakapi/models/filters.go:56.17,57.31 1 0 -github.com/muety/wakapi/models/filters.go:58.23,59.43 1 1 -github.com/muety/wakapi/models/filters.go:60.21,61.39 1 0 -github.com/muety/wakapi/models/filters.go:62.22,63.41 1 0 -github.com/muety/wakapi/models/filters.go:64.20,65.37 1 1 -github.com/muety/wakapi/models/filters.go:66.21,67.39 1 0 -github.com/muety/wakapi/models/filters.go:72.49,73.44 1 1 -github.com/muety/wakapi/models/filters.go:88.2,88.29 1 1 -github.com/muety/wakapi/models/filters.go:73.44,75.3 1 1 -github.com/muety/wakapi/models/filters.go:75.8,75.41 1 1 -github.com/muety/wakapi/models/filters.go:75.41,77.3 1 0 -github.com/muety/wakapi/models/filters.go:77.8,77.53 1 1 -github.com/muety/wakapi/models/filters.go:77.53,79.3 1 1 -github.com/muety/wakapi/models/filters.go:79.8,79.49 1 1 -github.com/muety/wakapi/models/filters.go:79.49,81.3 1 0 -github.com/muety/wakapi/models/filters.go:81.8,81.51 1 1 -github.com/muety/wakapi/models/filters.go:81.51,83.3 1 0 -github.com/muety/wakapi/models/filters.go:83.8,83.47 1 1 -github.com/muety/wakapi/models/filters.go:83.47,85.3 1 0 -github.com/muety/wakapi/models/filters.go:85.8,85.49 1 1 -github.com/muety/wakapi/models/filters.go:85.49,87.3 1 0 -github.com/muety/wakapi/models/filters.go:91.46,92.30 1 1 -github.com/muety/wakapi/models/filters.go:95.2,95.66 1 0 -github.com/muety/wakapi/models/filters.go:92.30,94.3 1 1 -github.com/muety/wakapi/models/filters.go:98.34,101.2 2 1 -github.com/muety/wakapi/models/filters.go:103.31,105.51 2 0 -github.com/muety/wakapi/models/filters.go:108.2,108.14 1 0 -github.com/muety/wakapi/models/filters.go:105.51,107.3 1 0 -github.com/muety/wakapi/models/filters.go:111.51,113.2 1 0 -github.com/muety/wakapi/models/filters.go:115.37,117.51 2 0 -github.com/muety/wakapi/models/filters.go:122.2,122.14 1 0 -github.com/muety/wakapi/models/filters.go:117.51,118.37 1 0 -github.com/muety/wakapi/models/filters.go:118.37,120.4 1 0 -github.com/muety/wakapi/models/filters.go:125.59,126.18 1 0 -github.com/muety/wakapi/models/filters.go:127.22,128.20 1 0 -github.com/muety/wakapi/models/filters.go:129.23,130.21 1 0 -github.com/muety/wakapi/models/filters.go:131.21,132.19 1 0 -github.com/muety/wakapi/models/filters.go:133.17,134.15 1 0 -github.com/muety/wakapi/models/filters.go:135.22,136.20 1 0 -github.com/muety/wakapi/models/filters.go:137.20,138.18 1 0 -github.com/muety/wakapi/models/filters.go:139.21,140.19 1 0 -github.com/muety/wakapi/models/filters.go:141.10,142.21 1 0 -github.com/muety/wakapi/models/filters.go:146.33,148.16 2 0 -github.com/muety/wakapi/models/filters.go:151.2,151.32 1 0 -github.com/muety/wakapi/models/filters.go:148.16,150.3 1 0 -github.com/muety/wakapi/models/filters.go:154.44,160.2 1 1 -github.com/muety/wakapi/models/filters.go:163.70,164.22 1 1 -github.com/muety/wakapi/models/filters.go:172.2,172.17 1 1 -github.com/muety/wakapi/models/filters.go:180.2,180.23 1 1 -github.com/muety/wakapi/models/filters.go:188.2,188.21 1 1 -github.com/muety/wakapi/models/filters.go:196.2,196.22 1 1 -github.com/muety/wakapi/models/filters.go:204.2,204.21 1 1 -github.com/muety/wakapi/models/filters.go:212.2,212.10 1 1 -github.com/muety/wakapi/models/filters.go:164.22,166.31 2 1 -github.com/muety/wakapi/models/filters.go:170.3,170.22 1 1 -github.com/muety/wakapi/models/filters.go:166.31,169.4 2 1 -github.com/muety/wakapi/models/filters.go:172.17,174.26 2 0 -github.com/muety/wakapi/models/filters.go:178.3,178.17 1 0 -github.com/muety/wakapi/models/filters.go:174.26,177.4 2 0 -github.com/muety/wakapi/models/filters.go:180.23,182.32 2 1 -github.com/muety/wakapi/models/filters.go:186.3,186.23 1 1 -github.com/muety/wakapi/models/filters.go:182.32,185.4 2 1 -github.com/muety/wakapi/models/filters.go:188.21,190.30 2 0 -github.com/muety/wakapi/models/filters.go:194.3,194.21 1 0 -github.com/muety/wakapi/models/filters.go:190.30,193.4 2 0 -github.com/muety/wakapi/models/filters.go:196.22,198.31 2 0 -github.com/muety/wakapi/models/filters.go:202.3,202.22 1 0 -github.com/muety/wakapi/models/filters.go:198.31,201.4 2 0 -github.com/muety/wakapi/models/filters.go:204.21,206.30 2 0 -github.com/muety/wakapi/models/filters.go:210.3,210.21 1 0 -github.com/muety/wakapi/models/filters.go:206.30,209.4 2 0 -github.com/muety/wakapi/models/filters.go:215.83,216.41 1 1 -github.com/muety/wakapi/models/filters.go:219.2,219.28 1 1 -github.com/muety/wakapi/models/filters.go:222.2,222.10 1 1 -github.com/muety/wakapi/models/filters.go:216.41,218.3 1 0 -github.com/muety/wakapi/models/filters.go:219.28,221.3 1 1 -github.com/muety/wakapi/models/mail_address.go:15.13,18.2 2 1 -github.com/muety/wakapi/models/mail_address.go:24.38,26.2 1 0 -github.com/muety/wakapi/models/mail_address.go:28.35,30.21 2 1 -github.com/muety/wakapi/models/mail_address.go:36.2,36.11 1 1 -github.com/muety/wakapi/models/mail_address.go:30.21,31.21 1 1 -github.com/muety/wakapi/models/mail_address.go:34.3,34.18 1 1 -github.com/muety/wakapi/models/mail_address.go:31.21,33.4 1 1 -github.com/muety/wakapi/models/mail_address.go:39.35,41.2 1 1 -github.com/muety/wakapi/models/mail_address.go:43.43,45.22 2 0 -github.com/muety/wakapi/models/mail_address.go:48.2,48.12 1 0 -github.com/muety/wakapi/models/mail_address.go:45.22,47.3 1 0 -github.com/muety/wakapi/models/mail_address.go:51.46,53.22 2 1 -github.com/muety/wakapi/models/mail_address.go:56.2,56.12 1 1 -github.com/muety/wakapi/models/mail_address.go:53.22,55.3 1 1 -github.com/muety/wakapi/models/mail_address.go:59.40,60.22 1 1 -github.com/muety/wakapi/models/mail_address.go:65.2,65.13 1 1 -github.com/muety/wakapi/models/mail_address.go:60.22,61.17 1 1 -github.com/muety/wakapi/models/mail_address.go:61.17,63.4 1 1 -github.com/muety/wakapi/models/shared.go:40.52,42.2 1 0 -github.com/muety/wakapi/models/shared.go:44.52,47.16 3 0 -github.com/muety/wakapi/models/shared.go:50.2,52.12 3 0 -github.com/muety/wakapi/models/shared.go:47.16,49.3 1 0 -github.com/muety/wakapi/models/shared.go:55.52,61.22 2 0 -github.com/muety/wakapi/models/shared.go:76.2,79.12 3 0 -github.com/muety/wakapi/models/shared.go:62.14,66.17 2 0 -github.com/muety/wakapi/models/shared.go:69.17,71.8 2 0 -github.com/muety/wakapi/models/shared.go:72.10,73.64 1 0 -github.com/muety/wakapi/models/shared.go:66.17,68.4 1 0 -github.com/muety/wakapi/models/shared.go:82.51,85.2 2 0 -github.com/muety/wakapi/models/shared.go:87.45,89.2 1 0 -github.com/muety/wakapi/models/shared.go:91.37,93.2 1 0 -github.com/muety/wakapi/models/shared.go:95.35,97.2 1 0 -github.com/muety/wakapi/models/shared.go:99.34,101.2 1 0 +github.com/muety/wakapi/models/mail.go:19.44,23.2 3 0 +github.com/muety/wakapi/models/mail.go:25.44,29.2 3 0 +github.com/muety/wakapi/models/mail.go:31.32,44.2 1 0 +github.com/muety/wakapi/models/mail.go:46.41,48.2 1 0 +github.com/muety/wakapi/models/project_label.go:14.39,16.2 1 0 github.com/muety/wakapi/models/heartbeat.go:33.34,35.2 1 1 github.com/muety/wakapi/models/heartbeat.go:37.55,40.2 2 0 github.com/muety/wakapi/models/heartbeat.go:42.65,44.46 2 1 @@ -292,29 +315,6 @@ github.com/muety/wakapi/models/interval.go:39.47,40.23 1 0 github.com/muety/wakapi/models/interval.go:45.2,45.14 1 0 github.com/muety/wakapi/models/interval.go:40.23,41.13 1 0 github.com/muety/wakapi/models/interval.go:41.13,43.4 1 0 -github.com/muety/wakapi/models/user.go:11.13,13.2 1 1 -github.com/muety/wakapi/models/user.go:83.36,84.22 1 1 -github.com/muety/wakapi/models/user.go:87.2,88.16 2 1 -github.com/muety/wakapi/models/user.go:91.2,91.11 1 1 -github.com/muety/wakapi/models/user.go:84.22,86.3 1 1 -github.com/muety/wakapi/models/user.go:88.16,90.3 1 0 -github.com/muety/wakapi/models/user.go:96.41,99.2 2 1 -github.com/muety/wakapi/models/user.go:101.53,104.54 3 0 -github.com/muety/wakapi/models/user.go:107.2,107.51 1 0 -github.com/muety/wakapi/models/user.go:110.2,110.20 1 0 -github.com/muety/wakapi/models/user.go:104.54,106.3 1 0 -github.com/muety/wakapi/models/user.go:107.51,109.3 1 0 -github.com/muety/wakapi/models/user.go:114.52,115.28 1 0 -github.com/muety/wakapi/models/user.go:118.2,118.17 1 0 -github.com/muety/wakapi/models/user.go:115.28,117.3 1 0 -github.com/muety/wakapi/models/user.go:121.43,124.2 1 0 -github.com/muety/wakapi/models/user.go:126.45,129.2 1 0 -github.com/muety/wakapi/models/user.go:131.33,136.2 1 0 -github.com/muety/wakapi/models/user.go:138.41,140.2 1 0 -github.com/muety/wakapi/models/user.go:142.45,144.2 1 0 -github.com/muety/wakapi/models/user.go:146.45,148.2 1 0 -github.com/muety/wakapi/models/user.go:150.39,152.2 1 0 -github.com/muety/wakapi/models/user.go:154.39,157.2 2 0 github.com/muety/wakapi/config/utils.go:5.78,7.22 2 0 github.com/muety/wakapi/config/utils.go:13.2,13.11 1 0 github.com/muety/wakapi/config/utils.go:7.22,8.18 1 0 @@ -461,36 +461,6 @@ github.com/muety/wakapi/config/sentry.go:142.17,144.3 1 0 github.com/muety/wakapi/config/sentry.go:147.49,151.51 2 0 github.com/muety/wakapi/config/sentry.go:154.2,154.12 1 0 github.com/muety/wakapi/config/sentry.go:151.51,153.3 1 0 -github.com/muety/wakapi/utils/template.go:13.41,15.16 2 0 -github.com/muety/wakapi/utils/template.go:18.2,18.23 1 0 -github.com/muety/wakapi/utils/template.go:15.16,17.3 1 0 -github.com/muety/wakapi/utils/template.go:21.37,22.30 1 0 -github.com/muety/wakapi/utils/template.go:25.2,25.10 1 0 -github.com/muety/wakapi/utils/template.go:22.30,24.3 1 0 -github.com/muety/wakapi/utils/template.go:28.83,33.16 4 0 -github.com/muety/wakapi/utils/template.go:37.2,37.29 1 0 -github.com/muety/wakapi/utils/template.go:62.2,62.23 1 0 -github.com/muety/wakapi/utils/template.go:33.16,35.3 1 0 -github.com/muety/wakapi/utils/template.go:37.29,39.51 2 0 -github.com/muety/wakapi/utils/template.go:43.3,44.17 2 0 -github.com/muety/wakapi/utils/template.go:47.3,48.17 2 0 -github.com/muety/wakapi/utils/template.go:52.3,55.17 3 0 -github.com/muety/wakapi/utils/template.go:59.3,59.27 1 0 -github.com/muety/wakapi/utils/template.go:39.51,40.12 1 0 -github.com/muety/wakapi/utils/template.go:44.17,46.4 1 0 -github.com/muety/wakapi/utils/template.go:48.17,50.4 1 0 -github.com/muety/wakapi/utils/template.go:55.17,57.4 1 0 -github.com/muety/wakapi/utils/db.go:8.34,9.37 1 0 -github.com/muety/wakapi/utils/db.go:17.2,18.14 2 0 -github.com/muety/wakapi/utils/db.go:9.37,11.110 2 0 -github.com/muety/wakapi/utils/db.go:15.3,15.20 1 0 -github.com/muety/wakapi/utils/db.go:11.110,14.4 2 0 -github.com/muety/wakapi/utils/db.go:21.39,22.37 1 0 -github.com/muety/wakapi/utils/db.go:30.2,31.14 2 0 -github.com/muety/wakapi/utils/db.go:22.37,24.119 2 0 -github.com/muety/wakapi/utils/db.go:28.3,28.20 1 0 -github.com/muety/wakapi/utils/db.go:24.119,27.4 2 0 -github.com/muety/wakapi/utils/strings.go:8.34,10.2 1 0 github.com/muety/wakapi/utils/common.go:18.73,19.58 1 0 github.com/muety/wakapi/utils/common.go:22.2,22.87 1 0 github.com/muety/wakapi/utils/common.go:25.2,25.64 1 0 @@ -518,6 +488,16 @@ github.com/muety/wakapi/utils/date.go:43.3,44.10 2 1 github.com/muety/wakapi/utils/date.go:40.19,42.4 1 1 github.com/muety/wakapi/utils/date.go:50.50,56.2 5 0 github.com/muety/wakapi/utils/date.go:59.36,62.2 2 0 +github.com/muety/wakapi/utils/db.go:8.34,9.37 1 0 +github.com/muety/wakapi/utils/db.go:17.2,18.14 2 0 +github.com/muety/wakapi/utils/db.go:9.37,11.110 2 0 +github.com/muety/wakapi/utils/db.go:15.3,15.20 1 0 +github.com/muety/wakapi/utils/db.go:11.110,14.4 2 0 +github.com/muety/wakapi/utils/db.go:21.39,22.37 1 0 +github.com/muety/wakapi/utils/db.go:30.2,31.14 2 0 +github.com/muety/wakapi/utils/db.go:22.37,24.119 2 0 +github.com/muety/wakapi/utils/db.go:28.3,28.20 1 0 +github.com/muety/wakapi/utils/db.go:24.119,27.4 2 0 github.com/muety/wakapi/utils/http.go:21.13,23.2 1 1 github.com/muety/wakapi/utils/http.go:25.90,28.58 3 0 github.com/muety/wakapi/utils/http.go:28.58,30.3 1 0 @@ -527,6 +507,30 @@ github.com/muety/wakapi/utils/http.go:43.2,43.14 1 0 github.com/muety/wakapi/utils/http.go:35.48,37.3 1 0 github.com/muety/wakapi/utils/http.go:38.93,39.89 1 0 github.com/muety/wakapi/utils/http.go:39.89,41.4 1 0 +github.com/muety/wakapi/utils/strings.go:8.34,10.2 1 0 +github.com/muety/wakapi/utils/auth.go:16.79,18.54 2 0 +github.com/muety/wakapi/utils/auth.go:22.2,24.16 3 0 +github.com/muety/wakapi/utils/auth.go:28.2,30.45 3 0 +github.com/muety/wakapi/utils/auth.go:33.2,34.32 2 0 +github.com/muety/wakapi/utils/auth.go:18.54,20.3 1 0 +github.com/muety/wakapi/utils/auth.go:24.16,26.3 1 0 +github.com/muety/wakapi/utils/auth.go:30.45,32.3 1 0 +github.com/muety/wakapi/utils/auth.go:37.65,39.85 2 0 +github.com/muety/wakapi/utils/auth.go:43.2,44.30 2 0 +github.com/muety/wakapi/utils/auth.go:39.85,41.3 1 0 +github.com/muety/wakapi/utils/auth.go:47.94,49.16 2 0 +github.com/muety/wakapi/utils/auth.go:53.2,53.107 1 0 +github.com/muety/wakapi/utils/auth.go:57.2,57.22 1 0 +github.com/muety/wakapi/utils/auth.go:49.16,51.3 1 0 +github.com/muety/wakapi/utils/auth.go:53.107,55.3 1 0 +github.com/muety/wakapi/utils/auth.go:60.56,64.2 3 0 +github.com/muety/wakapi/utils/auth.go:66.55,69.16 3 0 +github.com/muety/wakapi/utils/auth.go:72.2,72.16 1 0 +github.com/muety/wakapi/utils/auth.go:69.16,71.3 1 0 +github.com/muety/wakapi/utils/color.go:8.90,10.32 2 0 +github.com/muety/wakapi/utils/color.go:15.2,15.15 1 0 +github.com/muety/wakapi/utils/color.go:10.32,11.50 1 0 +github.com/muety/wakapi/utils/color.go:11.50,13.4 1 0 github.com/muety/wakapi/utils/summary.go:10.66,11.40 1 0 github.com/muety/wakapi/utils/summary.go:16.2,16.48 1 0 github.com/muety/wakapi/utils/summary.go:11.40,12.27 1 0 @@ -578,70 +582,25 @@ github.com/muety/wakapi/utils/summary.go:130.47,132.3 1 0 github.com/muety/wakapi/utils/summary.go:136.48,140.51 2 0 github.com/muety/wakapi/utils/summary.go:143.2,143.12 1 0 github.com/muety/wakapi/utils/summary.go:140.51,142.3 1 0 -github.com/muety/wakapi/utils/auth.go:16.79,18.54 2 0 -github.com/muety/wakapi/utils/auth.go:22.2,24.16 3 0 -github.com/muety/wakapi/utils/auth.go:28.2,30.45 3 0 -github.com/muety/wakapi/utils/auth.go:33.2,34.32 2 0 -github.com/muety/wakapi/utils/auth.go:18.54,20.3 1 0 -github.com/muety/wakapi/utils/auth.go:24.16,26.3 1 0 -github.com/muety/wakapi/utils/auth.go:30.45,32.3 1 0 -github.com/muety/wakapi/utils/auth.go:37.65,39.85 2 0 -github.com/muety/wakapi/utils/auth.go:43.2,44.30 2 0 -github.com/muety/wakapi/utils/auth.go:39.85,41.3 1 0 -github.com/muety/wakapi/utils/auth.go:47.94,49.16 2 0 -github.com/muety/wakapi/utils/auth.go:53.2,53.107 1 0 -github.com/muety/wakapi/utils/auth.go:57.2,57.22 1 0 -github.com/muety/wakapi/utils/auth.go:49.16,51.3 1 0 -github.com/muety/wakapi/utils/auth.go:53.107,55.3 1 0 -github.com/muety/wakapi/utils/auth.go:60.56,64.2 3 0 -github.com/muety/wakapi/utils/auth.go:66.55,69.16 3 0 -github.com/muety/wakapi/utils/auth.go:72.2,72.16 1 0 -github.com/muety/wakapi/utils/auth.go:69.16,71.3 1 0 -github.com/muety/wakapi/utils/color.go:8.90,10.32 2 0 -github.com/muety/wakapi/utils/color.go:15.2,15.15 1 0 -github.com/muety/wakapi/utils/color.go:10.32,11.50 1 0 -github.com/muety/wakapi/utils/color.go:11.50,13.4 1 0 -github.com/muety/wakapi/middlewares/sentry.go:15.60,16.43 1 0 -github.com/muety/wakapi/middlewares/sentry.go:16.43,20.3 1 0 -github.com/muety/wakapi/middlewares/sentry.go:23.78,26.54 3 0 -github.com/muety/wakapi/middlewares/sentry.go:26.54,27.43 1 0 -github.com/muety/wakapi/middlewares/sentry.go:27.43,29.4 1 0 -github.com/muety/wakapi/middlewares/authenticate.go:30.91,36.2 1 1 -github.com/muety/wakapi/middlewares/authenticate.go:38.90,41.2 2 0 -github.com/muety/wakapi/middlewares/authenticate.go:43.90,46.2 2 0 -github.com/muety/wakapi/middlewares/authenticate.go:48.71,49.71 1 0 -github.com/muety/wakapi/middlewares/authenticate.go:49.71,51.3 1 0 -github.com/muety/wakapi/middlewares/authenticate.go:54.107,58.16 3 0 -github.com/muety/wakapi/middlewares/authenticate.go:61.2,61.16 1 0 -github.com/muety/wakapi/middlewares/authenticate.go:65.2,65.31 1 0 -github.com/muety/wakapi/middlewares/authenticate.go:81.2,82.12 2 0 -github.com/muety/wakapi/middlewares/authenticate.go:58.16,60.3 1 0 -github.com/muety/wakapi/middlewares/authenticate.go:61.16,63.3 1 0 -github.com/muety/wakapi/middlewares/authenticate.go:65.31,66.31 1 0 -github.com/muety/wakapi/middlewares/authenticate.go:71.3,71.29 1 0 -github.com/muety/wakapi/middlewares/authenticate.go:78.3,78.9 1 0 -github.com/muety/wakapi/middlewares/authenticate.go:66.31,69.4 2 0 -github.com/muety/wakapi/middlewares/authenticate.go:71.29,74.4 2 0 -github.com/muety/wakapi/middlewares/authenticate.go:74.9,77.4 2 0 -github.com/muety/wakapi/middlewares/authenticate.go:85.70,86.39 1 0 -github.com/muety/wakapi/middlewares/authenticate.go:91.2,91.14 1 0 -github.com/muety/wakapi/middlewares/authenticate.go:86.39,87.60 1 0 -github.com/muety/wakapi/middlewares/authenticate.go:87.60,89.4 1 0 -github.com/muety/wakapi/middlewares/authenticate.go:94.98,96.16 2 1 -github.com/muety/wakapi/middlewares/authenticate.go:100.2,103.16 4 1 -github.com/muety/wakapi/middlewares/authenticate.go:106.2,106.18 1 1 -github.com/muety/wakapi/middlewares/authenticate.go:96.16,98.3 1 1 -github.com/muety/wakapi/middlewares/authenticate.go:103.16,105.3 1 0 -github.com/muety/wakapi/middlewares/authenticate.go:109.97,113.19 4 1 -github.com/muety/wakapi/middlewares/authenticate.go:116.2,117.16 2 1 -github.com/muety/wakapi/middlewares/authenticate.go:120.2,120.18 1 1 -github.com/muety/wakapi/middlewares/authenticate.go:113.19,115.3 1 1 -github.com/muety/wakapi/middlewares/authenticate.go:117.16,119.3 1 0 -github.com/muety/wakapi/middlewares/authenticate.go:123.92,125.16 2 0 -github.com/muety/wakapi/middlewares/authenticate.go:129.2,130.16 2 0 -github.com/muety/wakapi/middlewares/authenticate.go:137.2,137.18 1 0 -github.com/muety/wakapi/middlewares/authenticate.go:125.16,127.3 1 0 -github.com/muety/wakapi/middlewares/authenticate.go:130.16,132.3 1 0 +github.com/muety/wakapi/utils/template.go:13.41,15.16 2 0 +github.com/muety/wakapi/utils/template.go:18.2,18.23 1 0 +github.com/muety/wakapi/utils/template.go:15.16,17.3 1 0 +github.com/muety/wakapi/utils/template.go:21.37,22.30 1 0 +github.com/muety/wakapi/utils/template.go:25.2,25.10 1 0 +github.com/muety/wakapi/utils/template.go:22.30,24.3 1 0 +github.com/muety/wakapi/utils/template.go:28.83,33.16 4 0 +github.com/muety/wakapi/utils/template.go:37.2,37.29 1 0 +github.com/muety/wakapi/utils/template.go:62.2,62.23 1 0 +github.com/muety/wakapi/utils/template.go:33.16,35.3 1 0 +github.com/muety/wakapi/utils/template.go:37.29,39.51 2 0 +github.com/muety/wakapi/utils/template.go:43.3,44.17 2 0 +github.com/muety/wakapi/utils/template.go:47.3,48.17 2 0 +github.com/muety/wakapi/utils/template.go:52.3,55.17 3 0 +github.com/muety/wakapi/utils/template.go:59.3,59.27 1 0 +github.com/muety/wakapi/utils/template.go:39.51,40.12 1 0 +github.com/muety/wakapi/utils/template.go:44.17,46.4 1 0 +github.com/muety/wakapi/utils/template.go:48.17,50.4 1 0 +github.com/muety/wakapi/utils/template.go:55.17,57.4 1 0 github.com/muety/wakapi/middlewares/filetype.go:13.83,14.43 1 0 github.com/muety/wakapi/middlewares/filetype.go:14.43,19.3 1 0 github.com/muety/wakapi/middlewares/filetype.go:22.84,24.34 2 0 @@ -691,6 +650,47 @@ github.com/muety/wakapi/middlewares/security.go:25.80,26.36 1 0 github.com/muety/wakapi/middlewares/security.go:31.2,31.27 1 0 github.com/muety/wakapi/middlewares/security.go:26.36,27.30 1 0 github.com/muety/wakapi/middlewares/security.go:27.30,29.4 1 0 +github.com/muety/wakapi/middlewares/sentry.go:15.60,16.43 1 0 +github.com/muety/wakapi/middlewares/sentry.go:16.43,20.3 1 0 +github.com/muety/wakapi/middlewares/sentry.go:23.78,26.54 3 0 +github.com/muety/wakapi/middlewares/sentry.go:26.54,27.43 1 0 +github.com/muety/wakapi/middlewares/sentry.go:27.43,29.4 1 0 +github.com/muety/wakapi/middlewares/authenticate.go:30.91,36.2 1 1 +github.com/muety/wakapi/middlewares/authenticate.go:38.90,41.2 2 0 +github.com/muety/wakapi/middlewares/authenticate.go:43.90,46.2 2 0 +github.com/muety/wakapi/middlewares/authenticate.go:48.71,49.71 1 0 +github.com/muety/wakapi/middlewares/authenticate.go:49.71,51.3 1 0 +github.com/muety/wakapi/middlewares/authenticate.go:54.107,58.16 3 0 +github.com/muety/wakapi/middlewares/authenticate.go:61.2,61.16 1 0 +github.com/muety/wakapi/middlewares/authenticate.go:65.2,65.31 1 0 +github.com/muety/wakapi/middlewares/authenticate.go:81.2,82.12 2 0 +github.com/muety/wakapi/middlewares/authenticate.go:58.16,60.3 1 0 +github.com/muety/wakapi/middlewares/authenticate.go:61.16,63.3 1 0 +github.com/muety/wakapi/middlewares/authenticate.go:65.31,66.31 1 0 +github.com/muety/wakapi/middlewares/authenticate.go:71.3,71.29 1 0 +github.com/muety/wakapi/middlewares/authenticate.go:78.3,78.9 1 0 +github.com/muety/wakapi/middlewares/authenticate.go:66.31,69.4 2 0 +github.com/muety/wakapi/middlewares/authenticate.go:71.29,74.4 2 0 +github.com/muety/wakapi/middlewares/authenticate.go:74.9,77.4 2 0 +github.com/muety/wakapi/middlewares/authenticate.go:85.70,86.39 1 0 +github.com/muety/wakapi/middlewares/authenticate.go:91.2,91.14 1 0 +github.com/muety/wakapi/middlewares/authenticate.go:86.39,87.60 1 0 +github.com/muety/wakapi/middlewares/authenticate.go:87.60,89.4 1 0 +github.com/muety/wakapi/middlewares/authenticate.go:94.98,96.16 2 1 +github.com/muety/wakapi/middlewares/authenticate.go:100.2,103.16 4 1 +github.com/muety/wakapi/middlewares/authenticate.go:106.2,106.18 1 1 +github.com/muety/wakapi/middlewares/authenticate.go:96.16,98.3 1 1 +github.com/muety/wakapi/middlewares/authenticate.go:103.16,105.3 1 0 +github.com/muety/wakapi/middlewares/authenticate.go:109.97,113.19 4 1 +github.com/muety/wakapi/middlewares/authenticate.go:116.2,117.16 2 1 +github.com/muety/wakapi/middlewares/authenticate.go:120.2,120.18 1 1 +github.com/muety/wakapi/middlewares/authenticate.go:113.19,115.3 1 1 +github.com/muety/wakapi/middlewares/authenticate.go:117.16,119.3 1 0 +github.com/muety/wakapi/middlewares/authenticate.go:123.92,125.16 2 0 +github.com/muety/wakapi/middlewares/authenticate.go:129.2,130.16 2 0 +github.com/muety/wakapi/middlewares/authenticate.go:137.2,137.18 1 0 +github.com/muety/wakapi/middlewares/authenticate.go:125.16,127.3 1 0 +github.com/muety/wakapi/middlewares/authenticate.go:130.16,132.3 1 0 github.com/muety/wakapi/routes/compat/shields/v1/badge.go:25.112,32.2 1 0 github.com/muety/wakapi/routes/compat/shields/v1/badge.go:34.59,38.2 2 0 github.com/muety/wakapi/routes/compat/shields/v1/badge.go:50.68,52.16 2 0 @@ -709,6 +709,190 @@ github.com/muety/wakapi/routes/compat/shields/v1/badge.go:118.2,118.36 1 0 github.com/muety/wakapi/routes/compat/shields/v1/badge.go:91.16,93.3 1 0 github.com/muety/wakapi/routes/compat/shields/v1/badge.go:102.29,104.3 1 0 github.com/muety/wakapi/routes/compat/shields/v1/badge.go:114.16,116.3 1 0 +github.com/muety/wakapi/services/user.go:25.99,35.33 3 0 +github.com/muety/wakapi/services/user.go:56.2,56.12 1 0 +github.com/muety/wakapi/services/user.go:35.33,36.31 1 0 +github.com/muety/wakapi/services/user.go:36.31,42.73 4 0 +github.com/muety/wakapi/services/user.go:46.4,46.24 1 0 +github.com/muety/wakapi/services/user.go:42.73,44.5 1 0 +github.com/muety/wakapi/services/user.go:46.24,47.80 1 0 +github.com/muety/wakapi/services/user.go:47.80,49.6 1 0 +github.com/muety/wakapi/services/user.go:49.11,51.6 1 0 +github.com/muety/wakapi/services/user.go:59.74,60.40 1 0 +github.com/muety/wakapi/services/user.go:64.2,65.16 2 0 +github.com/muety/wakapi/services/user.go:69.2,70.15 2 0 +github.com/muety/wakapi/services/user.go:60.40,62.3 1 0 +github.com/muety/wakapi/services/user.go:65.16,67.3 1 0 +github.com/muety/wakapi/services/user.go:73.72,74.37 1 0 +github.com/muety/wakapi/services/user.go:78.2,79.16 2 0 +github.com/muety/wakapi/services/user.go:83.2,84.15 2 0 +github.com/muety/wakapi/services/user.go:74.37,76.3 1 0 +github.com/muety/wakapi/services/user.go:79.16,81.3 1 0 +github.com/muety/wakapi/services/user.go:87.76,89.2 1 0 +github.com/muety/wakapi/services/user.go:91.86,93.2 1 0 +github.com/muety/wakapi/services/user.go:95.58,97.2 1 0 +github.com/muety/wakapi/services/user.go:99.86,101.2 1 0 +github.com/muety/wakapi/services/user.go:103.71,105.12 2 0 +github.com/muety/wakapi/services/user.go:109.2,110.42 2 0 +github.com/muety/wakapi/services/user.go:114.2,115.16 2 0 +github.com/muety/wakapi/services/user.go:119.2,120.21 2 0 +github.com/muety/wakapi/services/user.go:105.12,107.3 1 0 +github.com/muety/wakapi/services/user.go:110.42,112.3 1 0 +github.com/muety/wakapi/services/user.go:115.16,117.3 1 0 +github.com/muety/wakapi/services/user.go:123.48,125.2 1 0 +github.com/muety/wakapi/services/user.go:127.102,137.93 2 0 +github.com/muety/wakapi/services/user.go:143.2,143.38 1 0 +github.com/muety/wakapi/services/user.go:137.93,139.3 1 0 +github.com/muety/wakapi/services/user.go:139.8,141.3 1 0 +github.com/muety/wakapi/services/user.go:146.73,150.2 3 0 +github.com/muety/wakapi/services/user.go:152.78,156.2 3 0 +github.com/muety/wakapi/services/user.go:158.122,161.35 2 0 +github.com/muety/wakapi/services/user.go:167.2,167.35 1 0 +github.com/muety/wakapi/services/user.go:171.2,171.18 1 0 +github.com/muety/wakapi/services/user.go:161.35,162.89 1 0 +github.com/muety/wakapi/services/user.go:162.89,164.4 1 0 +github.com/muety/wakapi/services/user.go:167.35,169.3 1 0 +github.com/muety/wakapi/services/user.go:174.106,177.96 3 0 +github.com/muety/wakapi/services/user.go:182.2,182.68 1 0 +github.com/muety/wakapi/services/user.go:177.96,179.3 1 0 +github.com/muety/wakapi/services/user.go:179.8,181.3 1 0 +github.com/muety/wakapi/services/user.go:185.85,187.2 1 0 +github.com/muety/wakapi/services/user.go:189.57,196.2 4 0 +github.com/muety/wakapi/services/user.go:198.38,200.2 1 0 +github.com/muety/wakapi/services/user.go:202.57,207.2 1 0 +github.com/muety/wakapi/services/aggregation.go:30.142,38.2 1 0 +github.com/muety/wakapi/services/aggregation.go:47.43,49.64 1 0 +github.com/muety/wakapi/services/aggregation.go:53.2,55.19 3 0 +github.com/muety/wakapi/services/aggregation.go:49.64,51.3 1 0 +github.com/muety/wakapi/services/aggregation.go:58.77,59.47 1 0 +github.com/muety/wakapi/services/aggregation.go:62.2,67.40 4 0 +github.com/muety/wakapi/services/aggregation.go:71.2,71.50 1 0 +github.com/muety/wakapi/services/aggregation.go:76.2,76.60 1 0 +github.com/muety/wakapi/services/aggregation.go:82.2,82.35 1 0 +github.com/muety/wakapi/services/aggregation.go:59.47,61.3 1 0 +github.com/muety/wakapi/services/aggregation.go:67.40,69.3 1 0 +github.com/muety/wakapi/services/aggregation.go:71.50,73.3 1 0 +github.com/muety/wakapi/services/aggregation.go:76.60,80.3 3 0 +github.com/muety/wakapi/services/aggregation.go:85.109,86.24 1 0 +github.com/muety/wakapi/services/aggregation.go:86.24,87.116 1 0 +github.com/muety/wakapi/services/aggregation.go:87.116,89.4 1 0 +github.com/muety/wakapi/services/aggregation.go:89.9,92.4 2 0 +github.com/muety/wakapi/services/aggregation.go:96.80,97.33 1 0 +github.com/muety/wakapi/services/aggregation.go:97.33,98.60 1 0 +github.com/muety/wakapi/services/aggregation.go:98.60,100.4 1 0 +github.com/muety/wakapi/services/aggregation.go:104.110,109.16 3 0 +github.com/muety/wakapi/services/aggregation.go:115.2,116.16 2 0 +github.com/muety/wakapi/services/aggregation.go:122.2,123.44 2 0 +github.com/muety/wakapi/services/aggregation.go:128.2,128.41 1 0 +github.com/muety/wakapi/services/aggregation.go:146.2,146.12 1 0 +github.com/muety/wakapi/services/aggregation.go:109.16,112.3 2 0 +github.com/muety/wakapi/services/aggregation.go:116.16,119.3 2 0 +github.com/muety/wakapi/services/aggregation.go:123.44,125.3 1 0 +github.com/muety/wakapi/services/aggregation.go:128.41,129.71 1 0 +github.com/muety/wakapi/services/aggregation.go:133.3,133.21 1 0 +github.com/muety/wakapi/services/aggregation.go:129.71,130.12 1 0 +github.com/muety/wakapi/services/aggregation.go:133.21,137.4 1 0 +github.com/muety/wakapi/services/aggregation.go:137.9,137.62 1 0 +github.com/muety/wakapi/services/aggregation.go:137.62,141.4 1 0 +github.com/muety/wakapi/services/aggregation.go:149.83,152.27 3 0 +github.com/muety/wakapi/services/aggregation.go:157.2,158.12 2 0 +github.com/muety/wakapi/services/aggregation.go:152.27,153.34 1 0 +github.com/muety/wakapi/services/aggregation.go:153.34,155.4 1 0 +github.com/muety/wakapi/services/aggregation.go:161.79,164.27 3 0 +github.com/muety/wakapi/services/aggregation.go:164.27,166.3 1 0 +github.com/muety/wakapi/services/aggregation.go:169.83,184.41 5 0 +github.com/muety/wakapi/services/aggregation.go:184.41,194.3 3 0 +github.com/muety/wakapi/services/aggregation.go:197.34,200.2 2 0 +github.com/muety/wakapi/services/alias.go:19.77,24.2 1 1 +github.com/muety/wakapi/services/alias.go:28.60,29.43 1 1 +github.com/muety/wakapi/services/alias.go:32.2,32.14 1 1 +github.com/muety/wakapi/services/alias.go:29.43,31.3 1 1 +github.com/muety/wakapi/services/alias.go:35.62,37.16 2 1 +github.com/muety/wakapi/services/alias.go:40.2,40.12 1 1 +github.com/muety/wakapi/services/alias.go:37.16,39.3 1 1 +github.com/muety/wakapi/services/alias.go:43.59,44.51 1 1 +github.com/muety/wakapi/services/alias.go:44.51,46.3 1 0 +github.com/muety/wakapi/services/alias.go:49.76,50.32 1 0 +github.com/muety/wakapi/services/alias.go:53.2,53.49 1 0 +github.com/muety/wakapi/services/alias.go:50.32,52.3 1 0 +github.com/muety/wakapi/services/alias.go:53.49,55.3 1 0 +github.com/muety/wakapi/services/alias.go:55.8,57.3 1 0 +github.com/muety/wakapi/services/alias.go:60.102,61.38 1 0 +github.com/muety/wakapi/services/alias.go:64.2,64.39 1 0 +github.com/muety/wakapi/services/alias.go:61.38,63.3 1 0 +github.com/muety/wakapi/services/alias.go:67.113,68.38 1 0 +github.com/muety/wakapi/services/alias.go:71.2,71.39 1 0 +github.com/muety/wakapi/services/alias.go:68.38,70.3 1 0 +github.com/muety/wakapi/services/alias.go:74.108,75.32 1 1 +github.com/muety/wakapi/services/alias.go:79.2,79.49 1 1 +github.com/muety/wakapi/services/alias.go:87.2,87.19 1 1 +github.com/muety/wakapi/services/alias.go:75.32,77.3 1 1 +github.com/muety/wakapi/services/alias.go:79.49,80.47 1 1 +github.com/muety/wakapi/services/alias.go:80.47,81.49 1 1 +github.com/muety/wakapi/services/alias.go:81.49,83.5 1 1 +github.com/muety/wakapi/services/alias.go:90.77,92.16 2 0 +github.com/muety/wakapi/services/alias.go:96.2,100.20 3 0 +github.com/muety/wakapi/services/alias.go:92.16,94.3 1 0 +github.com/muety/wakapi/services/alias.go:103.60,104.24 1 0 +github.com/muety/wakapi/services/alias.go:107.2,110.16 2 0 +github.com/muety/wakapi/services/alias.go:114.2,116.12 2 0 +github.com/muety/wakapi/services/alias.go:104.24,106.3 1 0 +github.com/muety/wakapi/services/alias.go:110.16,112.3 1 0 +github.com/muety/wakapi/services/alias.go:119.69,123.28 3 0 +github.com/muety/wakapi/services/alias.go:131.2,134.16 2 0 +github.com/muety/wakapi/services/alias.go:140.2,140.31 1 0 +github.com/muety/wakapi/services/alias.go:144.2,144.12 1 0 +github.com/muety/wakapi/services/alias.go:123.28,124.21 1 0 +github.com/muety/wakapi/services/alias.go:127.3,128.16 2 0 +github.com/muety/wakapi/services/alias.go:124.21,126.4 1 0 +github.com/muety/wakapi/services/alias.go:134.16,135.29 1 0 +github.com/muety/wakapi/services/alias.go:135.29,137.4 1 0 +github.com/muety/wakapi/services/alias.go:140.31,142.3 1 0 +github.com/muety/wakapi/services/alias.go:147.74,148.14 1 0 +github.com/muety/wakapi/services/alias.go:148.14,149.57 1 0 +github.com/muety/wakapi/services/alias.go:149.57,153.4 3 0 +github.com/muety/wakapi/services/alias.go:154.8,155.57 1 0 +github.com/muety/wakapi/services/alias.go:155.57,157.48 2 0 +github.com/muety/wakapi/services/alias.go:162.4,162.52 1 0 +github.com/muety/wakapi/services/alias.go:157.48,158.26 1 0 +github.com/muety/wakapi/services/alias.go:158.26,160.6 1 0 +github.com/muety/wakapi/services/alias.go:167.116,168.32 1 0 +github.com/muety/wakapi/services/alias.go:171.2,171.49 1 0 +github.com/muety/wakapi/services/alias.go:168.32,170.3 1 0 +github.com/muety/wakapi/services/alias.go:171.49,173.47 2 0 +github.com/muety/wakapi/services/alias.go:178.3,178.30 1 0 +github.com/muety/wakapi/services/alias.go:173.47,174.16 1 0 +github.com/muety/wakapi/services/alias.go:174.16,176.5 1 0 +github.com/muety/wakapi/services/alias.go:179.8,181.3 1 0 +github.com/muety/wakapi/services/duration.go:17.78,23.2 2 1 +github.com/muety/wakapi/services/duration.go:25.123,28.42 2 1 +github.com/muety/wakapi/services/duration.go:34.2,35.16 2 1 +github.com/muety/wakapi/services/duration.go:42.2,47.31 4 1 +github.com/muety/wakapi/services/duration.go:95.2,97.31 2 1 +github.com/muety/wakapi/services/duration.go:110.2,110.49 1 1 +github.com/muety/wakapi/services/duration.go:114.2,114.32 1 1 +github.com/muety/wakapi/services/duration.go:28.42,29.90 1 1 +github.com/muety/wakapi/services/duration.go:29.90,31.4 1 1 +github.com/muety/wakapi/services/duration.go:35.16,37.3 1 0 +github.com/muety/wakapi/services/duration.go:47.31,48.42 1 1 +github.com/muety/wakapi/services/duration.go:52.3,54.62 2 1 +github.com/muety/wakapi/services/duration.go:58.3,58.20 1 1 +github.com/muety/wakapi/services/duration.go:63.3,73.15 3 1 +github.com/muety/wakapi/services/duration.go:76.3,82.84 2 1 +github.com/muety/wakapi/services/duration.go:92.3,92.10 1 1 +github.com/muety/wakapi/services/duration.go:48.42,49.12 1 1 +github.com/muety/wakapi/services/duration.go:54.62,56.4 1 1 +github.com/muety/wakapi/services/duration.go:58.20,60.12 2 1 +github.com/muety/wakapi/services/duration.go:73.15,75.4 1 0 +github.com/muety/wakapi/services/duration.go:82.84,84.41 2 1 +github.com/muety/wakapi/services/duration.go:87.4,87.15 1 1 +github.com/muety/wakapi/services/duration.go:84.41,86.5 1 1 +github.com/muety/wakapi/services/duration.go:88.9,90.4 1 1 +github.com/muety/wakapi/services/duration.go:97.31,98.26 1 1 +github.com/muety/wakapi/services/duration.go:98.26,103.23 1 1 +github.com/muety/wakapi/services/duration.go:106.4,106.36 1 1 +github.com/muety/wakapi/services/duration.go:103.23,105.5 1 1 +github.com/muety/wakapi/services/duration.go:110.49,112.3 1 1 github.com/muety/wakapi/services/heartbeat.go:26.141,40.33 3 0 github.com/muety/wakapi/services/heartbeat.go:48.2,48.12 1 0 github.com/muety/wakapi/services/heartbeat.go:40.33,41.31 1 0 @@ -778,6 +962,60 @@ github.com/muety/wakapi/services/heartbeat.go:255.94,257.42 2 0 github.com/muety/wakapi/services/heartbeat.go:263.2,263.18 1 0 github.com/muety/wakapi/services/heartbeat.go:257.42,259.18 2 0 github.com/muety/wakapi/services/heartbeat.go:259.18,261.4 1 0 +github.com/muety/wakapi/services/key_value.go:14.89,19.2 1 0 +github.com/muety/wakapi/services/key_value.go:21.83,23.2 1 0 +github.com/muety/wakapi/services/key_value.go:25.78,27.16 2 0 +github.com/muety/wakapi/services/key_value.go:33.2,33.11 1 0 +github.com/muety/wakapi/services/key_value.go:27.16,32.3 1 0 +github.com/muety/wakapi/services/key_value.go:36.72,38.2 1 0 +github.com/muety/wakapi/services/key_value.go:40.60,42.2 1 0 +github.com/muety/wakapi/services/project_label.go:21.111,28.2 1 0 +github.com/muety/wakapi/services/project_label.go:30.80,32.2 1 0 +github.com/muety/wakapi/services/project_label.go:34.90,35.51 1 0 +github.com/muety/wakapi/services/project_label.go:39.2,40.16 2 0 +github.com/muety/wakapi/services/project_label.go:43.2,44.20 2 0 +github.com/muety/wakapi/services/project_label.go:35.51,37.3 1 0 +github.com/muety/wakapi/services/project_label.go:40.16,42.3 1 0 +github.com/muety/wakapi/services/project_label.go:48.108,50.16 2 0 +github.com/muety/wakapi/services/project_label.go:53.2,53.112 1 0 +github.com/muety/wakapi/services/project_label.go:56.2,56.26 1 0 +github.com/muety/wakapi/services/project_label.go:50.16,52.3 1 0 +github.com/muety/wakapi/services/project_label.go:53.112,55.3 1 0 +github.com/muety/wakapi/services/project_label.go:60.116,62.16 2 0 +github.com/muety/wakapi/services/project_label.go:65.2,65.112 1 0 +github.com/muety/wakapi/services/project_label.go:68.2,68.26 1 0 +github.com/muety/wakapi/services/project_label.go:62.16,64.3 1 0 +github.com/muety/wakapi/services/project_label.go:65.112,67.3 1 0 +github.com/muety/wakapi/services/project_label.go:71.98,73.16 2 0 +github.com/muety/wakapi/services/project_label.go:77.2,79.20 3 0 +github.com/muety/wakapi/services/project_label.go:73.16,75.3 1 0 +github.com/muety/wakapi/services/project_label.go:82.74,83.24 1 0 +github.com/muety/wakapi/services/project_label.go:86.2,89.12 4 0 +github.com/muety/wakapi/services/project_label.go:83.24,85.3 1 0 +github.com/muety/wakapi/services/project_label.go:92.89,94.14 2 0 +github.com/muety/wakapi/services/project_label.go:97.2,100.4 1 0 +github.com/muety/wakapi/services/project_label.go:94.14,96.3 1 0 +github.com/muety/wakapi/services/diagnostics.go:14.101,19.2 1 0 +github.com/muety/wakapi/services/diagnostics.go:21.101,23.2 1 0 +github.com/muety/wakapi/services/language_mapping.go:18.118,24.2 1 0 +github.com/muety/wakapi/services/language_mapping.go:26.86,28.2 1 0 +github.com/muety/wakapi/services/language_mapping.go:30.96,31.53 1 0 +github.com/muety/wakapi/services/language_mapping.go:35.2,36.16 2 0 +github.com/muety/wakapi/services/language_mapping.go:39.2,40.22 2 0 +github.com/muety/wakapi/services/language_mapping.go:31.53,33.3 1 0 +github.com/muety/wakapi/services/language_mapping.go:36.16,38.3 1 0 +github.com/muety/wakapi/services/language_mapping.go:43.92,46.16 3 0 +github.com/muety/wakapi/services/language_mapping.go:50.2,50.33 1 0 +github.com/muety/wakapi/services/language_mapping.go:53.2,53.22 1 0 +github.com/muety/wakapi/services/language_mapping.go:46.16,48.3 1 0 +github.com/muety/wakapi/services/language_mapping.go:50.33,52.3 1 0 +github.com/muety/wakapi/services/language_mapping.go:56.109,58.16 2 0 +github.com/muety/wakapi/services/language_mapping.go:62.2,63.20 2 0 +github.com/muety/wakapi/services/language_mapping.go:58.16,60.3 1 0 +github.com/muety/wakapi/services/language_mapping.go:66.82,67.26 1 0 +github.com/muety/wakapi/services/language_mapping.go:70.2,72.12 3 0 +github.com/muety/wakapi/services/language_mapping.go:67.26,69.3 1 0 +github.com/muety/wakapi/services/language_mapping.go:75.74,78.2 1 0 github.com/muety/wakapi/services/misc.go:21.126,28.2 1 0 github.com/muety/wakapi/services/misc.go:40.50,42.48 1 0 github.com/muety/wakapi/services/misc.go:46.2,48.19 3 0 @@ -828,201 +1066,6 @@ github.com/muety/wakapi/services/report.go:145.2,145.12 1 0 github.com/muety/wakapi/services/report.go:138.41,139.30 1 0 github.com/muety/wakapi/services/report.go:139.30,140.16 1 0 github.com/muety/wakapi/services/report.go:140.16,142.5 1 0 -github.com/muety/wakapi/services/user.go:25.99,35.33 3 0 -github.com/muety/wakapi/services/user.go:56.2,56.12 1 0 -github.com/muety/wakapi/services/user.go:35.33,36.31 1 0 -github.com/muety/wakapi/services/user.go:36.31,42.73 4 0 -github.com/muety/wakapi/services/user.go:46.4,46.24 1 0 -github.com/muety/wakapi/services/user.go:42.73,44.5 1 0 -github.com/muety/wakapi/services/user.go:46.24,47.80 1 0 -github.com/muety/wakapi/services/user.go:47.80,49.6 1 0 -github.com/muety/wakapi/services/user.go:49.11,51.6 1 0 -github.com/muety/wakapi/services/user.go:59.74,60.40 1 0 -github.com/muety/wakapi/services/user.go:64.2,65.16 2 0 -github.com/muety/wakapi/services/user.go:69.2,70.15 2 0 -github.com/muety/wakapi/services/user.go:60.40,62.3 1 0 -github.com/muety/wakapi/services/user.go:65.16,67.3 1 0 -github.com/muety/wakapi/services/user.go:73.72,74.37 1 0 -github.com/muety/wakapi/services/user.go:78.2,79.16 2 0 -github.com/muety/wakapi/services/user.go:83.2,84.15 2 0 -github.com/muety/wakapi/services/user.go:74.37,76.3 1 0 -github.com/muety/wakapi/services/user.go:79.16,81.3 1 0 -github.com/muety/wakapi/services/user.go:87.76,89.2 1 0 -github.com/muety/wakapi/services/user.go:91.86,93.2 1 0 -github.com/muety/wakapi/services/user.go:95.58,97.2 1 0 -github.com/muety/wakapi/services/user.go:99.86,101.2 1 0 -github.com/muety/wakapi/services/user.go:103.71,105.12 2 0 -github.com/muety/wakapi/services/user.go:109.2,110.42 2 0 -github.com/muety/wakapi/services/user.go:114.2,115.16 2 0 -github.com/muety/wakapi/services/user.go:119.2,120.21 2 0 -github.com/muety/wakapi/services/user.go:105.12,107.3 1 0 -github.com/muety/wakapi/services/user.go:110.42,112.3 1 0 -github.com/muety/wakapi/services/user.go:115.16,117.3 1 0 -github.com/muety/wakapi/services/user.go:123.48,125.2 1 0 -github.com/muety/wakapi/services/user.go:127.102,137.93 2 0 -github.com/muety/wakapi/services/user.go:143.2,143.38 1 0 -github.com/muety/wakapi/services/user.go:137.93,139.3 1 0 -github.com/muety/wakapi/services/user.go:139.8,141.3 1 0 -github.com/muety/wakapi/services/user.go:146.73,150.2 3 0 -github.com/muety/wakapi/services/user.go:152.78,156.2 3 0 -github.com/muety/wakapi/services/user.go:158.122,161.35 2 0 -github.com/muety/wakapi/services/user.go:167.2,167.35 1 0 -github.com/muety/wakapi/services/user.go:171.2,171.18 1 0 -github.com/muety/wakapi/services/user.go:161.35,162.89 1 0 -github.com/muety/wakapi/services/user.go:162.89,164.4 1 0 -github.com/muety/wakapi/services/user.go:167.35,169.3 1 0 -github.com/muety/wakapi/services/user.go:174.106,177.96 3 0 -github.com/muety/wakapi/services/user.go:182.2,182.68 1 0 -github.com/muety/wakapi/services/user.go:177.96,179.3 1 0 -github.com/muety/wakapi/services/user.go:179.8,181.3 1 0 -github.com/muety/wakapi/services/user.go:185.85,187.2 1 0 -github.com/muety/wakapi/services/user.go:189.57,196.2 4 0 -github.com/muety/wakapi/services/user.go:198.38,200.2 1 0 -github.com/muety/wakapi/services/user.go:202.57,207.2 1 0 -github.com/muety/wakapi/services/duration.go:16.78,22.2 2 1 -github.com/muety/wakapi/services/duration.go:24.123,27.42 2 1 -github.com/muety/wakapi/services/duration.go:33.2,34.16 2 1 -github.com/muety/wakapi/services/duration.go:41.2,46.31 4 1 -github.com/muety/wakapi/services/duration.go:81.2,83.31 2 1 -github.com/muety/wakapi/services/duration.go:96.2,96.49 1 1 -github.com/muety/wakapi/services/duration.go:100.2,100.32 1 1 -github.com/muety/wakapi/services/duration.go:27.42,28.90 1 1 -github.com/muety/wakapi/services/duration.go:28.90,30.4 1 1 -github.com/muety/wakapi/services/duration.go:34.16,36.3 1 0 -github.com/muety/wakapi/services/duration.go:46.31,47.42 1 1 -github.com/muety/wakapi/services/duration.go:51.3,53.62 2 1 -github.com/muety/wakapi/services/duration.go:57.3,57.20 1 1 -github.com/muety/wakapi/services/duration.go:62.3,63.35 2 1 -github.com/muety/wakapi/services/duration.go:66.3,68.72 2 1 -github.com/muety/wakapi/services/duration.go:78.3,78.10 1 1 -github.com/muety/wakapi/services/duration.go:47.42,48.12 1 1 -github.com/muety/wakapi/services/duration.go:53.62,55.4 1 1 -github.com/muety/wakapi/services/duration.go:57.20,59.12 2 1 -github.com/muety/wakapi/services/duration.go:63.35,65.4 1 1 -github.com/muety/wakapi/services/duration.go:68.72,70.41 2 1 -github.com/muety/wakapi/services/duration.go:73.4,73.15 1 1 -github.com/muety/wakapi/services/duration.go:70.41,72.5 1 1 -github.com/muety/wakapi/services/duration.go:74.9,76.4 1 1 -github.com/muety/wakapi/services/duration.go:83.31,84.26 1 1 -github.com/muety/wakapi/services/duration.go:84.26,89.23 1 1 -github.com/muety/wakapi/services/duration.go:92.4,92.36 1 1 -github.com/muety/wakapi/services/duration.go:89.23,91.5 1 1 -github.com/muety/wakapi/services/duration.go:96.49,98.3 1 1 -github.com/muety/wakapi/services/alias.go:19.77,24.2 1 1 -github.com/muety/wakapi/services/alias.go:28.60,29.43 1 1 -github.com/muety/wakapi/services/alias.go:32.2,32.14 1 1 -github.com/muety/wakapi/services/alias.go:29.43,31.3 1 1 -github.com/muety/wakapi/services/alias.go:35.62,37.16 2 1 -github.com/muety/wakapi/services/alias.go:40.2,40.12 1 1 -github.com/muety/wakapi/services/alias.go:37.16,39.3 1 1 -github.com/muety/wakapi/services/alias.go:43.59,44.51 1 1 -github.com/muety/wakapi/services/alias.go:44.51,46.3 1 0 -github.com/muety/wakapi/services/alias.go:49.76,50.32 1 0 -github.com/muety/wakapi/services/alias.go:53.2,53.49 1 0 -github.com/muety/wakapi/services/alias.go:50.32,52.3 1 0 -github.com/muety/wakapi/services/alias.go:53.49,55.3 1 0 -github.com/muety/wakapi/services/alias.go:55.8,57.3 1 0 -github.com/muety/wakapi/services/alias.go:60.102,61.38 1 0 -github.com/muety/wakapi/services/alias.go:64.2,64.39 1 0 -github.com/muety/wakapi/services/alias.go:61.38,63.3 1 0 -github.com/muety/wakapi/services/alias.go:67.113,68.38 1 0 -github.com/muety/wakapi/services/alias.go:71.2,71.39 1 0 -github.com/muety/wakapi/services/alias.go:68.38,70.3 1 0 -github.com/muety/wakapi/services/alias.go:74.108,75.32 1 1 -github.com/muety/wakapi/services/alias.go:79.2,79.49 1 1 -github.com/muety/wakapi/services/alias.go:87.2,87.19 1 1 -github.com/muety/wakapi/services/alias.go:75.32,77.3 1 1 -github.com/muety/wakapi/services/alias.go:79.49,80.47 1 1 -github.com/muety/wakapi/services/alias.go:80.47,81.49 1 1 -github.com/muety/wakapi/services/alias.go:81.49,83.5 1 1 -github.com/muety/wakapi/services/alias.go:90.77,92.16 2 0 -github.com/muety/wakapi/services/alias.go:96.2,100.20 3 0 -github.com/muety/wakapi/services/alias.go:92.16,94.3 1 0 -github.com/muety/wakapi/services/alias.go:103.60,104.24 1 0 -github.com/muety/wakapi/services/alias.go:107.2,110.16 2 0 -github.com/muety/wakapi/services/alias.go:114.2,116.12 2 0 -github.com/muety/wakapi/services/alias.go:104.24,106.3 1 0 -github.com/muety/wakapi/services/alias.go:110.16,112.3 1 0 -github.com/muety/wakapi/services/alias.go:119.69,123.28 3 0 -github.com/muety/wakapi/services/alias.go:131.2,134.16 2 0 -github.com/muety/wakapi/services/alias.go:140.2,140.31 1 0 -github.com/muety/wakapi/services/alias.go:144.2,144.12 1 0 -github.com/muety/wakapi/services/alias.go:123.28,124.21 1 0 -github.com/muety/wakapi/services/alias.go:127.3,128.16 2 0 -github.com/muety/wakapi/services/alias.go:124.21,126.4 1 0 -github.com/muety/wakapi/services/alias.go:134.16,135.29 1 0 -github.com/muety/wakapi/services/alias.go:135.29,137.4 1 0 -github.com/muety/wakapi/services/alias.go:140.31,142.3 1 0 -github.com/muety/wakapi/services/alias.go:147.74,148.14 1 0 -github.com/muety/wakapi/services/alias.go:148.14,149.57 1 0 -github.com/muety/wakapi/services/alias.go:149.57,153.4 3 0 -github.com/muety/wakapi/services/alias.go:154.8,155.57 1 0 -github.com/muety/wakapi/services/alias.go:155.57,157.48 2 0 -github.com/muety/wakapi/services/alias.go:162.4,162.52 1 0 -github.com/muety/wakapi/services/alias.go:157.48,158.26 1 0 -github.com/muety/wakapi/services/alias.go:158.26,160.6 1 0 -github.com/muety/wakapi/services/alias.go:167.116,168.32 1 0 -github.com/muety/wakapi/services/alias.go:171.2,171.49 1 0 -github.com/muety/wakapi/services/alias.go:168.32,170.3 1 0 -github.com/muety/wakapi/services/alias.go:171.49,173.47 2 0 -github.com/muety/wakapi/services/alias.go:178.3,178.30 1 0 -github.com/muety/wakapi/services/alias.go:173.47,174.16 1 0 -github.com/muety/wakapi/services/alias.go:174.16,176.5 1 0 -github.com/muety/wakapi/services/alias.go:179.8,181.3 1 0 -github.com/muety/wakapi/services/diagnostics.go:14.101,19.2 1 0 -github.com/muety/wakapi/services/diagnostics.go:21.101,23.2 1 0 -github.com/muety/wakapi/services/key_value.go:14.89,19.2 1 0 -github.com/muety/wakapi/services/key_value.go:21.83,23.2 1 0 -github.com/muety/wakapi/services/key_value.go:25.78,27.16 2 0 -github.com/muety/wakapi/services/key_value.go:33.2,33.11 1 0 -github.com/muety/wakapi/services/key_value.go:27.16,32.3 1 0 -github.com/muety/wakapi/services/key_value.go:36.72,38.2 1 0 -github.com/muety/wakapi/services/key_value.go:40.60,42.2 1 0 -github.com/muety/wakapi/services/language_mapping.go:18.118,24.2 1 0 -github.com/muety/wakapi/services/language_mapping.go:26.86,28.2 1 0 -github.com/muety/wakapi/services/language_mapping.go:30.96,31.53 1 0 -github.com/muety/wakapi/services/language_mapping.go:35.2,36.16 2 0 -github.com/muety/wakapi/services/language_mapping.go:39.2,40.22 2 0 -github.com/muety/wakapi/services/language_mapping.go:31.53,33.3 1 0 -github.com/muety/wakapi/services/language_mapping.go:36.16,38.3 1 0 -github.com/muety/wakapi/services/language_mapping.go:43.92,46.16 3 0 -github.com/muety/wakapi/services/language_mapping.go:50.2,50.33 1 0 -github.com/muety/wakapi/services/language_mapping.go:53.2,53.22 1 0 -github.com/muety/wakapi/services/language_mapping.go:46.16,48.3 1 0 -github.com/muety/wakapi/services/language_mapping.go:50.33,52.3 1 0 -github.com/muety/wakapi/services/language_mapping.go:56.109,58.16 2 0 -github.com/muety/wakapi/services/language_mapping.go:62.2,63.20 2 0 -github.com/muety/wakapi/services/language_mapping.go:58.16,60.3 1 0 -github.com/muety/wakapi/services/language_mapping.go:66.82,67.26 1 0 -github.com/muety/wakapi/services/language_mapping.go:70.2,72.12 3 0 -github.com/muety/wakapi/services/language_mapping.go:67.26,69.3 1 0 -github.com/muety/wakapi/services/language_mapping.go:75.74,78.2 1 0 -github.com/muety/wakapi/services/project_label.go:21.111,28.2 1 0 -github.com/muety/wakapi/services/project_label.go:30.80,32.2 1 0 -github.com/muety/wakapi/services/project_label.go:34.90,35.51 1 0 -github.com/muety/wakapi/services/project_label.go:39.2,40.16 2 0 -github.com/muety/wakapi/services/project_label.go:43.2,44.20 2 0 -github.com/muety/wakapi/services/project_label.go:35.51,37.3 1 0 -github.com/muety/wakapi/services/project_label.go:40.16,42.3 1 0 -github.com/muety/wakapi/services/project_label.go:48.108,50.16 2 0 -github.com/muety/wakapi/services/project_label.go:53.2,53.112 1 0 -github.com/muety/wakapi/services/project_label.go:56.2,56.26 1 0 -github.com/muety/wakapi/services/project_label.go:50.16,52.3 1 0 -github.com/muety/wakapi/services/project_label.go:53.112,55.3 1 0 -github.com/muety/wakapi/services/project_label.go:60.116,62.16 2 0 -github.com/muety/wakapi/services/project_label.go:65.2,65.112 1 0 -github.com/muety/wakapi/services/project_label.go:68.2,68.26 1 0 -github.com/muety/wakapi/services/project_label.go:62.16,64.3 1 0 -github.com/muety/wakapi/services/project_label.go:65.112,67.3 1 0 -github.com/muety/wakapi/services/project_label.go:71.98,73.16 2 0 -github.com/muety/wakapi/services/project_label.go:77.2,79.20 3 0 -github.com/muety/wakapi/services/project_label.go:73.16,75.3 1 0 -github.com/muety/wakapi/services/project_label.go:82.74,83.24 1 0 -github.com/muety/wakapi/services/project_label.go:86.2,89.12 4 0 -github.com/muety/wakapi/services/project_label.go:83.24,85.3 1 0 -github.com/muety/wakapi/services/project_label.go:92.89,94.14 2 0 -github.com/muety/wakapi/services/project_label.go:97.2,100.4 1 0 -github.com/muety/wakapi/services/project_label.go:94.14,96.3 1 0 github.com/muety/wakapi/services/summary.go:30.189,42.33 3 1 github.com/muety/wakapi/services/summary.go:53.2,53.12 1 1 github.com/muety/wakapi/services/summary.go:42.33,43.31 1 1 @@ -1153,46 +1196,3 @@ github.com/muety/wakapi/services/summary.go:475.3,475.24 1 1 github.com/muety/wakapi/services/summary.go:466.17,467.33 1 1 github.com/muety/wakapi/services/summary.go:467.33,469.5 1 1 github.com/muety/wakapi/services/summary.go:472.28,474.4 1 1 -github.com/muety/wakapi/services/aggregation.go:30.142,38.2 1 0 -github.com/muety/wakapi/services/aggregation.go:47.43,49.64 1 0 -github.com/muety/wakapi/services/aggregation.go:53.2,55.19 3 0 -github.com/muety/wakapi/services/aggregation.go:49.64,51.3 1 0 -github.com/muety/wakapi/services/aggregation.go:58.77,59.47 1 0 -github.com/muety/wakapi/services/aggregation.go:62.2,67.40 4 0 -github.com/muety/wakapi/services/aggregation.go:71.2,71.50 1 0 -github.com/muety/wakapi/services/aggregation.go:76.2,76.60 1 0 -github.com/muety/wakapi/services/aggregation.go:82.2,82.35 1 0 -github.com/muety/wakapi/services/aggregation.go:59.47,61.3 1 0 -github.com/muety/wakapi/services/aggregation.go:67.40,69.3 1 0 -github.com/muety/wakapi/services/aggregation.go:71.50,73.3 1 0 -github.com/muety/wakapi/services/aggregation.go:76.60,80.3 3 0 -github.com/muety/wakapi/services/aggregation.go:85.109,86.24 1 0 -github.com/muety/wakapi/services/aggregation.go:86.24,87.116 1 0 -github.com/muety/wakapi/services/aggregation.go:87.116,89.4 1 0 -github.com/muety/wakapi/services/aggregation.go:89.9,92.4 2 0 -github.com/muety/wakapi/services/aggregation.go:96.80,97.33 1 0 -github.com/muety/wakapi/services/aggregation.go:97.33,98.60 1 0 -github.com/muety/wakapi/services/aggregation.go:98.60,100.4 1 0 -github.com/muety/wakapi/services/aggregation.go:104.110,109.16 3 0 -github.com/muety/wakapi/services/aggregation.go:115.2,116.16 2 0 -github.com/muety/wakapi/services/aggregation.go:122.2,123.44 2 0 -github.com/muety/wakapi/services/aggregation.go:128.2,128.41 1 0 -github.com/muety/wakapi/services/aggregation.go:146.2,146.12 1 0 -github.com/muety/wakapi/services/aggregation.go:109.16,112.3 2 0 -github.com/muety/wakapi/services/aggregation.go:116.16,119.3 2 0 -github.com/muety/wakapi/services/aggregation.go:123.44,125.3 1 0 -github.com/muety/wakapi/services/aggregation.go:128.41,129.71 1 0 -github.com/muety/wakapi/services/aggregation.go:133.3,133.21 1 0 -github.com/muety/wakapi/services/aggregation.go:129.71,130.12 1 0 -github.com/muety/wakapi/services/aggregation.go:133.21,137.4 1 0 -github.com/muety/wakapi/services/aggregation.go:137.9,137.62 1 0 -github.com/muety/wakapi/services/aggregation.go:137.62,141.4 1 0 -github.com/muety/wakapi/services/aggregation.go:149.83,152.27 3 0 -github.com/muety/wakapi/services/aggregation.go:157.2,158.12 2 0 -github.com/muety/wakapi/services/aggregation.go:152.27,153.34 1 0 -github.com/muety/wakapi/services/aggregation.go:153.34,155.4 1 0 -github.com/muety/wakapi/services/aggregation.go:161.79,164.27 3 0 -github.com/muety/wakapi/services/aggregation.go:164.27,166.3 1 0 -github.com/muety/wakapi/services/aggregation.go:169.83,184.41 5 0 -github.com/muety/wakapi/services/aggregation.go:184.41,194.3 3 0 -github.com/muety/wakapi/services/aggregation.go:197.34,200.2 2 0 diff --git a/testing/wakapi_api_tests.postman_collection.json b/testing/wakapi_api_tests.postman_collection.json index 73e807b..a3d0725 100644 --- a/testing/wakapi_api_tests.postman_collection.json +++ b/testing/wakapi_api_tests.postman_collection.json @@ -2097,7 +2097,7 @@ "", "pm.test(\"Correct content\", function () {", " const jsonData = pm.response.json();", - " pm.expect(jsonData.data.text).to.eql('0 hrs 8 mins');", + " pm.expect(jsonData.data.text).to.eql('0 hrs 4 mins');", "});" ], "type": "text/javascript" From 179042f81bd4a068cea285ec26224f0d34d7bb1a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ferdinand=20M=C3=BCtsch?= Date: Mon, 18 Apr 2022 16:59:46 +0200 Subject: [PATCH 10/14] refactor: use cross join instead of subquery for populating summary items (see #350) --- go.mod | 2 +- repositories/summary.go | 63 ++++++++++++++++++++++++----------------- 2 files changed, 38 insertions(+), 27 deletions(-) diff --git a/go.mod b/go.mod index b7252e9..2b4e343 100644 --- a/go.mod +++ b/go.mod @@ -29,7 +29,7 @@ require ( golang.org/x/crypto v0.0.0-20220411220226-7b82a4e95df4 golang.org/x/sync v0.0.0-20210220032951-036812b2e83c gorm.io/driver/mysql v1.3.3 - gorm.io/driver/postgres v1.3.3 + gorm.io/driver/postgres v1.3.4 gorm.io/driver/sqlite v1.3.1 gorm.io/gorm v1.23.4 ) diff --git a/repositories/summary.go b/repositories/summary.go index e4668b8..7b0100f 100644 --- a/repositories/summary.go +++ b/repositories/summary.go @@ -1,9 +1,10 @@ package repositories import ( - datastructure "github.com/duke-git/lancet/v2/datastructure/set" + "github.com/duke-git/lancet/v2/slice" "github.com/muety/wakapi/models" "gorm.io/gorm" + "gorm.io/gorm/clause" "time" ) @@ -24,7 +25,7 @@ func (r *SummaryRepository) GetAll() ([]*models.Summary, error) { return nil, err } - if err := r.populateItems(summaries); err != nil { + if err := r.populateItems(summaries, []clause.Interface{}); err != nil { return nil, err } @@ -40,17 +41,26 @@ func (r *SummaryRepository) Insert(summary *models.Summary) error { func (r *SummaryRepository) GetByUserWithin(user *models.User, from, to time.Time) ([]*models.Summary, error) { var summaries []*models.Summary - if err := r.db. - Where(&models.Summary{UserID: user.ID}). - Where("from_time >= ?", from.Local()). - Where("to_time <= ?", to.Local()). - Order("from_time asc"). - // branch summaries are currently not persisted, as only relevant in combination with project filter - Find(&summaries).Error; err != nil { + + queryConditions := []clause.Interface{ + clause.Where{Exprs: r.db.Statement.BuildCondition("user_id = ?", user.ID)}, + clause.Where{Exprs: r.db.Statement.BuildCondition("from_time >= ?", from.Local())}, + clause.Where{Exprs: r.db.Statement.BuildCondition("to_time <= ?", to.Local())}, + } + + q := r.db.Model(&models.Summary{}). + Order("from_time asc") + + for _, c := range queryConditions { + q.Statement.AddClause(c) + } + + // branch summaries are currently not persisted, as only relevant in combination with project filter + if err := q.Find(&summaries).Error; err != nil { return nil, err } - if err := r.populateItems(summaries); err != nil { + if err := r.populateItems(summaries, queryConditions); err != nil { return nil, err } @@ -77,28 +87,29 @@ func (r *SummaryRepository) DeleteByUser(userId string) error { } // inplace -func (r *SummaryRepository) populateItems(summaries []*models.Summary) error { - summaryMap := map[uint]*models.Summary{} - summaryIds := datastructure.NewSet[uint]() - for _, s := range summaries { - if s.NumHeartbeats == 0 { - continue - } - summaryMap[s.ID] = s - summaryIds.Add(s.ID) - } - +func (r *SummaryRepository) populateItems(summaries []*models.Summary, conditions []clause.Interface) error { var items []*models.SummaryItem - if err := r.db. - Model(&models.SummaryItem{}). - Where("summary_id in ?", summaryIds.Values()). - Find(&items).Error; err != nil { + summaryMap := slice.GroupWith[*models.Summary, uint](summaries, func(s *models.Summary) uint { + return s.ID + }) + + q := r.db.Model(&models.SummaryItem{}). + Select("summary_items.*"). + Joins("cross join summaries"). + Where("summary_items.summary_id = summaries.id"). + Where("num_heartbeats > ?", 0) + + for _, c := range conditions { + q.Statement.AddClause(c) + } + + if err := q.Find(&items).Error; err != nil { return err } for _, item := range items { - l := summaryMap[item.SummaryID].ItemsByType(item.Type) + l := summaryMap[item.SummaryID][0].ItemsByType(item.Type) *l = append(*l, item) } From 9d7688957fc1cfa8cef032f2dd79bc16a704bcc2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ferdinand=20M=C3=BCtsch?= Date: Mon, 18 Apr 2022 19:28:30 +0200 Subject: [PATCH 11/14] chore: explicit width and height for front page images [ci skip] --- views/index.tpl.html | 8 ++++---- views/logo.tpl.html | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/views/index.tpl.html b/views/index.tpl.html index 459dd31..cc99eda 100644 --- a/views/index.tpl.html +++ b/views/index.tpl.html @@ -58,7 +58,7 @@

- App screenshot + App screenshot
@@ -81,11 +81,11 @@
- License badge - Go version badge - Wakapi coding time badge
diff --git a/views/logo.tpl.html b/views/logo.tpl.html index dfdda4e..702768d 100644 --- a/views/logo.tpl.html +++ b/views/logo.tpl.html @@ -1,3 +1,3 @@ - Logo + Logo \ No newline at end of file From ff7d595a86fb324f3210e80a055b1ffca8b1bd7b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ferdinand=20M=C3=BCtsch?= Date: Mon, 18 Apr 2022 21:07:15 +0200 Subject: [PATCH 12/14] chore: do not run expensive jobs initially but only scheduled --- main.go | 8 +++----- services/aggregation.go | 7 +------ services/misc.go | 7 +------ 3 files changed, 5 insertions(+), 17 deletions(-) diff --git a/main.go b/main.go index c2a62c3..804e015 100644 --- a/main.go +++ b/main.go @@ -169,11 +169,9 @@ func main() { miscService = services.NewMiscService(userService, summaryService, keyValueService) // Schedule background tasks - if !config.QuickStart { - go aggregationService.Schedule() - go miscService.ScheduleCountTotalTime() - go reportService.Schedule() - } + go aggregationService.Schedule() + go miscService.ScheduleCountTotalTime() + go reportService.Schedule() routes.Init() diff --git a/services/aggregation.go b/services/aggregation.go index 6310ef9..f11653a 100644 --- a/services/aggregation.go +++ b/services/aggregation.go @@ -45,13 +45,8 @@ type AggregationJob struct { // Schedule a job to (re-)generate summaries every day shortly after midnight func (srv *AggregationService) Schedule() { - // Run once initially - if err := srv.Run(datastructure.NewSet[string]()); err != nil { - logbuch.Fatal("failed to run AggregationJob: %v", err) - } - s := gocron.NewScheduler(time.Local) - s.Every(1).Day().At(srv.config.App.AggregationTime).Do(srv.Run, datastructure.NewSet[string]()) + s.Every(1).Day().At(srv.config.App.AggregationTime).WaitForSchedule().Do(srv.Run, datastructure.NewSet[string]()) s.StartBlocking() } diff --git a/services/misc.go b/services/misc.go index e1b03d5..f493209 100644 --- a/services/misc.go +++ b/services/misc.go @@ -38,13 +38,8 @@ type CountTotalTimeResult struct { } func (srv *MiscService) ScheduleCountTotalTime() { - // Run once initially - if err := srv.runCountTotalTime(); err != nil { - logbuch.Fatal("failed to run CountTotalTimeJob: %v", err) - } - s := gocron.NewScheduler(time.Local) - s.Every(1).Hour().Do(srv.runCountTotalTime) + s.Every(1).Hour().WaitForSchedule().Do(srv.runCountTotalTime) s.StartBlocking() } From d7786122426359583c59cdddf5d08318cb1fc633 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ferdinand=20M=C3=BCtsch?= Date: Mon, 18 Apr 2022 21:32:30 +0200 Subject: [PATCH 13/14] fix: remove authentication requirement from diagnostics endpoint --- routes/api/diagnostics.go | 4 ---- 1 file changed, 4 deletions(-) diff --git a/routes/api/diagnostics.go b/routes/api/diagnostics.go index f903dbe..f22bf4a 100644 --- a/routes/api/diagnostics.go +++ b/routes/api/diagnostics.go @@ -6,7 +6,6 @@ import ( "github.com/gorilla/mux" conf "github.com/muety/wakapi/config" - "github.com/muety/wakapi/middlewares" "github.com/muety/wakapi/services" "github.com/muety/wakapi/utils" @@ -29,9 +28,6 @@ func NewDiagnosticsApiHandler(userService services.IUserService, diagnosticsServ func (h *DiagnosticsApiHandler) RegisterRoutes(router *mux.Router) { r := router.PathPrefix("/plugins/errors").Subrouter() - r.Use( - middlewares.NewAuthenticateMiddleware(h.userSrvc).Handler, - ) r.Path("").Methods(http.MethodPost).HandlerFunc(h.Post) } From 4b0a3cf0d6516e1ca0799f57fdd3de920b212beb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ferdinand=20M=C3=BCtsch?= Date: Wed, 20 Apr 2022 21:36:39 +0200 Subject: [PATCH 14/14] fix: index error during summary generation (resolve #361) chore(sentry): include stacktrace with panics --- config/sentry.go | 5 +++-- go.sum | 16 ---------------- repositories/summary.go | 3 +++ routes/login.go | 5 +++++ routes/summary.go | 1 + 5 files changed, 12 insertions(+), 18 deletions(-) diff --git a/config/sentry.go b/config/sentry.go index 2a0ad51..d0df388 100644 --- a/config/sentry.go +++ b/config/sentry.go @@ -109,8 +109,9 @@ var excludedRoutes = []string{ func initSentry(config sentryConfig, debug bool) { if err := sentry.Init(sentry.ClientOptions{ - Dsn: config.Dsn, - Debug: debug, + Dsn: config.Dsn, + Debug: debug, + AttachStacktrace: true, TracesSampler: sentry.TracesSamplerFunc(func(ctx sentry.SamplingContext) sentry.Sampled { if !config.EnableTracing { return sentry.SampledFalse diff --git a/go.sum b/go.sum index f1eb644..d962efb 100644 --- a/go.sum +++ b/go.sum @@ -1,8 +1,6 @@ codeberg.org/Codeberg/avatars v0.0.0-20211228163022-8da63012fe69 h1:/XvI42KX57UTpeIOIt7IfM+pmEFTL8FGtiIUGcGDOIU= codeberg.org/Codeberg/avatars v0.0.0-20211228163022-8da63012fe69/go.mod h1:ML/htpPRb3+owhkm4+qG2ZrXnk5WXaQLASOZ5GLCPi8= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/BurntSushi/toml v1.0.0 h1:dtDWrepsVPfW9H/4y7dDgFc2MBUSeJhlaDtK13CxFlU= -github.com/BurntSushi/toml v1.0.0/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= github.com/BurntSushi/toml v1.1.0 h1:ksErzDEI1khOiGPgpwuI7x2ebx/uXQNw7xJpn9Eq1+I= github.com/BurntSushi/toml v1.1.0/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= github.com/KyleBanks/depth v1.2.1 h1:5h8fQADFrWtarTdtDudMmGsC7GPbOAu6RVB3ffsVFHc= @@ -25,8 +23,6 @@ github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ3 github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/duke-git/lancet/v2 v2.0.2 h1:U1GBY7DIhYs8Zg/+pGT4XKgKR8p4mDMT++afG6ykTrc= -github.com/duke-git/lancet/v2 v2.0.2/go.mod h1:5Nawyf/bK783rCiHyVkZLx+jj8028oVVjLOrC21ZONA= github.com/duke-git/lancet/v2 v2.0.4 h1:IvMurTpL0cGhQmGPtkCge2eCkuiu3USQtglZJnKXxEo= github.com/duke-git/lancet/v2 v2.0.4/go.mod h1:5Nawyf/bK783rCiHyVkZLx+jj8028oVVjLOrC21ZONA= github.com/emersion/go-sasl v0.0.0-20200509203442-7bfe0ed36a21/go.mod h1:iL2twTeMvZnrg54ZoPDNfJaJaqy0xIQFuBdrLsmspwQ= @@ -79,7 +75,6 @@ github.com/gorilla/securecookie v1.1.1 h1:miw7JPhV+b/lAHSXz4qd/nN9jRiAFV5FwjeKyC github.com/gorilla/securecookie v1.1.1/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+HVt/4epWDjd4= github.com/hashicorp/golang-lru v0.5.4 h1:YDjusn29QI/Das2iO9M0BHnIbxPeyuCHsjMW+lJfyTc= github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= -github.com/jackc/chunkreader v1.0.0 h1:4s39bBR8ByfqH+DKm8rQA3E1LHZWB9XWcrz8fqaZbe0= github.com/jackc/chunkreader v1.0.0/go.mod h1:RT6O25fNZIuasFJRyZ4R/Y2BbhasbmZXF9QQ7T3kePo= github.com/jackc/chunkreader/v2 v2.0.0/go.mod h1:odVSm741yZoC3dpHEUXIqA9tQRhFrgOHwnPIn9lDKlk= github.com/jackc/chunkreader/v2 v2.0.1 h1:i+RDz65UE+mmpjTfyz0MoVTnzeYxroil2G82ki7MGG8= @@ -100,7 +95,6 @@ github.com/jackc/pgmock v0.0.0-20210724152146-4ad1a8207f65 h1:DadwsjnMwFjfWc9y5W github.com/jackc/pgmock v0.0.0-20210724152146-4ad1a8207f65/go.mod h1:5R2h2EEX+qri8jOWMbJCtaPWkrrNc7OHwsp2TCqp7ak= github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM= github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg= -github.com/jackc/pgproto3 v1.1.0 h1:FYYE4yRw+AgI8wXIinMlNjBbp/UitDJwfj5LqqewP1A= github.com/jackc/pgproto3 v1.1.0/go.mod h1:eR5FA3leWg7p9aeAqi37XOTgTIbkABlvcPB3E5rlc78= github.com/jackc/pgproto3/v2 v2.0.0-alpha1.0.20190420180111-c116219b62db/go.mod h1:bhq50y+xrl9n5mRYyCBFKkpRVTLYJVWeCc+mEAI3yXA= github.com/jackc/pgproto3/v2 v2.0.0-alpha1.0.20190609003834-432c2951c711/go.mod h1:uH0AWtUmuShn0bcesswc4aBTWGvw0cAxIJp+6OB//Wg= @@ -238,12 +232,8 @@ golang.org/x/crypto v0.0.0-20201203163018-be400aefbc4c/go.mod h1:jdWPYTVW3xRLrWP golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.0.0-20220331220935-ae2d96664a29 h1:tkVvjkPTB7pnW3jnid7kNyAMPVWllTNOf/qKDze4p9o= -golang.org/x/crypto v0.0.0-20220331220935-ae2d96664a29/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.0.0-20220411220226-7b82a4e95df4 h1:kUhD7nTDoI3fVd9G4ORWrbV5NY0liEs/Jg2pv5f+bBA= golang.org/x/crypto v0.0.0-20220411220226-7b82a4e95df4/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/image v0.0.0-20211028202545-6944b10bf410 h1:hTftEOvwiOq2+O8k2D5/Q7COC7k5Qcrgc2TFURJYnvQ= -golang.org/x/image v0.0.0-20211028202545-6944b10bf410/go.mod h1:023OzeP/+EPmXeapQh35lcL3II3LrY8Ic+EFFKVhULM= golang.org/x/image v0.0.0-20220413100746-70e8d0d3baa9 h1:LRtI4W37N+KFebI/qV0OFiLUv4GLOWeEW5hn/KEJvxE= golang.org/x/image v0.0.0-20220413100746-70e8d0d3baa9/go.mod h1:023OzeP/+EPmXeapQh35lcL3II3LrY8Ic+EFFKVhULM= golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= @@ -280,8 +270,6 @@ golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220403020550-483a9cbc67c0 h1:PgUUmg0gNMIPY2WafhL/oLyQGw+kdTNPlVWOjltpp3w= -golang.org/x/sys v0.0.0-20220403020550-483a9cbc67c0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220412211240-33da011f77ad h1:ntjMns5wyP/fN65tdBD4g8J5w8n015+iIIs9rtjXkY0= golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= @@ -329,10 +317,6 @@ gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gorm.io/driver/mysql v1.3.3 h1:jXG9ANrwBc4+bMvBcSl8zCfPBaVoPyBEBshA8dA93X8= gorm.io/driver/mysql v1.3.3/go.mod h1:ChK6AHbHgDCFZyJp0F+BmVGb06PSIoh9uVYKAlRbb2U= -gorm.io/driver/postgres v1.3.2 h1:1URWk4lHWJkcudB+9bxOcNNt3uk5VfB8V2mzTPOqjRg= -gorm.io/driver/postgres v1.3.2/go.mod h1:y0vEuInFKJtijuSGu9e5bs5hzzSzPK+LancpKpvbRBw= -gorm.io/driver/postgres v1.3.3 h1:y6DU2kJgDNisxfAlmxRaQZOIy4ytnuYrpzpSFYnSfCY= -gorm.io/driver/postgres v1.3.3/go.mod h1:y0vEuInFKJtijuSGu9e5bs5hzzSzPK+LancpKpvbRBw= gorm.io/driver/postgres v1.3.4 h1:evZ7plF+Bp+Lr1mO5NdPvd6M/N98XtwHixGB+y7fdEQ= gorm.io/driver/postgres v1.3.4/go.mod h1:y0vEuInFKJtijuSGu9e5bs5hzzSzPK+LancpKpvbRBw= gorm.io/driver/sqlite v1.3.1 h1:bwfE+zTEWklBYoEodIOIBwuWHpnx52Z9zJFW5F33WLk= diff --git a/repositories/summary.go b/repositories/summary.go index 7b0100f..29b2c01 100644 --- a/repositories/summary.go +++ b/repositories/summary.go @@ -109,6 +109,9 @@ func (r *SummaryRepository) populateItems(summaries []*models.Summary, condition } for _, item := range items { + if _, ok := summaryMap[item.SummaryID]; ok { + continue + } l := summaryMap[item.SummaryID][0].ItemsByType(item.Type) *l = append(*l, item) } diff --git a/routes/login.go b/routes/login.go index 9ad3c8e..ac3eb04 100644 --- a/routes/login.go +++ b/routes/login.go @@ -91,6 +91,7 @@ func (h *LoginHandler) PostLogin(w http.ResponseWriter, r *http.Request) { encoded, err := h.config.Security.SecureCookie.Encode(models.AuthCookieKey, login.Username) if err != nil { w.WriteHeader(http.StatusInternalServerError) + conf.Log().Request(r).Error("failed to encode secure cookie - %v", err) templates[conf.LoginTemplate].Execute(w, h.buildViewModel(r).WithError("internal server error")) return } @@ -163,6 +164,7 @@ func (h *LoginHandler) PostSignup(w http.ResponseWriter, r *http.Request) { _, created, err := h.userSrvc.CreateOrGet(&signup, numUsers == 0) if err != nil { w.WriteHeader(http.StatusInternalServerError) + conf.Log().Request(r).Error("failed to create new user - %v", err) templates[conf.SignupTemplate].Execute(w, h.buildViewModel(r).WithError("failed to create new user")) return } @@ -237,6 +239,7 @@ func (h *LoginHandler) PostSetPassword(w http.ResponseWriter, r *http.Request) { user.ResetToken = "" if hash, err := utils.HashBcrypt(user.Password, h.config.Security.PasswordSalt); err != nil { w.WriteHeader(http.StatusInternalServerError) + conf.Log().Request(r).Error("failed to set new password - %v", err) templates[conf.SetPasswordTemplate].Execute(w, h.buildViewModel(r).WithError("failed to set new password")) return } else { @@ -245,6 +248,7 @@ func (h *LoginHandler) PostSetPassword(w http.ResponseWriter, r *http.Request) { if _, err := h.userSrvc.Update(user); err != nil { w.WriteHeader(http.StatusInternalServerError) + conf.Log().Request(r).Error("failed to save new password - %v", err) templates[conf.SetPasswordTemplate].Execute(w, h.buildViewModel(r).WithError("failed to save new password")) return } @@ -278,6 +282,7 @@ func (h *LoginHandler) PostResetPassword(w http.ResponseWriter, r *http.Request) if user, err := h.userSrvc.GetUserByEmail(resetRequest.Email); user != nil && err == nil { if u, err := h.userSrvc.GenerateResetToken(user); err != nil { w.WriteHeader(http.StatusInternalServerError) + conf.Log().Request(r).Error("failed to generate password reset token - %v", err) templates[conf.ResetPasswordTemplate].Execute(w, h.buildViewModel(r).WithError("failed to generate password reset token")) return } else { diff --git a/routes/summary.go b/routes/summary.go index 42986b0..aaf874d 100644 --- a/routes/summary.go +++ b/routes/summary.go @@ -51,6 +51,7 @@ func (h *SummaryHandler) GetIndex(w http.ResponseWriter, r *http.Request) { summary, err, status := su.LoadUserSummary(h.summarySrvc, r) if err != nil { w.WriteHeader(status) + conf.Log().Request(r).Error("failed to load summary - %v", err) templates[conf.SummaryTemplate].Execute(w, h.buildViewModel(r).WithError(err.Error())) return }