mirror of
https://github.com/muety/wakapi.git
synced 2023-08-10 21:12:56 +03:00
Compare commits
25 Commits
Author | SHA1 | Date | |
---|---|---|---|
2b57da224c | |||
01d51b78b1 | |||
6b83600acc | |||
65bbd744b5 | |||
81ca703501 | |||
2d1010e9d9 | |||
5ca9a6a8be | |||
caf87de887 | |||
9fc3c65efe | |||
f73285160d | |||
1f557d562f | |||
3685f3a156 | |||
b3afe9bfa2 | |||
9de2c20885 | |||
2846748b26 | |||
f2f6fe1483 | |||
17ddd7ca76 | |||
292ae41c58 | |||
4f86f67716 | |||
017530ac4a | |||
81d3251856 | |||
16af17fc37 | |||
701ed0a3e1 | |||
218c93e975 | |||
44de057022 |
13
README.md
13
README.md
@ -90,6 +90,8 @@ $ docker run -d \
|
||||
|
||||
**Note:** By default, SQLite is used as a database. To run Wakapi in Docker with MySQL or Postgres, see [Dockerfile](https://github.com/muety/wakapi/blob/master/Dockerfile) and [config.default.yml](https://github.com/muety/wakapi/blob/master/config.default.yml) for further options.
|
||||
|
||||
If you want to run Wakapi on **Kubernetes**, there is [wakapi-helm-chart](https://github.com/andreymaznyak/wakapi-helm-chart) for quick and easy deployment.
|
||||
|
||||
### 📦 Option 3: Run a release
|
||||
```bash
|
||||
# Download the release and unpack it
|
||||
@ -176,6 +178,10 @@ You can specify configuration options either via a config file (default: `config
|
||||
| `db.charset` | `WAKAPI_DB_CHARSET` | `utf8mb4` | Database connection charset (for MySQL only) |
|
||||
| `db.max_conn` | `WAKAPI_DB_MAX_CONNECTIONS` | `2` | Maximum number of database connections |
|
||||
| `db.ssl` | `WAKAPI_DB_SSL` | `false` | Whether to use TLS encryption for database connection (Postgres and CockroachDB only) |
|
||||
| `sentry.dsn` | `WAKAPI_SENTRY_DSN` | – | DSN for to integrate [Sentry](https://sentry.io) for error logging and tracing (leave empty to disable) |
|
||||
| `sentry.enable_tracing` | `WAKAPI_SENTRY_TRACING` | `false` | Whether to enable Sentry request tracing |
|
||||
| `sentry.sample_rate` | `WAKAPI_SENTRY_SAMPLE_RATE` | `0.75` | Probability of tracing a request in Sentry |
|
||||
| `sentry.sample_rate_heartbats` | `WAKAPI_SENTRY_SAMPLE_RATE_HEARTBEATS` | `0.1` | Probability of tracing a heartbeats request in Sentry |
|
||||
|
||||
### Supported databases
|
||||
Wakapi uses [GORM](https://gorm.io) as an ORM. As a consequence, a set of different relational databases is supported.
|
||||
@ -249,6 +255,13 @@ However, if you want to expose your wakapi instance to the public anyway, you ne
|
||||
CGO_FLAGS="-g -O2 -Wno-return-local-addr" go test -json -coverprofile=coverage/coverage.out ./... -run ./...
|
||||
```
|
||||
|
||||
### Building Tailwind
|
||||
To keep things minimal, Wakapi does not contain a `package.json`, `node_modules` or any sort of frontend build step. Instead, all JS and CSS assets are included as static files and checked in to Git. This way we can avoid requiring NodeJS to build Wakapi. However, for [TailwindCSS](https://tailwindcss.com/docs/installation#building-for-production) it makes sense to run it through a "build" step to benefit from purging and significantly reduce it in size. To only require this at the time of development, the compiled asset is checked in to Git as well.
|
||||
|
||||
```bash
|
||||
$ tailwindcss-cli build static/assets/vendor/tailwind.css -o static/assets/vendor/tailwind.dist.css
|
||||
```
|
||||
|
||||
## 🙏 Support
|
||||
If you like this project, please consider supporting it 🙂. You can donate either through [buying me a coffee](https://buymeacoff.ee/n1try) or becoming a GitHub sponsor. Every little donation is highly appreciated and boosts the developers' motivation to keep improving Wakapi!
|
||||
|
||||
|
@ -14,6 +14,7 @@ app:
|
||||
custom_languages:
|
||||
vue: Vue
|
||||
jsx: JSX
|
||||
svelte: Svelte
|
||||
|
||||
db:
|
||||
host: # leave blank when using sqlite3
|
||||
@ -31,4 +32,10 @@ security:
|
||||
insecure_cookies: false # You need to set this to 'true' when on localhost
|
||||
cookie_max_age: 172800
|
||||
allow_signup: true
|
||||
expose_metrics: false
|
||||
expose_metrics: false
|
||||
|
||||
sentry:
|
||||
dsn: # leave blank to disable sentry integration
|
||||
enable_tracing: true # whether to use performance monitoring
|
||||
sample_rate: 0.75 # probability of tracing a request
|
||||
sample_rate_heartbeats: 0.1 # probability of tracing a heartbeat request
|
@ -5,6 +5,7 @@ import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"github.com/emvi/logbuch"
|
||||
"github.com/getsentry/sentry-go"
|
||||
"github.com/gorilla/securecookie"
|
||||
"github.com/jinzhu/configor"
|
||||
"github.com/markbates/pkger"
|
||||
@ -92,6 +93,13 @@ type serverConfig struct {
|
||||
TlsKeyPath string `yaml:"tls_key_path" default:"" env:"WAKAPI_TLS_KEY_PATH"`
|
||||
}
|
||||
|
||||
type sentryConfig struct {
|
||||
Dsn string `env:"WAKAPI_SENTRY_DSN"`
|
||||
EnableTracing bool `yaml:"enable_tracing" env:"WAKAPI_SENTRY_TRACING"`
|
||||
SampleRate float32 `yaml:"sample_rate" default:"0.75" env:"WAKAPI_SENTRY_SAMPLE_RATE"`
|
||||
SampleRateHeartbeats float32 `yaml:"sample_rate_heartbeats" default:"0.1" env:"WAKAPI_SENTRY_SAMPLE_RATE_HEARTBEATS"`
|
||||
}
|
||||
|
||||
type Config struct {
|
||||
Env string `default:"dev" env:"ENVIRONMENT"`
|
||||
Version string `yaml:"-"`
|
||||
@ -99,6 +107,7 @@ type Config struct {
|
||||
Security securityConfig
|
||||
Db dbConfig
|
||||
Server serverConfig
|
||||
Sentry sentryConfig
|
||||
}
|
||||
|
||||
func (c *Config) CreateCookie(name, value, path string) *http.Cookie {
|
||||
@ -290,6 +299,44 @@ func resolveDbDialect(dbType string) string {
|
||||
return dbType
|
||||
}
|
||||
|
||||
func initSentry(config sentryConfig, debug bool) {
|
||||
if err := sentry.Init(sentry.ClientOptions{
|
||||
Dsn: config.Dsn,
|
||||
Debug: debug,
|
||||
TracesSampler: sentry.TracesSamplerFunc(func(ctx sentry.SamplingContext) sentry.Sampled {
|
||||
if !config.EnableTracing {
|
||||
return sentry.SampledFalse
|
||||
}
|
||||
|
||||
hub := sentry.GetHubFromContext(ctx.Span.Context())
|
||||
txName := hub.Scope().Transaction()
|
||||
|
||||
if strings.HasPrefix(txName, "GET /assets") {
|
||||
return sentry.SampledFalse
|
||||
}
|
||||
if txName == "POST /api/heartbeat" {
|
||||
return sentry.UniformTracesSampler(config.SampleRateHeartbeats).Sample(ctx)
|
||||
}
|
||||
return sentry.UniformTracesSampler(config.SampleRate).Sample(ctx)
|
||||
}),
|
||||
BeforeSend: func(event *sentry.Event, hint *sentry.EventHint) *sentry.Event {
|
||||
type principalGetter interface {
|
||||
GetPrincipal() *models.User
|
||||
}
|
||||
if hint.Context != nil {
|
||||
if req, ok := hint.Context.Value(sentry.RequestContextKey).(*http.Request); ok {
|
||||
if p := req.Context().Value("principal"); p != nil {
|
||||
event.User.ID = p.(principalGetter).GetPrincipal().ID
|
||||
}
|
||||
}
|
||||
}
|
||||
return event
|
||||
},
|
||||
}); err != nil {
|
||||
logbuch.Fatal("failed to initialized sentry – %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func Set(config *Config) {
|
||||
cfg = config
|
||||
}
|
||||
@ -333,6 +380,11 @@ func Load() *Config {
|
||||
logbuch.Fatal("you must allow at least one database connection")
|
||||
}
|
||||
|
||||
if config.Sentry.Dsn != "" {
|
||||
logbuch.Info("enabling sentry integration")
|
||||
initSentry(config.Sentry, config.IsDev())
|
||||
}
|
||||
|
||||
Set(config)
|
||||
return Get()
|
||||
}
|
||||
|
@ -22,11 +22,12 @@ func Test_mysqlConnectionString(t *testing.T) {
|
||||
Password: "test_password",
|
||||
Name: "test_name",
|
||||
Dialect: "mysql",
|
||||
Charset: "utf8mb4",
|
||||
MaxConn: 10,
|
||||
}
|
||||
|
||||
assert.Equal(t, fmt.Sprintf(
|
||||
"%s:%s@tcp(%s:%d)/%s?charset=utf8&parseTime=true&loc=%s&sql_mode=ANSI_QUOTES",
|
||||
"%s:%s@tcp(%s:%d)/%s?charset=utf8mb4&parseTime=true&loc=%s&sql_mode=ANSI_QUOTES",
|
||||
c.User,
|
||||
c.Password,
|
||||
c.Host,
|
||||
|
@ -1,25 +1,100 @@
|
||||
mode: set
|
||||
github.com/muety/wakapi/models/heartbeat.go:32.34,34.2 1 1
|
||||
github.com/muety/wakapi/models/heartbeat.go:36.65,37.28 1 1
|
||||
github.com/muety/wakapi/models/heartbeat.go:40.2,41.45 2 1
|
||||
github.com/muety/wakapi/models/heartbeat.go:44.2,45.44 2 1
|
||||
github.com/muety/wakapi/models/heartbeat.go:48.2,48.42 1 1
|
||||
github.com/muety/wakapi/models/heartbeat.go:37.28,39.3 1 1
|
||||
github.com/muety/wakapi/models/heartbeat.go:41.45,43.3 1 0
|
||||
github.com/muety/wakapi/models/heartbeat.go:45.44,47.3 1 0
|
||||
github.com/muety/wakapi/models/heartbeat.go:51.50,52.11 1 1
|
||||
github.com/muety/wakapi/models/heartbeat.go:65.2,65.15 1 1
|
||||
github.com/muety/wakapi/models/heartbeat.go:69.2,69.12 1 1
|
||||
github.com/muety/wakapi/models/heartbeat.go:53.22,54.18 1 1
|
||||
github.com/muety/wakapi/models/heartbeat.go:55.21,56.17 1 1
|
||||
github.com/muety/wakapi/models/heartbeat.go:57.23,58.19 1 1
|
||||
github.com/muety/wakapi/models/heartbeat.go:59.17,60.26 1 1
|
||||
github.com/muety/wakapi/models/heartbeat.go:61.22,62.18 1 1
|
||||
github.com/muety/wakapi/models/heartbeat.go:65.15,67.3 1 1
|
||||
github.com/muety/wakapi/models/heartbeat.go:72.37,88.2 1 0
|
||||
github.com/muety/wakapi/models/heartbeat.go:96.41,98.16 2 0
|
||||
github.com/muety/wakapi/models/heartbeat.go:101.2,102.10 2 0
|
||||
github.com/muety/wakapi/models/heartbeat.go:98.16,100.3 1 0
|
||||
github.com/muety/wakapi/models/heartbeat.go:36.65,37.46 1 1
|
||||
github.com/muety/wakapi/models/heartbeat.go:37.46,38.46 1 1
|
||||
github.com/muety/wakapi/models/heartbeat.go:38.46,41.4 2 1
|
||||
github.com/muety/wakapi/models/heartbeat.go:45.50,46.11 1 1
|
||||
github.com/muety/wakapi/models/heartbeat.go:59.2,59.15 1 1
|
||||
github.com/muety/wakapi/models/heartbeat.go:63.2,63.12 1 1
|
||||
github.com/muety/wakapi/models/heartbeat.go:47.22,48.18 1 1
|
||||
github.com/muety/wakapi/models/heartbeat.go:49.21,50.17 1 1
|
||||
github.com/muety/wakapi/models/heartbeat.go:51.23,52.19 1 1
|
||||
github.com/muety/wakapi/models/heartbeat.go:53.17,54.26 1 1
|
||||
github.com/muety/wakapi/models/heartbeat.go:55.22,56.18 1 1
|
||||
github.com/muety/wakapi/models/heartbeat.go:59.15,61.3 1 1
|
||||
github.com/muety/wakapi/models/heartbeat.go:66.37,82.2 1 0
|
||||
github.com/muety/wakapi/models/heartbeat.go:90.41,92.16 2 0
|
||||
github.com/muety/wakapi/models/heartbeat.go:95.2,96.10 2 0
|
||||
github.com/muety/wakapi/models/heartbeat.go:92.16,94.3 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/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/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:51.52,57.22 2 0
|
||||
github.com/muety/wakapi/models/shared.go:73.2,76.12 3 0
|
||||
github.com/muety/wakapi/models/shared.go:58.14,60.17 2 0
|
||||
github.com/muety/wakapi/models/shared.go:63.13,65.8 2 0
|
||||
github.com/muety/wakapi/models/shared.go:66.17,68.8 2 0
|
||||
github.com/muety/wakapi/models/shared.go:69.10,70.64 1 0
|
||||
github.com/muety/wakapi/models/shared.go:60.17,62.4 1 0
|
||||
github.com/muety/wakapi/models/shared.go:79.45,81.2 1 0
|
||||
github.com/muety/wakapi/models/shared.go:83.51,86.2 2 0
|
||||
github.com/muety/wakapi/models/shared.go:88.37,91.2 2 0
|
||||
github.com/muety/wakapi/models/shared.go:93.35,95.2 1 0
|
||||
github.com/muety/wakapi/models/shared.go:97.34,99.2 1 0
|
||||
github.com/muety/wakapi/models/summary.go:69.29,71.2 1 1
|
||||
github.com/muety/wakapi/models/summary.go:73.37,80.2 6 1
|
||||
github.com/muety/wakapi/models/summary.go:82.35,84.2 1 1
|
||||
github.com/muety/wakapi/models/summary.go:86.57,94.2 1 1
|
||||
github.com/muety/wakapi/models/summary.go:96.64,98.2 1 0
|
||||
github.com/muety/wakapi/models/summary.go:111.33,116.26 4 1
|
||||
github.com/muety/wakapi/models/summary.go:123.2,123.37 1 1
|
||||
github.com/muety/wakapi/models/summary.go:127.2,130.33 2 1
|
||||
github.com/muety/wakapi/models/summary.go:116.26,117.30 1 1
|
||||
github.com/muety/wakapi/models/summary.go:117.30,119.4 1 1
|
||||
github.com/muety/wakapi/models/summary.go:123.37,125.3 1 0
|
||||
github.com/muety/wakapi/models/summary.go:130.33,136.3 1 1
|
||||
github.com/muety/wakapi/models/summary.go:139.45,144.30 3 1
|
||||
github.com/muety/wakapi/models/summary.go:153.2,153.30 1 1
|
||||
github.com/muety/wakapi/models/summary.go:144.30,145.47 1 1
|
||||
github.com/muety/wakapi/models/summary.go:145.47,146.32 1 1
|
||||
github.com/muety/wakapi/models/summary.go:149.4,149.9 1 1
|
||||
github.com/muety/wakapi/models/summary.go:146.32,148.5 1 1
|
||||
github.com/muety/wakapi/models/summary.go:156.73,158.55 2 1
|
||||
github.com/muety/wakapi/models/summary.go:163.2,163.16 1 1
|
||||
github.com/muety/wakapi/models/summary.go:158.55,159.31 1 1
|
||||
github.com/muety/wakapi/models/summary.go:159.31,161.4 1 1
|
||||
github.com/muety/wakapi/models/summary.go:166.88,168.55 2 1
|
||||
github.com/muety/wakapi/models/summary.go:176.2,176.16 1 1
|
||||
github.com/muety/wakapi/models/summary.go:168.55,169.31 1 1
|
||||
github.com/muety/wakapi/models/summary.go:169.31,170.23 1 1
|
||||
github.com/muety/wakapi/models/summary.go:173.4,173.46 1 1
|
||||
github.com/muety/wakapi/models/summary.go:170.23,171.13 1 1
|
||||
github.com/muety/wakapi/models/summary.go:179.70,181.8 2 1
|
||||
github.com/muety/wakapi/models/summary.go:184.2,184.10 1 1
|
||||
github.com/muety/wakapi/models/summary.go:181.8,183.3 1 1
|
||||
github.com/muety/wakapi/models/summary.go:187.71,188.63 1 1
|
||||
github.com/muety/wakapi/models/summary.go:228.2,234.10 6 1
|
||||
github.com/muety/wakapi/models/summary.go:188.63,191.45 2 1
|
||||
github.com/muety/wakapi/models/summary.go:200.3,200.31 1 1
|
||||
github.com/muety/wakapi/models/summary.go:207.3,207.31 1 1
|
||||
github.com/muety/wakapi/models/summary.go:224.3,224.16 1 1
|
||||
github.com/muety/wakapi/models/summary.go:191.45,192.32 1 1
|
||||
github.com/muety/wakapi/models/summary.go:197.4,197.14 1 1
|
||||
github.com/muety/wakapi/models/summary.go:192.32,193.24 1 1
|
||||
github.com/muety/wakapi/models/summary.go:193.24,195.6 1 1
|
||||
github.com/muety/wakapi/models/summary.go:200.31,202.60 1 1
|
||||
github.com/muety/wakapi/models/summary.go:202.60,204.5 1 1
|
||||
github.com/muety/wakapi/models/summary.go:207.31,209.60 1 1
|
||||
github.com/muety/wakapi/models/summary.go:209.60,210.55 1 1
|
||||
github.com/muety/wakapi/models/summary.go:210.55,212.6 1 1
|
||||
github.com/muety/wakapi/models/summary.go:212.11,220.6 1 1
|
||||
github.com/muety/wakapi/models/summary.go:237.33,239.2 1 1
|
||||
github.com/muety/wakapi/models/summary.go:241.43,243.2 1 1
|
||||
github.com/muety/wakapi/models/summary.go:245.38,247.2 1 1
|
||||
github.com/muety/wakapi/models/alias.go:12.32,14.2 1 0
|
||||
github.com/muety/wakapi/models/alias.go:16.37,17.35 1 0
|
||||
github.com/muety/wakapi/models/alias.go:22.2,22.14 1 0
|
||||
github.com/muety/wakapi/models/alias.go:17.35,18.18 1 0
|
||||
github.com/muety/wakapi/models/alias.go:18.18,20.4 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
|
||||
@ -30,68 +105,13 @@ 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/summary.go:68.29,70.2 1 1
|
||||
github.com/muety/wakapi/models/summary.go:72.37,79.2 6 1
|
||||
github.com/muety/wakapi/models/summary.go:81.35,83.2 1 1
|
||||
github.com/muety/wakapi/models/summary.go:85.57,93.2 1 1
|
||||
github.com/muety/wakapi/models/summary.go:95.64,97.2 1 0
|
||||
github.com/muety/wakapi/models/summary.go:110.33,115.26 4 1
|
||||
github.com/muety/wakapi/models/summary.go:122.2,122.37 1 1
|
||||
github.com/muety/wakapi/models/summary.go:126.2,129.33 2 1
|
||||
github.com/muety/wakapi/models/summary.go:115.26,116.30 1 1
|
||||
github.com/muety/wakapi/models/summary.go:116.30,118.4 1 1
|
||||
github.com/muety/wakapi/models/summary.go:122.37,124.3 1 0
|
||||
github.com/muety/wakapi/models/summary.go:129.33,135.3 1 1
|
||||
github.com/muety/wakapi/models/summary.go:138.45,143.30 3 1
|
||||
github.com/muety/wakapi/models/summary.go:152.2,152.30 1 1
|
||||
github.com/muety/wakapi/models/summary.go:143.30,144.47 1 1
|
||||
github.com/muety/wakapi/models/summary.go:144.47,145.32 1 1
|
||||
github.com/muety/wakapi/models/summary.go:148.4,148.9 1 1
|
||||
github.com/muety/wakapi/models/summary.go:145.32,147.5 1 1
|
||||
github.com/muety/wakapi/models/summary.go:155.73,157.55 2 1
|
||||
github.com/muety/wakapi/models/summary.go:162.2,162.16 1 1
|
||||
github.com/muety/wakapi/models/summary.go:157.55,158.31 1 1
|
||||
github.com/muety/wakapi/models/summary.go:158.31,160.4 1 1
|
||||
github.com/muety/wakapi/models/summary.go:165.88,167.55 2 1
|
||||
github.com/muety/wakapi/models/summary.go:175.2,175.16 1 1
|
||||
github.com/muety/wakapi/models/summary.go:167.55,168.31 1 1
|
||||
github.com/muety/wakapi/models/summary.go:168.31,169.23 1 1
|
||||
github.com/muety/wakapi/models/summary.go:172.4,172.46 1 1
|
||||
github.com/muety/wakapi/models/summary.go:169.23,170.13 1 1
|
||||
github.com/muety/wakapi/models/summary.go:178.70,180.8 2 1
|
||||
github.com/muety/wakapi/models/summary.go:183.2,183.10 1 1
|
||||
github.com/muety/wakapi/models/summary.go:180.8,182.3 1 1
|
||||
github.com/muety/wakapi/models/summary.go:186.71,187.63 1 1
|
||||
github.com/muety/wakapi/models/summary.go:227.2,233.10 6 1
|
||||
github.com/muety/wakapi/models/summary.go:187.63,190.45 2 1
|
||||
github.com/muety/wakapi/models/summary.go:199.3,199.31 1 1
|
||||
github.com/muety/wakapi/models/summary.go:206.3,206.31 1 1
|
||||
github.com/muety/wakapi/models/summary.go:223.3,223.16 1 1
|
||||
github.com/muety/wakapi/models/summary.go:190.45,191.32 1 1
|
||||
github.com/muety/wakapi/models/summary.go:196.4,196.14 1 1
|
||||
github.com/muety/wakapi/models/summary.go:191.32,192.24 1 1
|
||||
github.com/muety/wakapi/models/summary.go:192.24,194.6 1 1
|
||||
github.com/muety/wakapi/models/summary.go:199.31,201.60 1 1
|
||||
github.com/muety/wakapi/models/summary.go:201.60,203.5 1 1
|
||||
github.com/muety/wakapi/models/summary.go:206.31,208.60 1 1
|
||||
github.com/muety/wakapi/models/summary.go:208.60,209.55 1 1
|
||||
github.com/muety/wakapi/models/summary.go:209.55,211.6 1 1
|
||||
github.com/muety/wakapi/models/summary.go:211.11,219.6 1 1
|
||||
github.com/muety/wakapi/models/summary.go:236.33,238.2 1 1
|
||||
github.com/muety/wakapi/models/summary.go:240.43,242.2 1 1
|
||||
github.com/muety/wakapi/models/summary.go:244.38,246.2 1 1
|
||||
github.com/muety/wakapi/models/user.go:46.43,49.2 1 0
|
||||
github.com/muety/wakapi/models/user.go:51.33,55.2 1 0
|
||||
github.com/muety/wakapi/models/user.go:57.45,59.2 1 0
|
||||
github.com/muety/wakapi/models/user.go:61.45,63.2 1 0
|
||||
github.com/muety/wakapi/models/alias.go:12.32,14.2 1 0
|
||||
github.com/muety/wakapi/models/alias.go:16.37,17.35 1 0
|
||||
github.com/muety/wakapi/models/alias.go:22.2,22.14 1 0
|
||||
github.com/muety/wakapi/models/alias.go:17.35,18.18 1 0
|
||||
github.com/muety/wakapi/models/alias.go:18.18,20.4 1 0
|
||||
github.com/muety/wakapi/models/user.go:13.13,15.2 1 1
|
||||
github.com/muety/wakapi/models/user.go:67.43,70.2 1 0
|
||||
github.com/muety/wakapi/models/user.go:72.33,77.2 1 0
|
||||
github.com/muety/wakapi/models/user.go:79.41,81.2 1 0
|
||||
github.com/muety/wakapi/models/user.go:83.45,85.2 1 0
|
||||
github.com/muety/wakapi/models/user.go:87.45,89.2 1 0
|
||||
github.com/muety/wakapi/models/user.go:91.39,93.2 1 0
|
||||
github.com/muety/wakapi/models/filters.go:16.56,17.16 1 0
|
||||
github.com/muety/wakapi/models/filters.go:29.2,29.19 1 0
|
||||
github.com/muety/wakapi/models/filters.go:18.22,19.32 1 0
|
||||
@ -110,96 +130,21 @@ github.com/muety/wakapi/models/filters.go:39.8,39.27 1 1
|
||||
github.com/muety/wakapi/models/filters.go:39.27,41.3 1 0
|
||||
github.com/muety/wakapi/models/filters.go:41.8,41.28 1 1
|
||||
github.com/muety/wakapi/models/filters.go:41.28,43.3 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/models.go:3.14,5.2 0 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:51.52,57.22 2 0
|
||||
github.com/muety/wakapi/models/shared.go:73.2,76.12 3 0
|
||||
github.com/muety/wakapi/models/shared.go:58.14,60.17 2 0
|
||||
github.com/muety/wakapi/models/shared.go:63.13,65.8 2 0
|
||||
github.com/muety/wakapi/models/shared.go:66.17,68.8 2 0
|
||||
github.com/muety/wakapi/models/shared.go:69.10,70.64 1 0
|
||||
github.com/muety/wakapi/models/shared.go:60.17,62.4 1 0
|
||||
github.com/muety/wakapi/models/shared.go:79.45,81.2 1 0
|
||||
github.com/muety/wakapi/models/shared.go:83.51,86.2 2 0
|
||||
github.com/muety/wakapi/models/shared.go:88.37,91.2 2 0
|
||||
github.com/muety/wakapi/models/shared.go:93.35,95.2 1 0
|
||||
github.com/muety/wakapi/models/shared.go:97.34,99.2 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:10.48,12.2 1 0
|
||||
github.com/muety/wakapi/utils/common.go:14.40,16.2 1 0
|
||||
github.com/muety/wakapi/utils/common.go:18.45,20.2 1 0
|
||||
github.com/muety/wakapi/utils/common.go:22.24,24.2 1 0
|
||||
github.com/muety/wakapi/utils/common.go:26.56,29.45 3 1
|
||||
github.com/muety/wakapi/utils/common.go:32.2,32.40 1 1
|
||||
github.com/muety/wakapi/utils/common.go:29.45,31.3 1 1
|
||||
github.com/muety/wakapi/utils/date.go:8.31,10.2 1 0
|
||||
github.com/muety/wakapi/utils/date.go:12.43,14.2 1 0
|
||||
github.com/muety/wakapi/utils/date.go:16.30,20.2 3 0
|
||||
github.com/muety/wakapi/utils/date.go:22.31,25.2 2 0
|
||||
github.com/muety/wakapi/utils/date.go:27.30,30.2 2 0
|
||||
github.com/muety/wakapi/utils/date.go:32.67,35.33 2 0
|
||||
github.com/muety/wakapi/utils/date.go:44.2,44.18 1 0
|
||||
github.com/muety/wakapi/utils/date.go:35.33,37.19 2 0
|
||||
github.com/muety/wakapi/utils/date.go:40.3,41.10 2 0
|
||||
github.com/muety/wakapi/utils/date.go:37.19,39.4 1 0
|
||||
github.com/muety/wakapi/utils/date.go:47.50,53.2 5 0
|
||||
github.com/muety/wakapi/utils/date.go:56.79,59.36 3 0
|
||||
github.com/muety/wakapi/utils/date.go:63.2,63.21 1 0
|
||||
github.com/muety/wakapi/utils/date.go:67.2,67.21 1 0
|
||||
github.com/muety/wakapi/utils/date.go:71.2,71.13 1 0
|
||||
github.com/muety/wakapi/utils/date.go:59.36,62.3 2 0
|
||||
github.com/muety/wakapi/utils/date.go:63.21,66.3 2 0
|
||||
github.com/muety/wakapi/utils/date.go:67.21,70.3 2 0
|
||||
github.com/muety/wakapi/utils/common.go:14.52,16.2 1 0
|
||||
github.com/muety/wakapi/utils/common.go:18.40,20.2 1 0
|
||||
github.com/muety/wakapi/utils/common.go:22.44,24.2 1 0
|
||||
github.com/muety/wakapi/utils/common.go:26.45,28.2 1 0
|
||||
github.com/muety/wakapi/utils/common.go:30.24,32.2 1 0
|
||||
github.com/muety/wakapi/utils/common.go:34.56,37.45 3 1
|
||||
github.com/muety/wakapi/utils/common.go:40.2,40.40 1 1
|
||||
github.com/muety/wakapi/utils/common.go:37.45,39.3 1 1
|
||||
github.com/muety/wakapi/utils/http.go:9.73,12.58 3 0
|
||||
github.com/muety/wakapi/utils/http.go:12.58,14.3 1 0
|
||||
github.com/muety/wakapi/utils/template.go:8.41,10.16 2 0
|
||||
github.com/muety/wakapi/utils/template.go:13.2,13.23 1 0
|
||||
github.com/muety/wakapi/utils/template.go:10.16,12.3 1 0
|
||||
github.com/muety/wakapi/utils/template.go:16.37,17.30 1 0
|
||||
github.com/muety/wakapi/utils/template.go:20.2,20.10 1 0
|
||||
github.com/muety/wakapi/utils/template.go:17.30,19.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/filesystem.go:14.68,16.16 2 0
|
||||
github.com/muety/wakapi/utils/filesystem.go:20.2,21.15 2 0
|
||||
github.com/muety/wakapi/utils/filesystem.go:33.2,33.15 1 0
|
||||
github.com/muety/wakapi/utils/filesystem.go:16.16,18.3 1 0
|
||||
github.com/muety/wakapi/utils/filesystem.go:21.15,23.47 2 0
|
||||
github.com/muety/wakapi/utils/filesystem.go:23.47,25.23 2 0
|
||||
github.com/muety/wakapi/utils/filesystem.go:29.4,29.19 1 0
|
||||
github.com/muety/wakapi/utils/filesystem.go:25.23,27.5 1 0
|
||||
github.com/muety/wakapi/utils/strings.go:8.34,10.2 1 0
|
||||
github.com/muety/wakapi/utils/strings.go:12.77,13.29 1 0
|
||||
github.com/muety/wakapi/utils/strings.go:18.2,18.19 1 0
|
||||
github.com/muety/wakapi/utils/strings.go:13.29,14.18 1 0
|
||||
github.com/muety/wakapi/utils/strings.go:14.18,16.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
|
||||
@ -225,161 +170,333 @@ github.com/muety/wakapi/utils/summary.go:62.35,63.43 1 0
|
||||
github.com/muety/wakapi/utils/summary.go:64.26,65.21 1 0
|
||||
github.com/muety/wakapi/utils/summary.go:66.10,67.39 1 0
|
||||
github.com/muety/wakapi/utils/summary.go:73.73,80.56 5 0
|
||||
github.com/muety/wakapi/utils/summary.go:96.2,103.8 2 0
|
||||
github.com/muety/wakapi/utils/summary.go:102.2,109.8 2 0
|
||||
github.com/muety/wakapi/utils/summary.go:80.56,82.3 1 0
|
||||
github.com/muety/wakapi/utils/summary.go:82.8,82.54 1 0
|
||||
github.com/muety/wakapi/utils/summary.go:82.54,84.3 1 0
|
||||
github.com/muety/wakapi/utils/summary.go:84.8,86.17 2 0
|
||||
github.com/muety/wakapi/utils/summary.go:90.3,91.17 2 0
|
||||
github.com/muety/wakapi/utils/summary.go:86.17,88.4 1 0
|
||||
github.com/muety/wakapi/utils/summary.go:91.17,93.4 1 0
|
||||
github.com/muety/wakapi/config/config.go:103.70,105.2 1 0
|
||||
github.com/muety/wakapi/config/config.go:107.65,109.2 1 0
|
||||
github.com/muety/wakapi/config/config.go:111.82,121.2 1 0
|
||||
github.com/muety/wakapi/config/config.go:123.31,125.2 1 0
|
||||
github.com/muety/wakapi/config/config.go:127.32,129.2 1 0
|
||||
github.com/muety/wakapi/config/config.go:131.74,132.19 1 0
|
||||
github.com/muety/wakapi/config/config.go:133.10,134.34 1 0
|
||||
github.com/muety/wakapi/config/config.go:134.34,143.4 8 0
|
||||
github.com/muety/wakapi/config/config.go:147.73,148.33 1 0
|
||||
github.com/muety/wakapi/config/config.go:148.33,156.17 5 0
|
||||
github.com/muety/wakapi/config/config.go:160.3,161.13 2 0
|
||||
github.com/muety/wakapi/config/config.go:156.17,158.4 1 0
|
||||
github.com/muety/wakapi/config/config.go:165.50,166.19 1 0
|
||||
github.com/muety/wakapi/config/config.go:179.2,179.12 1 0
|
||||
github.com/muety/wakapi/config/config.go:167.23,171.5 1 0
|
||||
github.com/muety/wakapi/config/config.go:172.26,175.5 1 0
|
||||
github.com/muety/wakapi/config/config.go:176.24,177.48 1 0
|
||||
github.com/muety/wakapi/config/config.go:182.53,192.2 1 1
|
||||
github.com/muety/wakapi/config/config.go:194.56,196.16 2 1
|
||||
github.com/muety/wakapi/config/config.go:200.2,207.3 1 1
|
||||
github.com/muety/wakapi/config/config.go:196.16,198.3 1 0
|
||||
github.com/muety/wakapi/config/config.go:210.54,212.2 1 1
|
||||
github.com/muety/wakapi/config/config.go:214.60,216.2 1 0
|
||||
github.com/muety/wakapi/config/config.go:218.59,220.2 1 0
|
||||
github.com/muety/wakapi/config/config.go:222.57,224.2 1 0
|
||||
github.com/muety/wakapi/config/config.go:226.53,228.2 1 0
|
||||
github.com/muety/wakapi/config/config.go:230.29,232.2 1 1
|
||||
github.com/muety/wakapi/config/config.go:234.27,236.16 2 0
|
||||
github.com/muety/wakapi/config/config.go:239.2,242.16 3 0
|
||||
github.com/muety/wakapi/config/config.go:246.2,246.41 1 0
|
||||
github.com/muety/wakapi/config/config.go:236.16,238.3 1 0
|
||||
github.com/muety/wakapi/config/config.go:242.16,244.3 1 0
|
||||
github.com/muety/wakapi/config/config.go:249.48,261.16 3 0
|
||||
github.com/muety/wakapi/config/config.go:264.2,266.16 3 0
|
||||
github.com/muety/wakapi/config/config.go:270.2,270.55 1 0
|
||||
github.com/muety/wakapi/config/config.go:274.2,274.15 1 0
|
||||
github.com/muety/wakapi/config/config.go:261.16,263.3 1 0
|
||||
github.com/muety/wakapi/config/config.go:266.16,268.3 1 0
|
||||
github.com/muety/wakapi/config/config.go:270.55,272.3 1 0
|
||||
github.com/muety/wakapi/config/config.go:277.38,278.43 1 0
|
||||
github.com/muety/wakapi/config/config.go:281.2,281.15 1 0
|
||||
github.com/muety/wakapi/config/config.go:278.43,280.3 1 0
|
||||
github.com/muety/wakapi/config/config.go:284.45,285.27 1 0
|
||||
github.com/muety/wakapi/config/config.go:288.2,288.15 1 0
|
||||
github.com/muety/wakapi/config/config.go:285.27,287.3 1 0
|
||||
github.com/muety/wakapi/config/config.go:291.26,293.2 1 0
|
||||
github.com/muety/wakapi/config/config.go:295.20,297.2 1 0
|
||||
github.com/muety/wakapi/config/config.go:299.21,304.96 3 0
|
||||
github.com/muety/wakapi/config/config.go:308.2,316.52 5 0
|
||||
github.com/muety/wakapi/config/config.go:320.2,320.47 1 0
|
||||
github.com/muety/wakapi/config/config.go:326.2,326.70 1 0
|
||||
github.com/muety/wakapi/config/config.go:330.2,330.28 1 0
|
||||
github.com/muety/wakapi/config/config.go:334.2,335.14 2 0
|
||||
github.com/muety/wakapi/config/config.go:304.96,306.3 1 0
|
||||
github.com/muety/wakapi/config/config.go:316.52,318.3 1 0
|
||||
github.com/muety/wakapi/config/config.go:320.47,321.14 1 0
|
||||
github.com/muety/wakapi/config/config.go:321.14,323.4 1 0
|
||||
github.com/muety/wakapi/config/config.go:326.70,328.3 1 0
|
||||
github.com/muety/wakapi/config/config.go:330.28,332.3 1 0
|
||||
github.com/muety/wakapi/utils/summary.go:93.3,94.17 2 0
|
||||
github.com/muety/wakapi/utils/summary.go:86.17,88.18 2 0
|
||||
github.com/muety/wakapi/utils/summary.go:88.18,90.5 1 0
|
||||
github.com/muety/wakapi/utils/summary.go:94.17,96.18 2 0
|
||||
github.com/muety/wakapi/utils/summary.go:96.18,98.5 1 0
|
||||
github.com/muety/wakapi/utils/summary.go:112.48,116.51 2 0
|
||||
github.com/muety/wakapi/utils/summary.go:119.2,119.12 1 0
|
||||
github.com/muety/wakapi/utils/summary.go:116.51,118.3 1 0
|
||||
github.com/muety/wakapi/utils/template.go:8.41,10.16 2 0
|
||||
github.com/muety/wakapi/utils/template.go:13.2,13.23 1 0
|
||||
github.com/muety/wakapi/utils/template.go:10.16,12.3 1 0
|
||||
github.com/muety/wakapi/utils/template.go:16.37,17.30 1 0
|
||||
github.com/muety/wakapi/utils/template.go:20.2,20.10 1 0
|
||||
github.com/muety/wakapi/utils/template.go:17.30,19.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/date.go:8.31,10.2 1 0
|
||||
github.com/muety/wakapi/utils/date.go:12.43,14.2 1 0
|
||||
github.com/muety/wakapi/utils/date.go:16.30,20.2 3 0
|
||||
github.com/muety/wakapi/utils/date.go:22.31,25.2 2 0
|
||||
github.com/muety/wakapi/utils/date.go:27.30,30.2 2 0
|
||||
github.com/muety/wakapi/utils/date.go:32.67,35.33 2 0
|
||||
github.com/muety/wakapi/utils/date.go:44.2,44.18 1 0
|
||||
github.com/muety/wakapi/utils/date.go:35.33,37.19 2 0
|
||||
github.com/muety/wakapi/utils/date.go:40.3,41.10 2 0
|
||||
github.com/muety/wakapi/utils/date.go:37.19,39.4 1 0
|
||||
github.com/muety/wakapi/utils/date.go:47.50,53.2 5 0
|
||||
github.com/muety/wakapi/utils/date.go:56.79,59.36 3 0
|
||||
github.com/muety/wakapi/utils/date.go:63.2,63.21 1 0
|
||||
github.com/muety/wakapi/utils/date.go:67.2,67.21 1 0
|
||||
github.com/muety/wakapi/utils/date.go:71.2,71.13 1 0
|
||||
github.com/muety/wakapi/utils/date.go:59.36,62.3 2 0
|
||||
github.com/muety/wakapi/utils/date.go:63.21,66.3 2 0
|
||||
github.com/muety/wakapi/utils/date.go:67.21,70.3 2 0
|
||||
github.com/muety/wakapi/utils/filesystem.go:14.68,16.16 2 0
|
||||
github.com/muety/wakapi/utils/filesystem.go:20.2,21.15 2 0
|
||||
github.com/muety/wakapi/utils/filesystem.go:33.2,33.15 1 0
|
||||
github.com/muety/wakapi/utils/filesystem.go:16.16,18.3 1 0
|
||||
github.com/muety/wakapi/utils/filesystem.go:21.15,23.47 2 0
|
||||
github.com/muety/wakapi/utils/filesystem.go:23.47,25.23 2 0
|
||||
github.com/muety/wakapi/utils/filesystem.go:29.4,29.19 1 0
|
||||
github.com/muety/wakapi/utils/filesystem.go:25.23,27.5 1 0
|
||||
github.com/muety/wakapi/utils/strings.go:8.34,10.2 1 0
|
||||
github.com/muety/wakapi/utils/strings.go:12.77,13.29 1 0
|
||||
github.com/muety/wakapi/utils/strings.go:18.2,18.19 1 0
|
||||
github.com/muety/wakapi/utils/strings.go:13.29,14.18 1 0
|
||||
github.com/muety/wakapi/utils/strings.go:14.18,16.4 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/middlewares/authenticate.go:20.91,26.2 1 1
|
||||
github.com/muety/wakapi/middlewares/authenticate.go:28.90,31.2 2 0
|
||||
github.com/muety/wakapi/middlewares/authenticate.go:33.90,36.2 2 0
|
||||
github.com/muety/wakapi/middlewares/authenticate.go:38.71,39.71 1 0
|
||||
github.com/muety/wakapi/middlewares/authenticate.go:39.71,41.3 1 0
|
||||
github.com/muety/wakapi/middlewares/authenticate.go:44.107,48.16 3 0
|
||||
github.com/muety/wakapi/middlewares/authenticate.go:52.2,52.31 1 0
|
||||
github.com/muety/wakapi/middlewares/authenticate.go:68.2,69.29 2 0
|
||||
github.com/muety/wakapi/middlewares/authenticate.go:48.16,50.3 1 0
|
||||
github.com/muety/wakapi/middlewares/authenticate.go:52.31,53.31 1 0
|
||||
github.com/muety/wakapi/middlewares/authenticate.go:58.3,58.29 1 0
|
||||
github.com/muety/wakapi/middlewares/authenticate.go:65.3,65.9 1 0
|
||||
github.com/muety/wakapi/middlewares/authenticate.go:53.31,56.4 2 0
|
||||
github.com/muety/wakapi/middlewares/authenticate.go:58.29,61.4 2 0
|
||||
github.com/muety/wakapi/middlewares/authenticate.go:61.9,64.4 2 0
|
||||
github.com/muety/wakapi/middlewares/authenticate.go:72.70,73.39 1 0
|
||||
github.com/muety/wakapi/middlewares/authenticate.go:78.2,78.14 1 0
|
||||
github.com/muety/wakapi/middlewares/authenticate.go:73.39,74.60 1 0
|
||||
github.com/muety/wakapi/middlewares/authenticate.go:74.60,76.4 1 0
|
||||
github.com/muety/wakapi/middlewares/authenticate.go:81.92,83.16 2 1
|
||||
github.com/muety/wakapi/middlewares/authenticate.go:87.2,90.16 4 1
|
||||
github.com/muety/wakapi/middlewares/authenticate.go:93.2,93.18 1 1
|
||||
github.com/muety/wakapi/middlewares/authenticate.go:83.16,85.3 1 1
|
||||
github.com/muety/wakapi/middlewares/authenticate.go:90.16,92.3 1 0
|
||||
github.com/muety/wakapi/middlewares/authenticate.go:96.92,98.16 2 0
|
||||
github.com/muety/wakapi/middlewares/authenticate.go:102.2,103.16 2 0
|
||||
github.com/muety/wakapi/middlewares/authenticate.go:110.2,110.18 1 0
|
||||
github.com/muety/wakapi/middlewares/authenticate.go:98.16,100.3 1 0
|
||||
github.com/muety/wakapi/middlewares/authenticate.go:103.16,105.3 1 0
|
||||
github.com/muety/wakapi/config/config.go:113.70,115.2 1 0
|
||||
github.com/muety/wakapi/config/config.go:117.65,119.2 1 0
|
||||
github.com/muety/wakapi/config/config.go:121.82,131.2 1 0
|
||||
github.com/muety/wakapi/config/config.go:133.31,135.2 1 0
|
||||
github.com/muety/wakapi/config/config.go:137.32,139.2 1 0
|
||||
github.com/muety/wakapi/config/config.go:141.74,142.19 1 0
|
||||
github.com/muety/wakapi/config/config.go:143.10,144.34 1 0
|
||||
github.com/muety/wakapi/config/config.go:144.34,153.4 8 0
|
||||
github.com/muety/wakapi/config/config.go:157.73,158.33 1 0
|
||||
github.com/muety/wakapi/config/config.go:158.33,166.17 5 0
|
||||
github.com/muety/wakapi/config/config.go:170.3,171.13 2 0
|
||||
github.com/muety/wakapi/config/config.go:166.17,168.4 1 0
|
||||
github.com/muety/wakapi/config/config.go:175.50,176.19 1 0
|
||||
github.com/muety/wakapi/config/config.go:189.2,189.12 1 0
|
||||
github.com/muety/wakapi/config/config.go:177.23,181.5 1 0
|
||||
github.com/muety/wakapi/config/config.go:182.26,185.5 1 0
|
||||
github.com/muety/wakapi/config/config.go:186.24,187.48 1 0
|
||||
github.com/muety/wakapi/config/config.go:192.53,203.2 1 1
|
||||
github.com/muety/wakapi/config/config.go:205.56,207.16 2 1
|
||||
github.com/muety/wakapi/config/config.go:211.2,218.3 1 1
|
||||
github.com/muety/wakapi/config/config.go:207.16,209.3 1 0
|
||||
github.com/muety/wakapi/config/config.go:221.54,223.2 1 1
|
||||
github.com/muety/wakapi/config/config.go:225.60,227.2 1 0
|
||||
github.com/muety/wakapi/config/config.go:229.59,231.2 1 0
|
||||
github.com/muety/wakapi/config/config.go:233.57,235.2 1 0
|
||||
github.com/muety/wakapi/config/config.go:237.53,239.2 1 0
|
||||
github.com/muety/wakapi/config/config.go:241.29,243.2 1 1
|
||||
github.com/muety/wakapi/config/config.go:245.27,247.16 2 0
|
||||
github.com/muety/wakapi/config/config.go:250.2,253.16 3 0
|
||||
github.com/muety/wakapi/config/config.go:257.2,257.41 1 0
|
||||
github.com/muety/wakapi/config/config.go:247.16,249.3 1 0
|
||||
github.com/muety/wakapi/config/config.go:253.16,255.3 1 0
|
||||
github.com/muety/wakapi/config/config.go:260.48,272.16 3 0
|
||||
github.com/muety/wakapi/config/config.go:275.2,277.16 3 0
|
||||
github.com/muety/wakapi/config/config.go:281.2,281.55 1 0
|
||||
github.com/muety/wakapi/config/config.go:285.2,285.15 1 0
|
||||
github.com/muety/wakapi/config/config.go:272.16,274.3 1 0
|
||||
github.com/muety/wakapi/config/config.go:277.16,279.3 1 0
|
||||
github.com/muety/wakapi/config/config.go:281.55,283.3 1 0
|
||||
github.com/muety/wakapi/config/config.go:288.38,289.43 1 0
|
||||
github.com/muety/wakapi/config/config.go:292.2,292.15 1 0
|
||||
github.com/muety/wakapi/config/config.go:289.43,291.3 1 0
|
||||
github.com/muety/wakapi/config/config.go:295.45,296.27 1 0
|
||||
github.com/muety/wakapi/config/config.go:299.2,299.15 1 0
|
||||
github.com/muety/wakapi/config/config.go:296.27,298.3 1 0
|
||||
github.com/muety/wakapi/config/config.go:302.50,306.91 1 0
|
||||
github.com/muety/wakapi/config/config.go:306.91,307.29 1 0
|
||||
github.com/muety/wakapi/config/config.go:311.4,314.48 3 0
|
||||
github.com/muety/wakapi/config/config.go:317.4,317.39 1 0
|
||||
github.com/muety/wakapi/config/config.go:320.4,320.69 1 0
|
||||
github.com/muety/wakapi/config/config.go:307.29,309.5 1 0
|
||||
github.com/muety/wakapi/config/config.go:314.48,316.5 1 0
|
||||
github.com/muety/wakapi/config/config.go:317.39,319.5 1 0
|
||||
github.com/muety/wakapi/config/config.go:322.79,326.27 2 0
|
||||
github.com/muety/wakapi/config/config.go:333.4,333.16 1 0
|
||||
github.com/muety/wakapi/config/config.go:326.27,327.84 1 0
|
||||
github.com/muety/wakapi/config/config.go:327.84,328.57 1 0
|
||||
github.com/muety/wakapi/config/config.go:328.57,330.7 1 0
|
||||
github.com/muety/wakapi/config/config.go:335.17,337.3 1 0
|
||||
github.com/muety/wakapi/config/config.go:340.26,342.2 1 0
|
||||
github.com/muety/wakapi/config/config.go:344.20,346.2 1 0
|
||||
github.com/muety/wakapi/config/config.go:348.21,353.96 3 0
|
||||
github.com/muety/wakapi/config/config.go:357.2,365.52 5 0
|
||||
github.com/muety/wakapi/config/config.go:369.2,369.47 1 0
|
||||
github.com/muety/wakapi/config/config.go:375.2,375.70 1 0
|
||||
github.com/muety/wakapi/config/config.go:379.2,379.28 1 0
|
||||
github.com/muety/wakapi/config/config.go:383.2,383.29 1 0
|
||||
github.com/muety/wakapi/config/config.go:388.2,389.14 2 0
|
||||
github.com/muety/wakapi/config/config.go:353.96,355.3 1 0
|
||||
github.com/muety/wakapi/config/config.go:365.52,367.3 1 0
|
||||
github.com/muety/wakapi/config/config.go:369.47,370.14 1 0
|
||||
github.com/muety/wakapi/config/config.go:370.14,372.4 1 0
|
||||
github.com/muety/wakapi/config/config.go:375.70,377.3 1 0
|
||||
github.com/muety/wakapi/config/config.go:379.28,381.3 1 0
|
||||
github.com/muety/wakapi/config/config.go:383.29,386.3 2 0
|
||||
github.com/muety/wakapi/middlewares/authenticate.go:19.91,25.2 1 1
|
||||
github.com/muety/wakapi/middlewares/authenticate.go:27.90,30.2 2 0
|
||||
github.com/muety/wakapi/middlewares/authenticate.go:32.90,35.2 2 0
|
||||
github.com/muety/wakapi/middlewares/authenticate.go:37.71,38.71 1 0
|
||||
github.com/muety/wakapi/middlewares/authenticate.go:38.71,40.3 1 0
|
||||
github.com/muety/wakapi/middlewares/authenticate.go:43.107,47.16 3 0
|
||||
github.com/muety/wakapi/middlewares/authenticate.go:51.2,51.31 1 0
|
||||
github.com/muety/wakapi/middlewares/authenticate.go:67.2,68.12 2 0
|
||||
github.com/muety/wakapi/middlewares/authenticate.go:47.16,49.3 1 0
|
||||
github.com/muety/wakapi/middlewares/authenticate.go:51.31,52.31 1 0
|
||||
github.com/muety/wakapi/middlewares/authenticate.go:57.3,57.29 1 0
|
||||
github.com/muety/wakapi/middlewares/authenticate.go:64.3,64.9 1 0
|
||||
github.com/muety/wakapi/middlewares/authenticate.go:52.31,55.4 2 0
|
||||
github.com/muety/wakapi/middlewares/authenticate.go:57.29,60.4 2 0
|
||||
github.com/muety/wakapi/middlewares/authenticate.go:60.9,63.4 2 0
|
||||
github.com/muety/wakapi/middlewares/authenticate.go:71.70,72.39 1 0
|
||||
github.com/muety/wakapi/middlewares/authenticate.go:77.2,77.14 1 0
|
||||
github.com/muety/wakapi/middlewares/authenticate.go:72.39,73.60 1 0
|
||||
github.com/muety/wakapi/middlewares/authenticate.go:73.60,75.4 1 0
|
||||
github.com/muety/wakapi/middlewares/authenticate.go:80.92,82.16 2 1
|
||||
github.com/muety/wakapi/middlewares/authenticate.go:86.2,89.16 4 1
|
||||
github.com/muety/wakapi/middlewares/authenticate.go:92.2,92.18 1 1
|
||||
github.com/muety/wakapi/middlewares/authenticate.go:82.16,84.3 1 1
|
||||
github.com/muety/wakapi/middlewares/authenticate.go:89.16,91.3 1 0
|
||||
github.com/muety/wakapi/middlewares/authenticate.go:95.92,97.16 2 0
|
||||
github.com/muety/wakapi/middlewares/authenticate.go:101.2,102.16 2 0
|
||||
github.com/muety/wakapi/middlewares/authenticate.go:109.2,109.18 1 0
|
||||
github.com/muety/wakapi/middlewares/authenticate.go:97.16,99.3 1 0
|
||||
github.com/muety/wakapi/middlewares/authenticate.go:102.16,104.3 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
|
||||
github.com/muety/wakapi/middlewares/filetype.go:31.2,31.27 1 0
|
||||
github.com/muety/wakapi/middlewares/filetype.go:24.34,25.50 1 0
|
||||
github.com/muety/wakapi/middlewares/filetype.go:25.50,29.4 3 0
|
||||
github.com/muety/wakapi/middlewares/logging.go:19.105,20.43 1 0
|
||||
github.com/muety/wakapi/middlewares/logging.go:20.43,26.3 1 0
|
||||
github.com/muety/wakapi/middlewares/logging.go:29.80,38.44 7 0
|
||||
github.com/muety/wakapi/middlewares/logging.go:44.2,53.3 1 0
|
||||
github.com/muety/wakapi/middlewares/logging.go:38.44,39.38 1 0
|
||||
github.com/muety/wakapi/middlewares/logging.go:39.38,41.4 1 0
|
||||
github.com/muety/wakapi/middlewares/logging.go:56.41,58.14 2 0
|
||||
github.com/muety/wakapi/middlewares/logging.go:61.2,61.14 1 0
|
||||
github.com/muety/wakapi/middlewares/logging.go:64.2,64.11 1 0
|
||||
github.com/muety/wakapi/middlewares/logging.go:58.14,60.3 1 0
|
||||
github.com/muety/wakapi/middlewares/logging.go:61.14,63.3 1 0
|
||||
github.com/muety/wakapi/middlewares/logging.go:95.52,97.2 1 0
|
||||
github.com/muety/wakapi/middlewares/logging.go:109.45,110.20 1 0
|
||||
github.com/muety/wakapi/middlewares/logging.go:110.20,114.3 3 0
|
||||
github.com/muety/wakapi/middlewares/logging.go:116.54,119.18 3 0
|
||||
github.com/muety/wakapi/middlewares/logging.go:126.2,127.15 2 0
|
||||
github.com/muety/wakapi/middlewares/logging.go:119.18,122.17 2 0
|
||||
github.com/muety/wakapi/middlewares/logging.go:122.17,124.4 1 0
|
||||
github.com/muety/wakapi/middlewares/logging.go:129.42,130.20 1 0
|
||||
github.com/muety/wakapi/middlewares/logging.go:130.20,132.3 1 0
|
||||
github.com/muety/wakapi/middlewares/logging.go:134.36,136.2 1 0
|
||||
github.com/muety/wakapi/middlewares/logging.go:137.42,139.2 1 0
|
||||
github.com/muety/wakapi/middlewares/logging.go:140.40,142.2 1 0
|
||||
github.com/muety/wakapi/middlewares/logging.go:143.52,145.2 1 0
|
||||
github.com/muety/wakapi/middlewares/logging.go:20.102,21.43 1 0
|
||||
github.com/muety/wakapi/middlewares/logging.go:21.43,27.3 1 0
|
||||
github.com/muety/wakapi/middlewares/logging.go:30.80,39.44 7 0
|
||||
github.com/muety/wakapi/middlewares/logging.go:45.2,54.3 1 0
|
||||
github.com/muety/wakapi/middlewares/logging.go:39.44,40.38 1 0
|
||||
github.com/muety/wakapi/middlewares/logging.go:40.38,42.4 1 0
|
||||
github.com/muety/wakapi/middlewares/logging.go:57.41,59.14 2 0
|
||||
github.com/muety/wakapi/middlewares/logging.go:62.2,62.14 1 0
|
||||
github.com/muety/wakapi/middlewares/logging.go:65.2,65.11 1 0
|
||||
github.com/muety/wakapi/middlewares/logging.go:59.14,61.3 1 0
|
||||
github.com/muety/wakapi/middlewares/logging.go:62.14,64.3 1 0
|
||||
github.com/muety/wakapi/middlewares/logging.go:68.41,69.42 1 0
|
||||
github.com/muety/wakapi/middlewares/logging.go:72.2,72.12 1 0
|
||||
github.com/muety/wakapi/middlewares/logging.go:69.42,71.3 1 0
|
||||
github.com/muety/wakapi/middlewares/logging.go:103.52,105.2 1 0
|
||||
github.com/muety/wakapi/middlewares/logging.go:117.45,118.20 1 0
|
||||
github.com/muety/wakapi/middlewares/logging.go:118.20,122.3 3 0
|
||||
github.com/muety/wakapi/middlewares/logging.go:124.54,127.18 3 0
|
||||
github.com/muety/wakapi/middlewares/logging.go:134.2,135.15 2 0
|
||||
github.com/muety/wakapi/middlewares/logging.go:127.18,130.17 2 0
|
||||
github.com/muety/wakapi/middlewares/logging.go:130.17,132.4 1 0
|
||||
github.com/muety/wakapi/middlewares/logging.go:137.42,138.20 1 0
|
||||
github.com/muety/wakapi/middlewares/logging.go:138.20,140.3 1 0
|
||||
github.com/muety/wakapi/middlewares/logging.go:142.36,144.2 1 0
|
||||
github.com/muety/wakapi/middlewares/logging.go:145.42,147.2 1 0
|
||||
github.com/muety/wakapi/middlewares/logging.go:148.40,150.2 1 0
|
||||
github.com/muety/wakapi/middlewares/logging.go:151.52,153.2 1 0
|
||||
github.com/muety/wakapi/middlewares/principal.go:15.62,17.2 1 0
|
||||
github.com/muety/wakapi/middlewares/principal.go:19.58,21.2 1 0
|
||||
github.com/muety/wakapi/middlewares/principal.go:42.71,43.43 1 0
|
||||
github.com/muety/wakapi/middlewares/principal.go:43.43,45.3 1 0
|
||||
github.com/muety/wakapi/middlewares/principal.go:48.81,51.2 2 0
|
||||
github.com/muety/wakapi/middlewares/principal.go:53.55,54.52 1 0
|
||||
github.com/muety/wakapi/middlewares/principal.go:54.52,56.3 1 0
|
||||
github.com/muety/wakapi/middlewares/principal.go:59.49,60.52 1 0
|
||||
github.com/muety/wakapi/middlewares/principal.go:63.2,63.12 1 0
|
||||
github.com/muety/wakapi/middlewares/principal.go:60.52,62.3 1 0
|
||||
github.com/muety/wakapi/middlewares/sentry.go:14.60,15.43 1 0
|
||||
github.com/muety/wakapi/middlewares/sentry.go:15.43,19.3 1 0
|
||||
github.com/muety/wakapi/middlewares/sentry.go:22.78,25.54 3 0
|
||||
github.com/muety/wakapi/middlewares/sentry.go:25.54,26.43 1 0
|
||||
github.com/muety/wakapi/middlewares/sentry.go:26.43,28.4 1 0
|
||||
github.com/muety/wakapi/services/alias.go:17.77,22.2 1 1
|
||||
github.com/muety/wakapi/services/alias.go:26.60,27.43 1 1
|
||||
github.com/muety/wakapi/services/alias.go:30.2,30.14 1 1
|
||||
github.com/muety/wakapi/services/alias.go:27.43,29.3 1 1
|
||||
github.com/muety/wakapi/services/alias.go:33.62,35.16 2 1
|
||||
github.com/muety/wakapi/services/alias.go:38.2,38.12 1 1
|
||||
github.com/muety/wakapi/services/alias.go:35.16,37.3 1 1
|
||||
github.com/muety/wakapi/services/alias.go:41.76,43.16 2 0
|
||||
github.com/muety/wakapi/services/alias.go:46.2,46.21 1 0
|
||||
github.com/muety/wakapi/services/alias.go:43.16,45.3 1 0
|
||||
github.com/muety/wakapi/services/alias.go:49.113,51.16 2 0
|
||||
github.com/muety/wakapi/services/alias.go:54.2,54.21 1 0
|
||||
github.com/muety/wakapi/services/alias.go:51.16,53.3 1 0
|
||||
github.com/muety/wakapi/services/alias.go:57.108,58.32 1 1
|
||||
github.com/muety/wakapi/services/alias.go:64.2,65.46 2 1
|
||||
github.com/muety/wakapi/services/alias.go:70.2,70.19 1 1
|
||||
github.com/muety/wakapi/services/alias.go:58.32,59.52 1 1
|
||||
github.com/muety/wakapi/services/alias.go:59.52,61.4 1 1
|
||||
github.com/muety/wakapi/services/alias.go:65.46,66.48 1 1
|
||||
github.com/muety/wakapi/services/alias.go:66.48,68.4 1 1
|
||||
github.com/muety/wakapi/services/alias.go:73.77,75.16 2 0
|
||||
github.com/muety/wakapi/services/alias.go:78.2,79.20 2 0
|
||||
github.com/muety/wakapi/services/alias.go:75.16,77.3 1 0
|
||||
github.com/muety/wakapi/services/alias.go:82.60,83.24 1 0
|
||||
github.com/muety/wakapi/services/alias.go:86.2,88.12 3 0
|
||||
github.com/muety/wakapi/services/alias.go:83.24,85.3 1 0
|
||||
github.com/muety/wakapi/services/alias.go:91.69,94.28 3 0
|
||||
github.com/muety/wakapi/services/alias.go:102.2,104.31 2 0
|
||||
github.com/muety/wakapi/services/alias.go:108.2,108.12 1 0
|
||||
github.com/muety/wakapi/services/alias.go:94.28,95.21 1 0
|
||||
github.com/muety/wakapi/services/alias.go:98.3,99.16 2 0
|
||||
github.com/muety/wakapi/services/alias.go:95.21,97.4 1 0
|
||||
github.com/muety/wakapi/services/alias.go:104.31,106.3 1 0
|
||||
github.com/muety/wakapi/services/alias.go:111.52,112.51 1 0
|
||||
github.com/muety/wakapi/services/alias.go:112.51,114.3 1 0
|
||||
github.com/muety/wakapi/services/heartbeat.go:17.141,23.2 1 0
|
||||
github.com/muety/wakapi/services/heartbeat.go:25.72,27.2 1 0
|
||||
github.com/muety/wakapi/services/heartbeat.go:29.80,31.2 1 0
|
||||
github.com/muety/wakapi/services/heartbeat.go:33.53,35.2 1 0
|
||||
github.com/muety/wakapi/services/heartbeat.go:37.76,39.2 1 0
|
||||
github.com/muety/wakapi/services/heartbeat.go:41.96,43.2 1 0
|
||||
github.com/muety/wakapi/services/heartbeat.go:45.111,47.16 2 0
|
||||
github.com/muety/wakapi/services/heartbeat.go:50.2,50.43 1 0
|
||||
github.com/muety/wakapi/services/heartbeat.go:47.16,49.3 1 0
|
||||
github.com/muety/wakapi/services/heartbeat.go:53.116,55.2 1 0
|
||||
github.com/muety/wakapi/services/heartbeat.go:57.78,59.2 1 0
|
||||
github.com/muety/wakapi/services/heartbeat.go:61.62,63.2 1 0
|
||||
github.com/muety/wakapi/services/heartbeat.go:65.116,67.16 2 0
|
||||
github.com/muety/wakapi/services/heartbeat.go:71.2,71.28 1 0
|
||||
github.com/muety/wakapi/services/heartbeat.go:75.2,75.24 1 0
|
||||
github.com/muety/wakapi/services/heartbeat.go:67.16,69.3 1 0
|
||||
github.com/muety/wakapi/services/heartbeat.go:71.28,73.3 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/heartbeat.go:29.80,34.32 3 0
|
||||
github.com/muety/wakapi/services/heartbeat.go:41.2,41.55 1 0
|
||||
github.com/muety/wakapi/services/heartbeat.go:34.32,35.36 1 0
|
||||
github.com/muety/wakapi/services/heartbeat.go:35.36,38.4 2 0
|
||||
github.com/muety/wakapi/services/heartbeat.go:44.53,46.2 1 0
|
||||
github.com/muety/wakapi/services/heartbeat.go:48.76,50.2 1 0
|
||||
github.com/muety/wakapi/services/heartbeat.go:52.96,54.2 1 0
|
||||
github.com/muety/wakapi/services/heartbeat.go:56.111,58.16 2 0
|
||||
github.com/muety/wakapi/services/heartbeat.go:61.2,61.43 1 0
|
||||
github.com/muety/wakapi/services/heartbeat.go:58.16,60.3 1 0
|
||||
github.com/muety/wakapi/services/heartbeat.go:64.116,66.2 1 0
|
||||
github.com/muety/wakapi/services/heartbeat.go:68.78,70.2 1 0
|
||||
github.com/muety/wakapi/services/heartbeat.go:72.62,74.2 1 0
|
||||
github.com/muety/wakapi/services/heartbeat.go:76.116,78.16 2 0
|
||||
github.com/muety/wakapi/services/heartbeat.go:82.2,82.28 1 0
|
||||
github.com/muety/wakapi/services/heartbeat.go:86.2,86.24 1 0
|
||||
github.com/muety/wakapi/services/heartbeat.go:78.16,80.3 1 0
|
||||
github.com/muety/wakapi/services/heartbeat.go:82.28,84.3 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/user.go:19.73,25.2 1 0
|
||||
github.com/muety/wakapi/services/user.go:27.74,28.40 1 0
|
||||
github.com/muety/wakapi/services/user.go:32.2,33.16 2 0
|
||||
github.com/muety/wakapi/services/user.go:37.2,38.15 2 0
|
||||
github.com/muety/wakapi/services/user.go:28.40,30.3 1 0
|
||||
github.com/muety/wakapi/services/user.go:33.16,35.3 1 0
|
||||
github.com/muety/wakapi/services/user.go:41.72,42.37 1 0
|
||||
github.com/muety/wakapi/services/user.go:46.2,47.16 2 0
|
||||
github.com/muety/wakapi/services/user.go:51.2,52.15 2 0
|
||||
github.com/muety/wakapi/services/user.go:42.37,44.3 1 0
|
||||
github.com/muety/wakapi/services/user.go:47.16,49.3 1 0
|
||||
github.com/muety/wakapi/services/user.go:55.58,57.2 1 0
|
||||
github.com/muety/wakapi/services/user.go:59.61,62.2 2 0
|
||||
github.com/muety/wakapi/services/user.go:64.48,66.2 1 0
|
||||
github.com/muety/wakapi/services/user.go:68.102,77.93 2 0
|
||||
github.com/muety/wakapi/services/user.go:83.2,83.38 1 0
|
||||
github.com/muety/wakapi/services/user.go:77.93,79.3 1 0
|
||||
github.com/muety/wakapi/services/user.go:79.8,81.3 1 0
|
||||
github.com/muety/wakapi/services/user.go:86.73,89.2 2 0
|
||||
github.com/muety/wakapi/services/user.go:91.78,95.2 3 0
|
||||
github.com/muety/wakapi/services/user.go:97.99,100.2 2 0
|
||||
github.com/muety/wakapi/services/user.go:102.106,105.96 3 0
|
||||
github.com/muety/wakapi/services/user.go:110.2,110.68 1 0
|
||||
github.com/muety/wakapi/services/user.go:105.96,107.3 1 0
|
||||
github.com/muety/wakapi/services/user.go:107.8,109.3 1 0
|
||||
github.com/muety/wakapi/services/user.go:113.57,116.2 2 0
|
||||
github.com/muety/wakapi/services/user.go:118.38,120.2 1 0
|
||||
github.com/muety/wakapi/services/aggregation.go:24.142,31.2 1 0
|
||||
github.com/muety/wakapi/services/aggregation.go:40.43,42.37 1 0
|
||||
github.com/muety/wakapi/services/aggregation.go:46.2,48.19 3 0
|
||||
@ -420,48 +537,36 @@ github.com/muety/wakapi/services/aggregation.go:136.62,140.4 1 0
|
||||
github.com/muety/wakapi/services/aggregation.go:148.83,163.41 5 0
|
||||
github.com/muety/wakapi/services/aggregation.go:163.41,173.3 3 0
|
||||
github.com/muety/wakapi/services/aggregation.go:176.34,179.2 2 0
|
||||
github.com/muety/wakapi/services/alias.go:17.77,22.2 1 1
|
||||
github.com/muety/wakapi/services/alias.go:26.60,27.43 1 1
|
||||
github.com/muety/wakapi/services/alias.go:30.2,30.14 1 1
|
||||
github.com/muety/wakapi/services/alias.go:27.43,29.3 1 1
|
||||
github.com/muety/wakapi/services/alias.go:33.62,35.16 2 1
|
||||
github.com/muety/wakapi/services/alias.go:38.2,38.12 1 1
|
||||
github.com/muety/wakapi/services/alias.go:35.16,37.3 1 1
|
||||
github.com/muety/wakapi/services/alias.go:41.76,43.16 2 0
|
||||
github.com/muety/wakapi/services/alias.go:46.2,46.21 1 0
|
||||
github.com/muety/wakapi/services/alias.go:43.16,45.3 1 0
|
||||
github.com/muety/wakapi/services/alias.go:49.113,51.16 2 0
|
||||
github.com/muety/wakapi/services/alias.go:54.2,54.21 1 0
|
||||
github.com/muety/wakapi/services/alias.go:51.16,53.3 1 0
|
||||
github.com/muety/wakapi/services/alias.go:57.108,58.32 1 1
|
||||
github.com/muety/wakapi/services/alias.go:64.2,65.46 2 1
|
||||
github.com/muety/wakapi/services/alias.go:70.2,70.19 1 1
|
||||
github.com/muety/wakapi/services/alias.go:58.32,59.52 1 1
|
||||
github.com/muety/wakapi/services/alias.go:59.52,61.4 1 1
|
||||
github.com/muety/wakapi/services/alias.go:65.46,66.48 1 1
|
||||
github.com/muety/wakapi/services/alias.go:66.48,68.4 1 1
|
||||
github.com/muety/wakapi/services/alias.go:73.77,75.16 2 0
|
||||
github.com/muety/wakapi/services/alias.go:78.2,79.20 2 0
|
||||
github.com/muety/wakapi/services/alias.go:75.16,77.3 1 0
|
||||
github.com/muety/wakapi/services/alias.go:82.60,83.24 1 0
|
||||
github.com/muety/wakapi/services/alias.go:86.2,88.12 3 0
|
||||
github.com/muety/wakapi/services/alias.go:83.24,85.3 1 0
|
||||
github.com/muety/wakapi/services/alias.go:91.69,94.28 3 0
|
||||
github.com/muety/wakapi/services/alias.go:102.2,104.31 2 0
|
||||
github.com/muety/wakapi/services/alias.go:108.2,108.12 1 0
|
||||
github.com/muety/wakapi/services/alias.go:94.28,95.21 1 0
|
||||
github.com/muety/wakapi/services/alias.go:98.3,99.16 2 0
|
||||
github.com/muety/wakapi/services/alias.go:95.21,97.4 1 0
|
||||
github.com/muety/wakapi/services/alias.go:104.31,106.3 1 0
|
||||
github.com/muety/wakapi/services/alias.go:111.52,112.51 1 0
|
||||
github.com/muety/wakapi/services/alias.go:112.51,114.3 1 0
|
||||
github.com/muety/wakapi/services/misc.go:23.126,30.2 1 0
|
||||
github.com/muety/wakapi/services/misc.go:42.50,44.48 1 0
|
||||
github.com/muety/wakapi/services/misc.go:48.2,50.19 3 0
|
||||
github.com/muety/wakapi/services/misc.go:44.48,46.3 1 0
|
||||
github.com/muety/wakapi/services/misc.go:53.51,59.40 4 0
|
||||
github.com/muety/wakapi/services/misc.go:63.2,66.56 2 0
|
||||
github.com/muety/wakapi/services/misc.go:77.2,77.12 1 0
|
||||
github.com/muety/wakapi/services/misc.go:59.40,61.3 1 0
|
||||
github.com/muety/wakapi/services/misc.go:66.56,67.27 1 0
|
||||
github.com/muety/wakapi/services/misc.go:67.27,72.4 1 0
|
||||
github.com/muety/wakapi/services/misc.go:73.8,75.3 1 0
|
||||
github.com/muety/wakapi/services/misc.go:80.116,81.24 1 0
|
||||
github.com/muety/wakapi/services/misc.go:81.24,82.151 1 0
|
||||
github.com/muety/wakapi/services/misc.go:91.3,91.48 1 0
|
||||
github.com/muety/wakapi/services/misc.go:82.151,84.4 1 0
|
||||
github.com/muety/wakapi/services/misc.go:84.9,90.4 2 0
|
||||
github.com/muety/wakapi/services/misc.go:91.48,94.4 2 0
|
||||
github.com/muety/wakapi/services/misc.go:98.86,101.30 3 0
|
||||
github.com/muety/wakapi/services/misc.go:106.2,109.17 1 0
|
||||
github.com/muety/wakapi/services/misc.go:113.2,116.17 1 0
|
||||
github.com/muety/wakapi/services/misc.go:101.30,104.3 2 0
|
||||
github.com/muety/wakapi/services/misc.go:109.17,111.3 1 0
|
||||
github.com/muety/wakapi/services/misc.go:116.17,118.3 1 0
|
||||
github.com/muety/wakapi/services/summary.go:27.149,35.2 1 1
|
||||
github.com/muety/wakapi/services/summary.go:39.120,42.52 2 1
|
||||
github.com/muety/wakapi/services/summary.go:39.136,42.66 2 1
|
||||
github.com/muety/wakapi/services/summary.go:47.2,47.44 1 1
|
||||
github.com/muety/wakapi/services/summary.go:53.2,53.65 1 1
|
||||
github.com/muety/wakapi/services/summary.go:58.2,59.16 2 1
|
||||
github.com/muety/wakapi/services/summary.go:64.2,66.30 3 1
|
||||
github.com/muety/wakapi/services/summary.go:42.52,44.3 1 0
|
||||
github.com/muety/wakapi/services/summary.go:42.66,44.3 1 0
|
||||
github.com/muety/wakapi/services/summary.go:47.44,50.3 2 1
|
||||
github.com/muety/wakapi/services/summary.go:53.65,55.3 1 0
|
||||
github.com/muety/wakapi/services/summary.go:59.16,61.3 1 0
|
||||
@ -544,72 +649,10 @@ github.com/muety/wakapi/services/summary.go:324.54,326.3 1 1
|
||||
github.com/muety/wakapi/services/summary.go:331.59,333.25 2 1
|
||||
github.com/muety/wakapi/services/summary.go:336.2,336.32 1 1
|
||||
github.com/muety/wakapi/services/summary.go:333.25,335.3 1 1
|
||||
github.com/muety/wakapi/services/user.go:19.73,25.2 1 0
|
||||
github.com/muety/wakapi/services/user.go:27.74,28.40 1 0
|
||||
github.com/muety/wakapi/services/user.go:32.2,33.16 2 0
|
||||
github.com/muety/wakapi/services/user.go:37.2,38.15 2 0
|
||||
github.com/muety/wakapi/services/user.go:28.40,30.3 1 0
|
||||
github.com/muety/wakapi/services/user.go:33.16,35.3 1 0
|
||||
github.com/muety/wakapi/services/user.go:41.72,42.37 1 0
|
||||
github.com/muety/wakapi/services/user.go:46.2,47.16 2 0
|
||||
github.com/muety/wakapi/services/user.go:51.2,52.15 2 0
|
||||
github.com/muety/wakapi/services/user.go:42.37,44.3 1 0
|
||||
github.com/muety/wakapi/services/user.go:47.16,49.3 1 0
|
||||
github.com/muety/wakapi/services/user.go:55.58,57.2 1 0
|
||||
github.com/muety/wakapi/services/user.go:59.61,62.2 2 0
|
||||
github.com/muety/wakapi/services/user.go:64.48,66.2 1 0
|
||||
github.com/muety/wakapi/services/user.go:68.102,76.93 2 0
|
||||
github.com/muety/wakapi/services/user.go:82.2,82.38 1 0
|
||||
github.com/muety/wakapi/services/user.go:76.93,78.3 1 0
|
||||
github.com/muety/wakapi/services/user.go:78.8,80.3 1 0
|
||||
github.com/muety/wakapi/services/user.go:85.73,88.2 2 0
|
||||
github.com/muety/wakapi/services/user.go:90.78,94.2 3 0
|
||||
github.com/muety/wakapi/services/user.go:96.99,99.2 2 0
|
||||
github.com/muety/wakapi/services/user.go:101.106,104.96 3 0
|
||||
github.com/muety/wakapi/services/user.go:109.2,109.68 1 0
|
||||
github.com/muety/wakapi/services/user.go:104.96,106.3 1 0
|
||||
github.com/muety/wakapi/services/user.go:106.8,108.3 1 0
|
||||
github.com/muety/wakapi/services/user.go:112.57,115.2 2 0
|
||||
github.com/muety/wakapi/services/user.go:117.38,119.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:23.126,30.2 1 0
|
||||
github.com/muety/wakapi/services/misc.go:42.50,44.48 1 0
|
||||
github.com/muety/wakapi/services/misc.go:48.2,50.19 3 0
|
||||
github.com/muety/wakapi/services/misc.go:44.48,46.3 1 0
|
||||
github.com/muety/wakapi/services/misc.go:53.51,59.40 4 0
|
||||
github.com/muety/wakapi/services/misc.go:63.2,66.56 2 0
|
||||
github.com/muety/wakapi/services/misc.go:77.2,77.12 1 0
|
||||
github.com/muety/wakapi/services/misc.go:59.40,61.3 1 0
|
||||
github.com/muety/wakapi/services/misc.go:66.56,67.27 1 0
|
||||
github.com/muety/wakapi/services/misc.go:67.27,72.4 1 0
|
||||
github.com/muety/wakapi/services/misc.go:73.8,75.3 1 0
|
||||
github.com/muety/wakapi/services/misc.go:80.116,81.24 1 0
|
||||
github.com/muety/wakapi/services/misc.go:81.24,82.144 1 0
|
||||
github.com/muety/wakapi/services/misc.go:91.3,91.48 1 0
|
||||
github.com/muety/wakapi/services/misc.go:82.144,84.4 1 0
|
||||
github.com/muety/wakapi/services/misc.go:84.9,90.4 2 0
|
||||
github.com/muety/wakapi/services/misc.go:91.48,94.4 2 0
|
||||
github.com/muety/wakapi/services/misc.go:98.86,101.30 3 0
|
||||
github.com/muety/wakapi/services/misc.go:106.2,109.17 1 0
|
||||
github.com/muety/wakapi/services/misc.go:113.2,116.17 1 0
|
||||
github.com/muety/wakapi/services/misc.go:101.30,104.3 2 0
|
||||
github.com/muety/wakapi/services/misc.go:109.17,111.3 1 0
|
||||
github.com/muety/wakapi/services/misc.go:116.17,118.3 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
|
||||
|
@ -210,6 +210,7 @@
|
||||
"Stan": "#b2011d",
|
||||
"Standard ML": "#dc566d",
|
||||
"SuperCollider": "#46390b",
|
||||
"Svelte": "#ff3e00",
|
||||
"Swift": "#ffac45",
|
||||
"SystemVerilog": "#DAE1C2",
|
||||
"Tcl": "#e4cc98",
|
||||
|
1
go.mod
1
go.mod
@ -5,6 +5,7 @@ go 1.13
|
||||
require (
|
||||
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751
|
||||
github.com/emvi/logbuch v1.1.1
|
||||
github.com/getsentry/sentry-go v0.10.0
|
||||
github.com/go-co-op/gocron v0.3.3
|
||||
github.com/go-openapi/spec v0.20.2 // indirect
|
||||
github.com/gorilla/handlers v1.4.2
|
||||
|
85
go.sum
85
go.sum
@ -1,7 +1,11 @@
|
||||
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||
github.com/AndreasBriese/bbloom v0.0.0-20190306092124-e2d15f34fcf9/go.mod h1:bOvUY6CB00SOBii9/FifXqc0awNKxLFCL/+pkDPuyl8=
|
||||
github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
|
||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||
github.com/CloudyKit/fastprinter v0.0.0-20200109182630-33d98a066a53/go.mod h1:+3IMCy2vIlbG1XG/0ggNQv0SvxCAIpPM5b1nCz56Xno=
|
||||
github.com/CloudyKit/jet/v3 v3.0.0/go.mod h1:HKQPgSJmdK8hdoAbKUUWajkHyHo4RaU5rMdUywE7VMo=
|
||||
github.com/Joker/hpp v1.0.0/go.mod h1:8x5n+M1Hp5hC0g8okX3sR3vFQwynaX/UgSOM9MeBKzY=
|
||||
github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0=
|
||||
github.com/KyleBanks/depth v1.2.1 h1:5h8fQADFrWtarTdtDudMmGsC7GPbOAu6RVB3ffsVFHc=
|
||||
github.com/KyleBanks/depth v1.2.1/go.mod h1:jzSb9d0L43HxTQfT+oSA1EEp2q+ne2uh6XgeJcm8brE=
|
||||
@ -9,10 +13,12 @@ github.com/PuerkitoBio/purell v1.1.1 h1:WEQqlqaGbrPkxLJWfBwQmfEAE1Z7ONdDLqrN38tN
|
||||
github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
|
||||
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 h1:d+Bc7a5rLufV/sSk/8dngufqelfh6jnri85riMAaF/M=
|
||||
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE=
|
||||
github.com/Shopify/goreferrer v0.0.0-20181106222321-ec9c9a553398/go.mod h1:a1uqRtAwp2Xwc6WNPJEufxJ7fx3npB4UV/JOLmbu5I0=
|
||||
github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo=
|
||||
github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI=
|
||||
github.com/VividCortex/gohistogram v1.0.0/go.mod h1:Pf5mBqqDxYaXu3hDrrU+w6nw50o/4+TcAqDqk/vUH7g=
|
||||
github.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5/go.mod h1:SkGFH1ia65gfNATL8TAiHDNxPzPdmEL5uirI2Uyuz6c=
|
||||
github.com/ajg/form v1.5.1/go.mod h1:uL1WgH+h2mgNtvBq0339dVnzXdBETtL2LeUXaIv25UY=
|
||||
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
||||
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751 h1:JYp7IbQjafoB+tBA3gMyHYHrpOtNuDiK/uB5uXxq5wM=
|
||||
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
||||
@ -28,6 +34,7 @@ github.com/aryann/difflib v0.0.0-20170710044230-e206f873d14a/go.mod h1:DAHtR1m6l
|
||||
github.com/aws/aws-lambda-go v1.13.3/go.mod h1:4UKl9IzQMoD+QF79YdCuzCwp8VbmG4VAQwij/eHl5CU=
|
||||
github.com/aws/aws-sdk-go v1.27.0/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo=
|
||||
github.com/aws/aws-sdk-go-v2 v0.18.0/go.mod h1:JWVYvqSMppoMJC0x5wdwiImzgXTI9FuZwxzkQq9wy+g=
|
||||
github.com/aymerick/raymond v2.0.3-0.20180322193309-b565731e1464+incompatible/go.mod h1:osfaiScAUVup+UC9Nfq76eWqDhXlp+4UYaA8uhTBO6g=
|
||||
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
|
||||
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
|
||||
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
|
||||
@ -42,6 +49,7 @@ github.com/cockroachdb/apd v1.1.0 h1:3LFP3629v+1aKXU5Q37mxmRxX/pIu1nijXydLShEq5I
|
||||
github.com/cockroachdb/apd v1.1.0/go.mod h1:8Sl8LxpKi29FqWXR16WEFZRNSz3SoPzUzeMeY4+DwBQ=
|
||||
github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8=
|
||||
github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI=
|
||||
github.com/codegangsta/inject v0.0.0-20150114235600-33e0aa1cb7c0/go.mod h1:4Zcjuz89kmFXt9morQgcfYZAYZ5n8WHjt81YYWIwtTM=
|
||||
github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
|
||||
github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk=
|
||||
github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
|
||||
@ -59,31 +67,46 @@ github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs
|
||||
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/denisenkom/go-mssqldb v0.0.0-20191001013358-cfbb681360f0/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU=
|
||||
github.com/dgraph-io/badger v1.6.0/go.mod h1:zwt7syl517jmP8s94KqSxTlM6IMsdhYy6psNgSztDR4=
|
||||
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
|
||||
github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw=
|
||||
github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
|
||||
github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
|
||||
github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs=
|
||||
github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU=
|
||||
github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I=
|
||||
github.com/edsrzf/mmap-go v1.0.0/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M=
|
||||
github.com/eknkc/amber v0.0.0-20171010120322-cdade1c07385/go.mod h1:0vRUJqYpeSZifjYj7uP3BG/gKcuzL9xWVV/Y+cK33KM=
|
||||
github.com/emvi/logbuch v1.1.1 h1:poBGNbHy/nB95oNoqLKAaJoBrcKxTO0W9DhMijKEkkU=
|
||||
github.com/emvi/logbuch v1.1.1/go.mod h1:J2Wgbr3BuSc1JO+D2MBVh6q3WPVSK5GzktwWz8pvkKw=
|
||||
github.com/envoyproxy/go-control-plane v0.6.9/go.mod h1:SBwIajubJHhxtWwsL9s8ss4safvEdbitLhGGK48rN6g=
|
||||
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
|
||||
github.com/etcd-io/bbolt v1.3.3/go.mod h1:ZF2nL25h33cCyBtcyWeZ2/I3HQOfTP+0PIEvHjkjCrw=
|
||||
github.com/fasthttp-contrib/websocket v0.0.0-20160511215533-1f3b11f56072/go.mod h1:duJ4Jxv5lDcvg4QuQr0oowTf7dz4/CR8NtyCooz9HL8=
|
||||
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
|
||||
github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M=
|
||||
github.com/franela/goblin v0.0.0-20200105215937-c9ffbefa60db/go.mod h1:7dvUGVsVBjqR7JHJk0brhHOZYGmfBYOrK0ZhYMEtBr4=
|
||||
github.com/franela/goreq v0.0.0-20171204163338-bcd34c9993f8/go.mod h1:ZhphrRTfi2rbfLwlschooIH4+wKKDR4Pdxhh+TRoA20=
|
||||
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||
github.com/gavv/httpexpect v2.0.0+incompatible/go.mod h1:x+9tiU1YnrOvnB725RkpoLv1M62hOWzwo5OXotisrKc=
|
||||
github.com/getsentry/sentry-go v0.10.0 h1:6gwY+66NHKqyZrdi6O2jGdo7wGdo9b3B69E01NFgT5g=
|
||||
github.com/getsentry/sentry-go v0.10.0/go.mod h1:kELm/9iCblqUYh+ZRML7PNdCvEuw24wBvJPYyi86cws=
|
||||
github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk=
|
||||
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
||||
github.com/gin-contrib/sse v0.0.0-20190301062529-5545eab6dad3/go.mod h1:VJ0WA2NBN22VlZ2dKZQPAPnyWw5XTlK1KymzLKsr59s=
|
||||
github.com/gin-gonic/gin v1.4.0/go.mod h1:OW2EZn3DO8Ln9oIKOvM++LBO+5UPHJJDH72/q/3rZdM=
|
||||
github.com/go-check/check v0.0.0-20180628173108-788fd7840127/go.mod h1:9ES+weclKsC9YodN5RgxqK/VD9HM9JsCSh7rNhMZE98=
|
||||
github.com/go-co-op/gocron v0.3.3 h1:QnarcMZWWKrEP25uCbtDiLsnnGw+PhCjL3wNITdWJOs=
|
||||
github.com/go-co-op/gocron v0.3.3/go.mod h1:Y9PWlYqDChf2Nbgg7kfS+ZsXHDTZbMZYPEQ0MILqH+M=
|
||||
github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q=
|
||||
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
|
||||
github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
|
||||
github.com/go-kit/kit v0.10.0/go.mod h1:xUsJbQ/Fp4kEt7AFgCuvyX4a71u8h9jB8tj/ORgOZ7o=
|
||||
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
|
||||
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
|
||||
github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A=
|
||||
github.com/go-martini/martini v0.0.0-20170121215854-22fa46961aab/go.mod h1:/P9AEU963A2AYjv4d1V5eVL1CQbEJq6aCNHDDjibzu8=
|
||||
github.com/go-openapi/jsonpointer v0.19.3 h1:gihV7YNZK1iK6Tgwwsxo2rJbD1GTbdm72325Bq8FI3w=
|
||||
github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg=
|
||||
github.com/go-openapi/jsonpointer v0.19.5 h1:gZr+CIYByUqjcgeLXnQu2gHYQC9o73G2XUeOFYEICuY=
|
||||
@ -118,6 +141,9 @@ github.com/gobuffalo/packd v0.3.0 h1:eMwymTkA1uXsqxS0Tpoop3Lc0u3kTfiMBE6nKtQU4g4
|
||||
github.com/gobuffalo/packd v0.3.0/go.mod h1:zC7QkmNkYVGKPw4tHpBQ+ml7W/3tIebgeo1b36chA3Q=
|
||||
github.com/gobuffalo/packr/v2 v2.7.1 h1:n3CIW5T17T8v4GGK5sWXLVWJhCz7b5aNLSxW6gYim4o=
|
||||
github.com/gobuffalo/packr/v2 v2.7.1/go.mod h1:qYEvAazPaVxy7Y7KR0W8qYEE+RymX74kETFqjFoFlOc=
|
||||
github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee/go.mod h1:L0fX3K22YWvt/FAX9NnzrNzcI4wNYi9Yku4O0LKYflo=
|
||||
github.com/gobwas/pool v0.2.0/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw=
|
||||
github.com/gobwas/ws v1.0.2/go.mod h1:szmBTxLgaFppYjEmNtny/v3w89xOydFnnZMcgRRu/EM=
|
||||
github.com/godror/godror v0.13.3/go.mod h1:2ouUT4kdhUBk7TAkHWD4SN0CdI0pgEQbo8FVHhbSKWg=
|
||||
github.com/gofrs/uuid v3.2.0+incompatible h1:y12jRkkFxsd7GpqdSZ+/KCs/fJbqpEXSGd4+jfEaewE=
|
||||
github.com/gofrs/uuid v3.2.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM=
|
||||
@ -134,12 +160,14 @@ github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5y
|
||||
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||
github.com/gomodule/redigo v1.7.1-0.20190724094224-574c33c3df38/go.mod h1:B4C85qUVwatsJoIUNIfCRsp7qO0iAmpGFZ4EELWSbC4=
|
||||
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
||||
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
||||
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
|
||||
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck=
|
||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
|
||||
github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
@ -156,6 +184,7 @@ github.com/gorilla/schema v1.1.0/go.mod h1:kgLaKoK1FELgZqMAVxx/5cbj0kT+57qxUrAlI
|
||||
github.com/gorilla/securecookie v1.1.1 h1:miw7JPhV+b/lAHSXz4qd/nN9jRiAFV5FwjeKyCS8BvQ=
|
||||
github.com/gorilla/securecookie v1.1.1/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+HVt/4epWDjd4=
|
||||
github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
|
||||
github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
||||
github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
|
||||
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk=
|
||||
github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
|
||||
@ -182,8 +211,14 @@ github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2p
|
||||
github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc=
|
||||
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
||||
github.com/hudl/fargo v1.3.0/go.mod h1:y3CKSmjA+wD2gak7sUSXTAoopbhU08POFhmITJgmKTg=
|
||||
github.com/imkira/go-interpol v1.1.0/go.mod h1:z0h2/2T3XF8kyEPpRgJ3kmNv+C43p+I/CoI+jC3w2iA=
|
||||
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
|
||||
github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo=
|
||||
github.com/iris-contrib/blackfriday v2.0.0+incompatible/go.mod h1:UzZ2bDEoaSGPbkg6SAB4att1aAwTmVIx/5gCVqeyUdI=
|
||||
github.com/iris-contrib/go.uuid v2.0.0+incompatible/go.mod h1:iz2lgM/1UnEf1kP0L/+fafWORmlnuysV2EMP8MW+qe0=
|
||||
github.com/iris-contrib/jade v1.1.3/go.mod h1:H/geBymxJhShH5kecoiOCSssPX7QWYH7UaeZTSWddIk=
|
||||
github.com/iris-contrib/pongo2 v0.0.1/go.mod h1:Ssh+00+3GAZqSQb30AvBRNxBx7rf0GqwkjqxNd0u65g=
|
||||
github.com/iris-contrib/schema v0.0.1/go.mod h1:urYA3uvUNG1TIIjOSCzHr9/LmbQo8LrOcOqfqxa4hXw=
|
||||
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=
|
||||
@ -251,11 +286,21 @@ github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFF
|
||||
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
|
||||
github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||
github.com/json-iterator/go v1.1.8/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||
github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||
github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo=
|
||||
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
|
||||
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
|
||||
github.com/k0kubun/colorstring v0.0.0-20150214042306-9440f1994b88/go.mod h1:3w7q1U84EfirKl04SVQ/s7nPm1ZPhiXd34z40TNz36k=
|
||||
github.com/kataras/golog v0.0.10/go.mod h1:yJ8YKCmyL+nWjERB90Qwn+bdyBZsaQwU3bTVFgkFIp8=
|
||||
github.com/kataras/iris/v12 v12.1.8/go.mod h1:LMYy4VlP67TQ3Zgriz8RE2h2kMZV2SgMYbq3UhfoFmE=
|
||||
github.com/kataras/neffos v0.0.14/go.mod h1:8lqADm8PnbeFfL7CLXh1WHw53dG27MC3pgi2R1rmoTE=
|
||||
github.com/kataras/pio v0.0.2/go.mod h1:hAoW0t9UmXi4R5Oyq5Z4irTbaTsOemSrDGUtaTl7Dro=
|
||||
github.com/kataras/sitemap v0.0.5/go.mod h1:KY2eugMKiPwsJgx7+U103YZehfvNGOXURubcGyk0Bz8=
|
||||
github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
|
||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||
github.com/klauspost/compress v1.8.2/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A=
|
||||
github.com/klauspost/compress v1.9.7/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A=
|
||||
github.com/klauspost/cpuid v1.2.1/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.2 h1:DB17ag19krx9CFsz4o3enTrPXyIXCl+2iCXH/aMAp9s=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
@ -266,6 +311,8 @@ github.com/kr/pty v1.1.8/go.mod h1:O1sed60cT9XZ5uDucP5qwvh+TE3NnUj51EiZO/lmSfw=
|
||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||
github.com/labstack/echo/v4 v4.1.11/go.mod h1:i541M3Fj6f76NZtHSj7TXnyM8n2gaodfvfxNnFqi74g=
|
||||
github.com/labstack/gommon v0.3.0/go.mod h1:MULnywXg0yavhxWKc+lOruYdAhDwPK9wf0OL7NoOu+k=
|
||||
github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
|
||||
github.com/lib/pq v1.1.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
|
||||
github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
|
||||
@ -301,7 +348,10 @@ github.com/mattn/go-sqlite3 v1.12.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsO
|
||||
github.com/mattn/go-sqlite3 v1.14.3/go.mod h1:WVKg1VTActs4Qso6iwGbiFih2UIHo0ENGwNd0Lj+XmI=
|
||||
github.com/mattn/go-sqlite3 v2.0.3+incompatible h1:gXHsfypPkaMZrKbD5209QV9jbUTJKjyR5WD3HYQSd+U=
|
||||
github.com/mattn/go-sqlite3 v2.0.3+incompatible/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
|
||||
github.com/mattn/goveralls v0.0.2/go.mod h1:8d1ZMHsd7fW6IRPKQh46F2WRpyib5/X4FOpevwGNQEw=
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
|
||||
github.com/mediocregopher/radix/v3 v3.4.2/go.mod h1:8FL3F6UQRXHXIBSPUs5h0RybMF8i4n7wVopoX3x7Bv8=
|
||||
github.com/microcosm-cc/bluemonday v1.0.2/go.mod h1:iVP4YcDBq+n/5fb23BhYFvIMq/leAFZyRl6bYmGDlGc=
|
||||
github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
|
||||
github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc=
|
||||
github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
||||
@ -317,6 +367,7 @@ github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJ
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||
github.com/moul/http2curl v1.0.0/go.mod h1:8UbvGypXm98wA/IqH45anm5Y2Z6ep6O31QGOAZ3H0fQ=
|
||||
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
|
||||
github.com/nats-io/jwt v0.3.0/go.mod h1:fRYCDE99xlTsqUzISS1Bi75UBJ6ljOJQOAAu5VglpSg=
|
||||
github.com/nats-io/jwt v0.3.2/go.mod h1:/euKqTS1ZD+zzjYrY7pseZrTtWQSjujC7xjPc8wL6eU=
|
||||
@ -335,8 +386,10 @@ github.com/olekukonko/tablewriter v0.0.2/go.mod h1:rSAaSIOAGT9odnlyGlUfAJaoc5w2f
|
||||
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/ginkgo v1.10.1/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/ginkgo v1.10.3/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
|
||||
github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
|
||||
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
|
||||
github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk=
|
||||
github.com/opentracing-contrib/go-observer v0.0.0-20170622124052-a52f23424492/go.mod h1:Ngi6UdF0k5OKD5t5wlmGhe/EDKPoUM3BXZSSfIuJbis=
|
||||
github.com/opentracing/basictracer-go v1.0.0/go.mod h1:QfBfYuafItcjQuMwinw9GhYKwFXS9KnPs5lxoYwgW74=
|
||||
@ -355,6 +408,7 @@ github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/9
|
||||
github.com/performancecopilot/speed v3.0.0+incompatible/go.mod h1:/CLtqpZ5gBg1M9iaPbIdPPGyKcA8hKdoy6hAWba7Yac=
|
||||
github.com/pierrec/lz4 v1.0.2-0.20190131084431-473cd7ce01a1/go.mod h1:3/3N9NVKO0jef7pBehbT1qWhCMrIgbYNnFAZCqQ5LRc=
|
||||
github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY=
|
||||
github.com/pingcap/errors v0.11.4/go.mod h1:Oi8TUi2kEtXXLMJk9l1cGmz20kV3TaQ0usTwv5KuLY8=
|
||||
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
|
||||
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
@ -395,10 +449,13 @@ github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR
|
||||
github.com/russross/blackfriday/v2 v2.0.1 h1:lPqVAte+HuHNfhJ/0LC98ESWRz8afy9tM/0RK8m9o+Q=
|
||||
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||
github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
|
||||
github.com/ryanuber/columnize v2.1.0+incompatible/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
|
||||
github.com/samuel/go-zookeeper v0.0.0-20190923202752-2cc03de413da/go.mod h1:gi+0XIa01GRL2eRQVjQkKGqKF3SF9vZR/HnPullcV2E=
|
||||
github.com/satori/go.uuid v1.2.0 h1:0uYX9dsZ2yD7q2RtLRtPSdGDWzjeM3TbMJP9utgA0ww=
|
||||
github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0=
|
||||
github.com/schollz/closestmatch v2.1.0+incompatible/go.mod h1:RtP1ddjLong6gTkbtmuhtR2uUrrJOpYzYRvbcPAid+g=
|
||||
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
|
||||
github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
|
||||
github.com/shopspring/decimal v0.0.0-20180709203117-cd690d0c9e24/go.mod h1:M+9NzErvs504Cn4c5DxATwIqPbtswREoFCre64PpcG4=
|
||||
github.com/shopspring/decimal v0.0.0-20200227202807-02e2044944cc h1:jUIKcSPO9MoMJBbEoyE/RJoE8vz7Mb8AjvifMMwSyvY=
|
||||
github.com/shopspring/decimal v0.0.0-20200227202807-02e2044944cc/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o=
|
||||
@ -438,14 +495,29 @@ github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/
|
||||
github.com/swaggo/swag v1.7.0 h1:5bCA/MTLQoIqDXXyHfOpMeDvL9j68OY/udlK4pQoo4E=
|
||||
github.com/swaggo/swag v1.7.0/go.mod h1:BdPIL73gvS9NBsdi7M1JOxLvlbfvNRaBP8m6WT6Aajo=
|
||||
github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
|
||||
github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc=
|
||||
github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw=
|
||||
github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0=
|
||||
github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY=
|
||||
github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
|
||||
github.com/urfave/cli v1.22.1 h1:+mkCCcOFKPnCmVYVcURKps1Xe+3zP90gSYGNfRkjoIY=
|
||||
github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
|
||||
github.com/urfave/cli/v2 v2.3.0 h1:qph92Y649prgesehzOrQjdWyxFOp/QVM+6imKHad91M=
|
||||
github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/XcUArI=
|
||||
github.com/urfave/negroni v1.0.0/go.mod h1:Meg73S6kFm/4PpbYdq35yYWoCZ9mS/YSx+lKnmiohz4=
|
||||
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
|
||||
github.com/valyala/fasthttp v1.6.0/go.mod h1:FstJa9V+Pj9vQ7OJie2qMHdwemEDaDiSdBnvPM1Su9w=
|
||||
github.com/valyala/fasttemplate v1.0.1/go.mod h1:UQGH1tvbgY+Nz5t2n7tXsz52dQxojPUpymEIMZ47gx8=
|
||||
github.com/valyala/tcplisten v0.0.0-20161114210144-ceec8f93295a/go.mod h1:v3UYOV9WzVtRmSR+PDvWpU/qWl4Wa5LApYYX4ZtKbio=
|
||||
github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU=
|
||||
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ=
|
||||
github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y=
|
||||
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
|
||||
github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
|
||||
github.com/yalp/jsonpath v0.0.0-20180802001716-5cc68e5049a0/go.mod h1:/LWChgwKmvncFJFHJ7Gvn9wZArjbV5/FppcK2fKk/tI=
|
||||
github.com/yudai/gojsondiff v1.0.0/go.mod h1:AY32+k2cwILAkW1fbgxQ5mUmMiZFgLIV+FBNExI05xg=
|
||||
github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82/go.mod h1:lgjkn3NuSvDfVJdfcVVdX+jpBxNmX4rDAzaS45IcYoM=
|
||||
github.com/yudai/pp v2.0.1+incompatible/go.mod h1:PuxR/8QJ7cyCkFp/aUDS+JY727OFEZkTdatxwunjIkc=
|
||||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/zenazn/goji v0.9.0/go.mod h1:7S9M489iMyHBNxwZnk9/EHS098H4/F6TATF2mIxtB1Q=
|
||||
github.com/ziutek/mymysql v1.5.4 h1:GB0qdRGsTwQSBVYuVShFBKaXSnSnYYC2d9knnE1LHFs=
|
||||
@ -479,6 +551,7 @@ golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8U
|
||||
golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20190911031432-227b76d455e7/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20191227163750-53104e6ec876/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20200323165209-0ec3e9974c59/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI=
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
@ -504,12 +577,15 @@ golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73r
|
||||
golang.org/x/net v0.0.0-20190125091013-d26f9f9a57f3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190327091125-710a502c58a2/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
|
||||
golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.0.0-20201110031124-69a78807bb2b h1:uwuIcX0g4Yl1NC5XAz37xsr2lTtcqevgzYNVt49waME=
|
||||
@ -543,6 +619,7 @@ golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7w
|
||||
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190515120540-06a5c4944438/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
@ -570,10 +647,12 @@ golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxb
|
||||
golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20181221001348-537d06c36207/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
|
||||
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20190327201419-c70d86f8b7cf/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20190425163242-31fd60d6bfdc/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||
@ -625,9 +704,13 @@ gopkg.in/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qS
|
||||
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
|
||||
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
|
||||
gopkg.in/gcfg.v1 v1.2.3/go.mod h1:yesOnuUOFQAhST5vPY4nbZsb/huCgGGXlipJsBn0b3o=
|
||||
gopkg.in/go-playground/assert.v1 v1.2.1/go.mod h1:9RXL0bg/zibRAgZUYszZSwO/z8Y/a8bDuhia5mkpMnE=
|
||||
gopkg.in/go-playground/validator.v8 v8.18.2/go.mod h1:RX2a/7Ha8BgOhfk7j780h4/u/RRjR0eouCJSH80/M2Y=
|
||||
gopkg.in/gorp.v1 v1.7.2 h1:j3DWlAyGVv8whO7AcIWznQ2Yj7yJkn34B8s63GViAAw=
|
||||
gopkg.in/gorp.v1 v1.7.2/go.mod h1:Wo3h+DBQZIxATwftsglhdD/62zRFPhGhTiu5jUJmCaw=
|
||||
gopkg.in/inconshreveable/log15.v2 v2.0.0-20180818164646-67afb5ed74ec/go.mod h1:aPpfJ7XW+gOuirDoZ8gHhLh3kZ1B08FtV2bbmy7Jv3s=
|
||||
gopkg.in/ini.v1 v1.51.1/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
||||
gopkg.in/mgo.v2 v2.0.0-20180705113604-9856a29383ce/go.mod h1:yeKp02qBN3iKW1OzL3MGk2IdtZzaj7SFntXj72NppTA=
|
||||
gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo=
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
|
||||
gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI=
|
||||
@ -635,12 +718,14 @@ gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bl
|
||||
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.7/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU=
|
||||
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
|
||||
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
||||
gopkg.in/yaml.v3 v3.0.0-20191120175047-4206685974f2/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776 h1:tQIYjPdBoyREyB9XMu+nnTclpTYkz2zFM+lzLJFO4gQ=
|
||||
|
23
main.go
23
main.go
@ -117,9 +117,7 @@ func main() {
|
||||
defer sqlDb.Close()
|
||||
|
||||
// Migrate database schema
|
||||
migrations.RunPreMigrations(db, config)
|
||||
runDatabaseMigrations()
|
||||
migrations.RunCustomPostMigrations(db, config)
|
||||
migrations.Run(db, config)
|
||||
|
||||
// Repositories
|
||||
aliasRepository = repositories.NewAliasRepository(db)
|
||||
@ -167,14 +165,15 @@ func main() {
|
||||
// Setup Routers
|
||||
router := mux.NewRouter()
|
||||
rootRouter := router.PathPrefix("/").Subrouter()
|
||||
apiRouter := router.PathPrefix("/api").Subrouter()
|
||||
apiRouter := router.PathPrefix("/api").Subrouter().StrictSlash(true)
|
||||
|
||||
// Globally used middlewares
|
||||
recoveryMiddleware := handlers.RecoveryHandler()
|
||||
loggingMiddleware := middlewares.NewLoggingMiddleware(logbuch.Info, []string{"/assets"})
|
||||
|
||||
// Router configs
|
||||
router.Use(loggingMiddleware, recoveryMiddleware)
|
||||
router.Use(middlewares.NewPrincipalMiddleware())
|
||||
router.Use(middlewares.NewLoggingMiddleware(logbuch.Info, []string{"/assets"}))
|
||||
router.Use(handlers.RecoveryHandler())
|
||||
if config.Sentry.Dsn != "" {
|
||||
router.Use(middlewares.NewSentryMiddleware())
|
||||
}
|
||||
|
||||
// Route registrations
|
||||
homeHandler.RegisterRoutes(rootRouter)
|
||||
@ -268,9 +267,3 @@ func listen(handler http.Handler) {
|
||||
|
||||
<-make(chan interface{}, 1)
|
||||
}
|
||||
|
||||
func runDatabaseMigrations() {
|
||||
if err := config.GetMigrationFunc(config.Db.Dialect)(db); err != nil {
|
||||
logbuch.Fatal(err.Error())
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,6 @@
|
||||
package middlewares
|
||||
|
||||
import (
|
||||
"context"
|
||||
conf "github.com/muety/wakapi/config"
|
||||
"github.com/muety/wakapi/models"
|
||||
"github.com/muety/wakapi/services"
|
||||
@ -65,8 +64,8 @@ func (m *AuthenticateMiddleware) ServeHTTP(w http.ResponseWriter, r *http.Reques
|
||||
return
|
||||
}
|
||||
|
||||
ctx := context.WithValue(r.Context(), models.UserKey, user)
|
||||
next(w, r.WithContext(ctx))
|
||||
SetPrincipal(r, user)
|
||||
next(w, r)
|
||||
}
|
||||
|
||||
func (m *AuthenticateMiddleware) isOptional(requestPath string) bool {
|
||||
|
@ -6,7 +6,7 @@ import (
|
||||
"fmt"
|
||||
"github.com/emvi/logbuch"
|
||||
"github.com/muety/wakapi/config"
|
||||
"github.com/muety/wakapi/models"
|
||||
"github.com/muety/wakapi/middlewares"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
@ -39,7 +39,7 @@ func (m *WakatimeRelayMiddleware) ServeHTTP(w http.ResponseWriter, r *http.Reque
|
||||
return
|
||||
}
|
||||
|
||||
user := r.Context().Value(models.UserKey).(*models.User)
|
||||
user := middlewares.GetPrincipal(r)
|
||||
if user == nil || user.WakatimeApiKey == "" {
|
||||
return
|
||||
}
|
||||
|
@ -43,13 +43,14 @@ func (lg *LoggingMiddleware) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
lg.logFunc(
|
||||
"[request] status=%d, method=%s, uri=%s, duration=%v, bytes=%d, addr=%s",
|
||||
"[request] status=%d, method=%s, uri=%s, duration=%v, bytes=%d, addr=%s, user=%s",
|
||||
ww.Status(),
|
||||
r.Method,
|
||||
r.URL.String(),
|
||||
duration,
|
||||
ww.BytesWritten(),
|
||||
readUserIP(r),
|
||||
readUserID(r),
|
||||
)
|
||||
}
|
||||
|
||||
@ -64,6 +65,13 @@ func readUserIP(r *http.Request) string {
|
||||
return ip
|
||||
}
|
||||
|
||||
func readUserID(r *http.Request) string {
|
||||
if user := GetPrincipal(r); user != nil {
|
||||
return user.ID
|
||||
}
|
||||
return "-"
|
||||
}
|
||||
|
||||
// The below writer-wrapping code has been lifted from
|
||||
// https://github.com/zenazn/goji/blob/master/web/middleware/logger.go - because
|
||||
// it does exactly what is needed, and it's unlikely to change in any
|
||||
|
64
middlewares/principal.go
Normal file
64
middlewares/principal.go
Normal file
@ -0,0 +1,64 @@
|
||||
package middlewares
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/muety/wakapi/models"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
const keyPrincipal = "principal"
|
||||
|
||||
type PrincipalContainer struct {
|
||||
principal *models.User
|
||||
}
|
||||
|
||||
func (c *PrincipalContainer) SetPrincipal(user *models.User) {
|
||||
c.principal = user
|
||||
}
|
||||
|
||||
func (c *PrincipalContainer) GetPrincipal() *models.User {
|
||||
return c.principal
|
||||
}
|
||||
|
||||
// This middleware is a bit of a dirty workaround to the fact that a http.Request's context
|
||||
// does not allow to pass values from an inner to an outer middleware. Calling WithContext() on a
|
||||
// request shallow-copies the whole request itself and therefore, in a chain of handler1(handler2()),
|
||||
// handler 1 will not have access to values handler 2 writes to its context. In addition, Context.WithValue
|
||||
// returns a new context with the old context as a parent.
|
||||
//
|
||||
// As a concrete example, SentryMiddleware as well as LoggingMiddleware should be quite the outer layers,
|
||||
// while AuthenticationMiddleware is on the very inside of the chain. However, we still want sentry or the
|
||||
// logger to have access to the user object populated by the auth. middleware, if present.
|
||||
//
|
||||
// This middleware shall be included as the outermost layers and it injects a stateful container that does
|
||||
// nothing but conditionally hold a reference to an authenticated user object.
|
||||
//
|
||||
// Other reference: https://stackoverflow.com/questions/55972869/send-errors-to-sentry-with-golang-and-mux
|
||||
|
||||
type PrincipalMiddleware struct {
|
||||
handler http.Handler
|
||||
}
|
||||
|
||||
func NewPrincipalMiddleware() func(handler http.Handler) http.Handler {
|
||||
return func(h http.Handler) http.Handler {
|
||||
return &PrincipalMiddleware{handler: h}
|
||||
}
|
||||
}
|
||||
|
||||
func (p *PrincipalMiddleware) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
ctx := context.WithValue(r.Context(), keyPrincipal, &PrincipalContainer{})
|
||||
p.handler.ServeHTTP(w, r.WithContext(ctx))
|
||||
}
|
||||
|
||||
func SetPrincipal(r *http.Request, user *models.User) {
|
||||
if p := r.Context().Value(keyPrincipal); p != nil {
|
||||
p.(*PrincipalContainer).SetPrincipal(user)
|
||||
}
|
||||
}
|
||||
|
||||
func GetPrincipal(r *http.Request) *models.User {
|
||||
if p := r.Context().Value(keyPrincipal); p != nil {
|
||||
return p.(*PrincipalContainer).GetPrincipal()
|
||||
}
|
||||
return nil
|
||||
}
|
30
middlewares/sentry.go
Normal file
30
middlewares/sentry.go
Normal file
@ -0,0 +1,30 @@
|
||||
package middlewares
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/getsentry/sentry-go"
|
||||
sentryhttp "github.com/getsentry/sentry-go/http"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
type SentryMiddleware struct {
|
||||
handler http.Handler
|
||||
}
|
||||
|
||||
func NewSentryMiddleware() func(http.Handler) http.Handler {
|
||||
return func(h http.Handler) http.Handler {
|
||||
return sentryhttp.New(sentryhttp.Options{
|
||||
Repanic: true,
|
||||
}).Handle(&SentryMiddleware{handler: h})
|
||||
}
|
||||
}
|
||||
|
||||
func (h *SentryMiddleware) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
ctx := context.WithValue(r.Context(), "-", "-")
|
||||
h.handler.ServeHTTP(w, r.WithContext(ctx))
|
||||
if hub := sentry.GetHubFromContext(ctx); hub != nil {
|
||||
if user := GetPrincipal(r); user != nil {
|
||||
hub.Scope().SetUser(sentry.User{ID: user.ID})
|
||||
}
|
||||
}
|
||||
}
|
41
migrations/20210221_add_created_date_column.go
Normal file
41
migrations/20210221_add_created_date_column.go
Normal file
@ -0,0 +1,41 @@
|
||||
package migrations
|
||||
|
||||
import (
|
||||
"github.com/emvi/logbuch"
|
||||
"github.com/muety/wakapi/config"
|
||||
"github.com/muety/wakapi/models"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
func init() {
|
||||
const name = "20210221-add_created_date_column"
|
||||
f := migrationFunc{
|
||||
name: name,
|
||||
f: func(db *gorm.DB, cfg *config.Config) error {
|
||||
condition := "key = ?"
|
||||
if cfg.Db.Dialect == config.SQLDialectMysql {
|
||||
condition = "`key` = ?"
|
||||
}
|
||||
lookupResult := db.Where(condition, name).First(&models.KeyStringValue{})
|
||||
if lookupResult.Error == nil && lookupResult.RowsAffected > 0 {
|
||||
logbuch.Info("no need to migrate '%s'", name)
|
||||
return nil
|
||||
}
|
||||
|
||||
if err := db.Exec("UPDATE heartbeats SET created_at = time WHERE TRUE").Error; err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := db.Create(&models.KeyStringValue{
|
||||
Key: name,
|
||||
Value: "done",
|
||||
}).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
registerPostMigration(f)
|
||||
}
|
@ -28,9 +28,17 @@ func registerPostMigration(f migrationFunc) {
|
||||
postMigrations = append(postMigrations, f)
|
||||
}
|
||||
|
||||
// NOTE: Currently, migrations themselves keep track
|
||||
// of whether they have run, yet or not, because some
|
||||
// simply run on every start.
|
||||
func Run(db *gorm.DB, cfg *config.Config) {
|
||||
RunPreMigrations(db, cfg)
|
||||
RunSchemaMigrations(db, cfg)
|
||||
RunPostMigrations(db, cfg)
|
||||
}
|
||||
|
||||
func RunSchemaMigrations(db *gorm.DB, cfg *config.Config) {
|
||||
if err := cfg.GetMigrationFunc(cfg.Db.Dialect)(db); err != nil {
|
||||
logbuch.Fatal(err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
func RunPreMigrations(db *gorm.DB, cfg *config.Config) {
|
||||
sort.Sort(preMigrations)
|
||||
@ -43,7 +51,7 @@ func RunPreMigrations(db *gorm.DB, cfg *config.Config) {
|
||||
}
|
||||
}
|
||||
|
||||
func RunCustomPostMigrations(db *gorm.DB, cfg *config.Config) {
|
||||
func RunPostMigrations(db *gorm.DB, cfg *config.Config) {
|
||||
sort.Sort(postMigrations)
|
||||
|
||||
for _, m := range postMigrations {
|
||||
|
@ -4,29 +4,29 @@ import (
|
||||
"fmt"
|
||||
"github.com/emvi/logbuch"
|
||||
"github.com/mitchellh/hashstructure/v2"
|
||||
"regexp"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
type Heartbeat struct {
|
||||
ID uint `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"`
|
||||
Entity string `json:"entity" gorm:"not null; index:idx_entity"`
|
||||
Type string `json:"type"`
|
||||
Category string `json:"category"`
|
||||
Project string `json:"project"`
|
||||
Branch string `json:"branch"`
|
||||
Language string `json:"language" gorm:"index:idx_language"`
|
||||
IsWrite bool `json:"is_write"`
|
||||
Editor string `json:"editor" hash:"ignore"` // ignored because editor might be parsed differently by wakatime
|
||||
OperatingSystem string `json:"operating_system" hash:"ignore"` // ignored because os might be parsed differently by wakatime
|
||||
Machine string `json:"machine" hash:"ignore"` // ignored because wakatime api doesn't return machines currently
|
||||
Time CustomTime `json:"time" gorm:"type:timestamp; default:CURRENT_TIMESTAMP; index:idx_time,idx_time_user" swaggertype:"primitive,number"`
|
||||
Hash string `json:"-" gorm:"type:varchar(17); uniqueIndex"`
|
||||
Origin string `json:"-" hash:"ignore"`
|
||||
OriginId string `json:"-" hash:"ignore"`
|
||||
languageRegex *regexp.Regexp `hash:"ignore"`
|
||||
ID uint `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"`
|
||||
Entity string `json:"entity" gorm:"not null; index:idx_entity"`
|
||||
Type string `json:"type"`
|
||||
Category string `json:"category"`
|
||||
Project string `json:"project"`
|
||||
Branch string `json:"branch"`
|
||||
Language string `json:"language" gorm:"index:idx_language"`
|
||||
IsWrite bool `json:"is_write"`
|
||||
Editor string `json:"editor" hash:"ignore"` // ignored because editor might be parsed differently by wakatime
|
||||
OperatingSystem string `json:"operating_system" hash:"ignore"` // ignored because os might be parsed differently by wakatime
|
||||
Machine string `json:"machine" hash:"ignore"` // ignored because wakatime api doesn't return machines currently
|
||||
Time CustomTime `json:"time" gorm:"type:timestamp; index:idx_time,idx_time_user" swaggertype:"primitive,number"`
|
||||
Hash string `json:"-" gorm:"type:varchar(17); uniqueIndex"`
|
||||
Origin string `json:"-" hash:"ignore"`
|
||||
OriginId string `json:"-" hash:"ignore"`
|
||||
CreatedAt CustomTime `json:"created_at" gorm:"type:timestamp" swaggertype:"primitive,number" hash:"ignore"` // https://gorm.io/docs/conventions.html#CreatedAt
|
||||
}
|
||||
|
||||
func (h *Heartbeat) Valid() bool {
|
||||
@ -34,18 +34,12 @@ func (h *Heartbeat) Valid() bool {
|
||||
}
|
||||
|
||||
func (h *Heartbeat) Augment(languageMappings map[string]string) {
|
||||
if h.languageRegex == nil {
|
||||
h.languageRegex = regexp.MustCompile(`^.+\.(.+)$`)
|
||||
for ending, value := range languageMappings {
|
||||
if strings.HasSuffix(h.Entity, "."+ending) {
|
||||
h.Language = value
|
||||
return
|
||||
}
|
||||
}
|
||||
groups := h.languageRegex.FindAllStringSubmatch(h.Entity, -1)
|
||||
if len(groups) == 0 || len(groups[0]) != 2 {
|
||||
return
|
||||
}
|
||||
ending := groups[0][1]
|
||||
if _, ok := languageMappings[ending]; !ok {
|
||||
return
|
||||
}
|
||||
h.Language, _ = languageMappings[ending]
|
||||
}
|
||||
|
||||
func (h *Heartbeat) GetKey(t uint8) (key string) {
|
||||
|
@ -26,17 +26,24 @@ func TestHeartbeat_Valid_MissingUser(t *testing.T) {
|
||||
|
||||
func TestHeartbeat_Augment(t *testing.T) {
|
||||
testMappings := map[string]string{
|
||||
"py": "Python3",
|
||||
"py": "Python3",
|
||||
"foo": "Foo Script",
|
||||
"blade.php": "Blade",
|
||||
}
|
||||
|
||||
sut := &Heartbeat{
|
||||
sut1, sut2 := &Heartbeat{
|
||||
Entity: "~/dev/file.py",
|
||||
Language: "Python",
|
||||
}, &Heartbeat{
|
||||
Entity: "~/dev/file.blade.php",
|
||||
Language: "unknown",
|
||||
}
|
||||
|
||||
sut.Augment(testMappings)
|
||||
sut1.Augment(testMappings)
|
||||
sut2.Augment(testMappings)
|
||||
|
||||
assert.Equal(t, "Python3", sut.Language)
|
||||
assert.Equal(t, "Python3", sut1.Language)
|
||||
assert.Equal(t, "Blade", sut2.Language)
|
||||
}
|
||||
|
||||
func TestHeartbeat_GetKey(t *testing.T) {
|
||||
|
@ -35,7 +35,7 @@ type SummaryItem struct {
|
||||
ID uint `json:"-" gorm:"primary_key"`
|
||||
Summary *Summary `json:"-" gorm:"not null; constraint:OnUpdate:CASCADE,OnDelete:CASCADE"`
|
||||
SummaryID uint `json:"-"`
|
||||
Type uint8 `json:"-"`
|
||||
Type uint8 `json:"-" gorm:"index:idx_type"`
|
||||
Key string `json:"key"`
|
||||
Total time.Duration `json:"total" swaggertype:"primitive,integer"`
|
||||
}
|
||||
|
@ -1,8 +1,23 @@
|
||||
package models
|
||||
|
||||
import "regexp"
|
||||
|
||||
const (
|
||||
MailPattern = "[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\\.[a-zA-Z0-9-.]+"
|
||||
)
|
||||
|
||||
var (
|
||||
mailRegex *regexp.Regexp
|
||||
)
|
||||
|
||||
func init() {
|
||||
mailRegex = regexp.MustCompile(MailPattern)
|
||||
}
|
||||
|
||||
type User struct {
|
||||
ID string `json:"id" gorm:"primary_key"`
|
||||
ApiKey string `json:"api_key" gorm:"unique"`
|
||||
Email string `json:"email"`
|
||||
Password string `json:"-"`
|
||||
CreatedAt CustomTime `gorm:"type:timestamp; default:CURRENT_TIMESTAMP" swaggertype:"string" format:"date" example:"2006-01-02 15:04:05.000"`
|
||||
LastLoggedInAt CustomTime `gorm:"type:timestamp; default:CURRENT_TIMESTAMP" swaggertype:"string" format:"date" example:"2006-01-02 15:04:05.000"`
|
||||
@ -24,6 +39,7 @@ type Login struct {
|
||||
|
||||
type Signup struct {
|
||||
Username string `schema:"username"`
|
||||
Email string `schema:"email"`
|
||||
Password string `schema:"password"`
|
||||
PasswordRepeat string `schema:"password_repeat"`
|
||||
}
|
||||
@ -34,6 +50,10 @@ type CredentialsReset struct {
|
||||
PasswordRepeat string `schema:"password_repeat"`
|
||||
}
|
||||
|
||||
type UserDataUpdate struct {
|
||||
Email string `schema:"email"`
|
||||
}
|
||||
|
||||
type TimeByUser struct {
|
||||
User string
|
||||
Time CustomTime
|
||||
@ -45,20 +65,29 @@ type CountByUser struct {
|
||||
}
|
||||
|
||||
func (c *CredentialsReset) IsValid() bool {
|
||||
return validatePassword(c.PasswordNew) &&
|
||||
return ValidatePassword(c.PasswordNew) &&
|
||||
c.PasswordNew == c.PasswordRepeat
|
||||
}
|
||||
|
||||
func (s *Signup) IsValid() bool {
|
||||
return validateUsername(s.Username) &&
|
||||
validatePassword(s.Password) &&
|
||||
return ValidateUsername(s.Username) &&
|
||||
ValidateEmail(s.Email) &&
|
||||
ValidatePassword(s.Password) &&
|
||||
s.Password == s.PasswordRepeat
|
||||
}
|
||||
|
||||
func validateUsername(username string) bool {
|
||||
func (r *UserDataUpdate) IsValid() bool {
|
||||
return ValidateEmail(r.Email)
|
||||
}
|
||||
|
||||
func ValidateUsername(username string) bool {
|
||||
return len(username) >= 1 && username != "current"
|
||||
}
|
||||
|
||||
func validatePassword(password string) bool {
|
||||
func ValidatePassword(password string) bool {
|
||||
return len(password) >= 6
|
||||
}
|
||||
|
||||
func ValidateEmail(email string) bool {
|
||||
return email == "" || mailRegex.Match([]byte(email))
|
||||
}
|
||||
|
346
postman/Wakapi.postman_collection.json
Normal file
346
postman/Wakapi.postman_collection.json
Normal file
@ -0,0 +1,346 @@
|
||||
{
|
||||
"info": {
|
||||
"_postman_id": "3dcc346d-a9a8-4699-8a52-459eb978b382",
|
||||
"name": "Wakapi",
|
||||
"schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json"
|
||||
},
|
||||
"item": [
|
||||
{
|
||||
"name": "Misc",
|
||||
"item": [
|
||||
{
|
||||
"name": "Get health",
|
||||
"request": {
|
||||
"method": "GET",
|
||||
"header": [],
|
||||
"url": {
|
||||
"raw": "{{BASE_URL}}/api/health",
|
||||
"host": [
|
||||
"{{BASE_URL}}"
|
||||
],
|
||||
"path": [
|
||||
"api",
|
||||
"health"
|
||||
]
|
||||
}
|
||||
},
|
||||
"response": []
|
||||
},
|
||||
{
|
||||
"name": "Get metrics",
|
||||
"request": {
|
||||
"method": "GET",
|
||||
"header": [
|
||||
{
|
||||
"key": "Authorization",
|
||||
"value": "Basic {{TOKEN}}",
|
||||
"type": "text"
|
||||
}
|
||||
],
|
||||
"url": {
|
||||
"raw": "{{BASE_URL}}/api/metrics",
|
||||
"host": [
|
||||
"{{BASE_URL}}"
|
||||
],
|
||||
"path": [
|
||||
"api",
|
||||
"metrics"
|
||||
]
|
||||
}
|
||||
},
|
||||
"response": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "Heartbeats",
|
||||
"item": [
|
||||
{
|
||||
"name": "Create heartbeat",
|
||||
"request": {
|
||||
"method": "POST",
|
||||
"header": [
|
||||
{
|
||||
"key": "Authorization",
|
||||
"value": "Basic {{TOKEN}}",
|
||||
"type": "text"
|
||||
},
|
||||
{
|
||||
"key": "X-Machine-Name",
|
||||
"value": "devmachine",
|
||||
"type": "text"
|
||||
},
|
||||
{
|
||||
"key": "User-Agent",
|
||||
"value": "wakatime/13.0.7 (Linux-4.15.0-91-generic-x86_64-with-glibc2.4) Python3.8.0.final.0 generator/1.42.1 generator-wakatime/4.0.0",
|
||||
"type": "text"
|
||||
}
|
||||
],
|
||||
"body": {
|
||||
"mode": "raw",
|
||||
"raw": "[{\n \"entity\": \"/home/user1/dev/proejct1/main.go\",\n \"project\": \"Project 1\",\n \"language\": \"Go\",\n \"is_write\": true,\n \"type\": \"file\",\n \"category\": null,\n \"branch\": null,\n \"time\": 1616680499.113417\n}]",
|
||||
"options": {
|
||||
"raw": {
|
||||
"language": "json"
|
||||
}
|
||||
}
|
||||
},
|
||||
"url": {
|
||||
"raw": "{{BASE_URL}}/api/heartbeat",
|
||||
"host": [
|
||||
"{{BASE_URL}}"
|
||||
],
|
||||
"path": [
|
||||
"api",
|
||||
"heartbeat"
|
||||
]
|
||||
}
|
||||
},
|
||||
"response": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "Summary",
|
||||
"item": [
|
||||
{
|
||||
"name": "Get summary",
|
||||
"request": {
|
||||
"method": "GET",
|
||||
"header": [
|
||||
{
|
||||
"key": "Authorization",
|
||||
"value": "Basic {{TOKEN}}",
|
||||
"type": "text"
|
||||
}
|
||||
],
|
||||
"url": {
|
||||
"raw": "{{BASE_URL}}/api/summary?interval=last_7_days",
|
||||
"host": [
|
||||
"{{BASE_URL}}"
|
||||
],
|
||||
"path": [
|
||||
"api",
|
||||
"summary"
|
||||
],
|
||||
"query": [
|
||||
{
|
||||
"key": "interval",
|
||||
"value": "last_7_days"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"response": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "Shields",
|
||||
"item": [
|
||||
{
|
||||
"name": "Get Shields data",
|
||||
"request": {
|
||||
"method": "GET",
|
||||
"header": [
|
||||
{
|
||||
"key": "Authorization",
|
||||
"value": "Basic {{TOKEN}}",
|
||||
"type": "text"
|
||||
}
|
||||
],
|
||||
"url": {
|
||||
"raw": "{{BASE_URL}}/api/compat/shields/v1/n1try/interval:today/language:Go",
|
||||
"host": [
|
||||
"{{BASE_URL}}"
|
||||
],
|
||||
"path": [
|
||||
"api",
|
||||
"compat",
|
||||
"shields",
|
||||
"v1",
|
||||
"n1try",
|
||||
"interval:today",
|
||||
"language:Go"
|
||||
]
|
||||
}
|
||||
},
|
||||
"response": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "WakaTime",
|
||||
"item": [
|
||||
{
|
||||
"name": "Get all time",
|
||||
"request": {
|
||||
"method": "GET",
|
||||
"header": [
|
||||
{
|
||||
"key": "Authorization",
|
||||
"value": "Basic {{TOKEN}}",
|
||||
"type": "text"
|
||||
}
|
||||
],
|
||||
"url": {
|
||||
"raw": "{{BASE_URL}}/api/compat/wakatime/v1/users/current/all_time_since_today",
|
||||
"host": [
|
||||
"{{BASE_URL}}"
|
||||
],
|
||||
"path": [
|
||||
"api",
|
||||
"compat",
|
||||
"wakatime",
|
||||
"v1",
|
||||
"users",
|
||||
"current",
|
||||
"all_time_since_today"
|
||||
]
|
||||
}
|
||||
},
|
||||
"response": []
|
||||
},
|
||||
{
|
||||
"name": "Get stats",
|
||||
"request": {
|
||||
"method": "GET",
|
||||
"header": [
|
||||
{
|
||||
"key": "Authorization",
|
||||
"value": "Basic {{TOKEN}}",
|
||||
"type": "text"
|
||||
}
|
||||
],
|
||||
"url": {
|
||||
"raw": "{{BASE_URL}}/api/compat/wakatime/v1/users/current/stats",
|
||||
"host": [
|
||||
"{{BASE_URL}}"
|
||||
],
|
||||
"path": [
|
||||
"api",
|
||||
"compat",
|
||||
"wakatime",
|
||||
"v1",
|
||||
"users",
|
||||
"current",
|
||||
"stats"
|
||||
]
|
||||
}
|
||||
},
|
||||
"response": []
|
||||
},
|
||||
{
|
||||
"name": "Get stats with range",
|
||||
"request": {
|
||||
"method": "GET",
|
||||
"header": [
|
||||
{
|
||||
"key": "Authorization",
|
||||
"value": "Basic {{TOKEN}}",
|
||||
"type": "text"
|
||||
}
|
||||
],
|
||||
"url": {
|
||||
"raw": "{{BASE_URL}}/api/compat/wakatime/v1/users/current/stats/last_7_days",
|
||||
"host": [
|
||||
"{{BASE_URL}}"
|
||||
],
|
||||
"path": [
|
||||
"api",
|
||||
"compat",
|
||||
"wakatime",
|
||||
"v1",
|
||||
"users",
|
||||
"current",
|
||||
"stats",
|
||||
"last_7_days"
|
||||
]
|
||||
}
|
||||
},
|
||||
"response": []
|
||||
},
|
||||
{
|
||||
"name": "Get summaries",
|
||||
"request": {
|
||||
"method": "GET",
|
||||
"header": [
|
||||
{
|
||||
"key": "Authorization",
|
||||
"value": "Basic {{TOKEN}}",
|
||||
"type": "text"
|
||||
}
|
||||
],
|
||||
"url": {
|
||||
"raw": "{{BASE_URL}}/api/compat/wakatime/v1/users/current/summaries?start=2020-03-01T15:04:05Z&end=2020-03-31T15:04:05Z",
|
||||
"host": [
|
||||
"{{BASE_URL}}"
|
||||
],
|
||||
"path": [
|
||||
"api",
|
||||
"compat",
|
||||
"wakatime",
|
||||
"v1",
|
||||
"users",
|
||||
"current",
|
||||
"summaries"
|
||||
],
|
||||
"query": [
|
||||
{
|
||||
"key": "start",
|
||||
"value": "2020-03-01T15:04:05Z"
|
||||
},
|
||||
{
|
||||
"key": "end",
|
||||
"value": "2020-03-31T15:04:05Z"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"response": []
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"event": [
|
||||
{
|
||||
"listen": "prerequest",
|
||||
"script": {
|
||||
"type": "text/javascript",
|
||||
"exec": [
|
||||
"const apiKey = pm.variables.get('API_KEY')",
|
||||
"",
|
||||
"if (!apiKey) {",
|
||||
" throw new Error('no api key given')",
|
||||
"}",
|
||||
"",
|
||||
"const token = base64encode(apiKey)",
|
||||
"pm.variables.set('TOKEN', token)",
|
||||
"",
|
||||
"function base64encode(str) {",
|
||||
" return Buffer.from(str, 'utf-8').toString('base64')",
|
||||
"}"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"listen": "test",
|
||||
"script": {
|
||||
"type": "text/javascript",
|
||||
"exec": [
|
||||
""
|
||||
]
|
||||
}
|
||||
}
|
||||
],
|
||||
"variable": [
|
||||
{
|
||||
"key": "BASE_URL",
|
||||
"value": "http://localhost:3000"
|
||||
},
|
||||
{
|
||||
"key": "API_KEY",
|
||||
"value": ""
|
||||
}
|
||||
]
|
||||
}
|
@ -109,6 +109,7 @@ func (r *UserRepository) Update(user *models.User) (*models.User, error) {
|
||||
updateMap := map[string]interface{}{
|
||||
"api_key": user.ApiKey,
|
||||
"password": user.Password,
|
||||
"email": user.Email,
|
||||
"last_logged_in_at": user.LastLoggedInAt,
|
||||
"share_data_max_days": user.ShareDataMaxDays,
|
||||
"share_editors": user.ShareEditors,
|
||||
|
@ -53,7 +53,7 @@ func (h *HeartbeatApiHandler) RegisterRoutes(router *mux.Router) {
|
||||
// @Router /heartbeat [post]
|
||||
func (h *HeartbeatApiHandler) Post(w http.ResponseWriter, r *http.Request) {
|
||||
var heartbeats []*models.Heartbeat
|
||||
user := r.Context().Value(models.UserKey).(*models.User)
|
||||
user := middlewares.GetPrincipal(r)
|
||||
opSys, editor, _ := utils.ParseUserAgent(r.Header.Get("User-Agent"))
|
||||
machineName := r.Header.Get("X-Machine-Name")
|
||||
|
||||
|
@ -68,7 +68,7 @@ func (h *MetricsHandler) RegisterRoutes(router *mux.Router) {
|
||||
}
|
||||
|
||||
func (h *MetricsHandler) Get(w http.ResponseWriter, r *http.Request) {
|
||||
reqUser := r.Context().Value(models.UserKey).(*models.User)
|
||||
reqUser := middlewares.GetPrincipal(r)
|
||||
if reqUser == nil {
|
||||
w.WriteHeader(http.StatusUnauthorized)
|
||||
w.Write([]byte(conf.ErrUnauthorized))
|
||||
@ -108,7 +108,7 @@ func (h *MetricsHandler) Get(w http.ResponseWriter, r *http.Request) {
|
||||
func (h *MetricsHandler) getUserMetrics(user *models.User) (*mm.Metrics, error) {
|
||||
var metrics mm.Metrics
|
||||
|
||||
summaryAllTime, err := h.summarySrvc.Aliased(time.Time{}, time.Now(), user, h.summarySrvc.Retrieve)
|
||||
summaryAllTime, err := h.summarySrvc.Aliased(time.Time{}, time.Now(), user, h.summarySrvc.Retrieve, false)
|
||||
if err != nil {
|
||||
logbuch.Error("failed to retrieve all time summary for user '%s' for metric", user.ID)
|
||||
return nil, err
|
||||
@ -116,7 +116,7 @@ func (h *MetricsHandler) getUserMetrics(user *models.User) (*mm.Metrics, error)
|
||||
|
||||
from, to := utils.MustResolveIntervalRaw("today")
|
||||
|
||||
summaryToday, err := h.summarySrvc.Aliased(from, to, user, h.summarySrvc.Retrieve)
|
||||
summaryToday, err := h.summarySrvc.Aliased(from, to, user, h.summarySrvc.Retrieve, false)
|
||||
if err != nil {
|
||||
logbuch.Error("failed to retrieve today's summary for user '%s' for metric", user.ID)
|
||||
return nil, err
|
||||
|
@ -1,15 +1,16 @@
|
||||
package v1
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/gorilla/mux"
|
||||
conf "github.com/muety/wakapi/config"
|
||||
"github.com/muety/wakapi/models"
|
||||
v1 "github.com/muety/wakapi/models/compat/shields/v1"
|
||||
"github.com/muety/wakapi/services"
|
||||
"github.com/muety/wakapi/utils"
|
||||
"github.com/patrickmn/go-cache"
|
||||
"net/http"
|
||||
"regexp"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
@ -22,12 +23,14 @@ type BadgeHandler struct {
|
||||
config *conf.Config
|
||||
userSrvc services.IUserService
|
||||
summarySrvc services.ISummaryService
|
||||
cache *cache.Cache
|
||||
}
|
||||
|
||||
func NewBadgeHandler(summaryService services.ISummaryService, userService services.IUserService) *BadgeHandler {
|
||||
return &BadgeHandler{
|
||||
summarySrvc: summaryService,
|
||||
userSrvc: userService,
|
||||
cache: cache.New(time.Hour, time.Hour),
|
||||
config: conf.Get(),
|
||||
}
|
||||
}
|
||||
@ -52,11 +55,6 @@ func (h *BadgeHandler) Get(w http.ResponseWriter, r *http.Request) {
|
||||
intervalReg := regexp.MustCompile(intervalPattern)
|
||||
entityFilterReg := regexp.MustCompile(entityFilterPattern)
|
||||
|
||||
if userAgent := r.Header.Get("user-agent"); !strings.HasPrefix(userAgent, "Shields.io/") && !h.config.IsDev() {
|
||||
w.WriteHeader(http.StatusForbidden)
|
||||
return
|
||||
}
|
||||
|
||||
var filterEntity, filterKey string
|
||||
if groups := entityFilterReg.FindStringSubmatch(r.URL.Path); len(groups) > 2 {
|
||||
filterEntity, filterKey = groups[1], groups[2]
|
||||
@ -101,6 +99,12 @@ func (h *BadgeHandler) Get(w http.ResponseWriter, r *http.Request) {
|
||||
filters = &models.Filters{}
|
||||
}
|
||||
|
||||
cacheKey := fmt.Sprintf("%s_%v_%s_%s", user.ID, *interval, filterEntity, filterKey)
|
||||
if cacheResult, ok := h.cache.Get(cacheKey); ok {
|
||||
utils.RespondJSON(w, http.StatusOK, cacheResult.(*v1.BadgeData))
|
||||
return
|
||||
}
|
||||
|
||||
summary, err, status := h.loadUserSummary(user, interval)
|
||||
if err != nil {
|
||||
w.WriteHeader(status)
|
||||
@ -109,6 +113,7 @@ func (h *BadgeHandler) Get(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
vm := v1.NewBadgeDataFrom(summary, filters)
|
||||
h.cache.SetDefault(cacheKey, vm)
|
||||
utils.RespondJSON(w, http.StatusOK, vm)
|
||||
}
|
||||
|
||||
@ -129,7 +134,7 @@ func (h *BadgeHandler) loadUserSummary(user *models.User, interval *models.Inter
|
||||
retrieveSummary = h.summarySrvc.Summarize
|
||||
}
|
||||
|
||||
summary, err := h.summarySrvc.Aliased(summaryParams.From, summaryParams.To, summaryParams.User, retrieveSummary)
|
||||
summary, err := h.summarySrvc.Aliased(summaryParams.From, summaryParams.To, summaryParams.User, retrieveSummary, summaryParams.Recompute)
|
||||
if err != nil {
|
||||
return nil, err, http.StatusInternalServerError
|
||||
}
|
||||
|
@ -49,7 +49,7 @@ func (h *AllTimeHandler) Get(w http.ResponseWriter, r *http.Request) {
|
||||
values, _ := url.ParseQuery(r.URL.RawQuery)
|
||||
|
||||
requestedUser := vars["user"]
|
||||
authorizedUser := r.Context().Value(models.UserKey).(*models.User)
|
||||
authorizedUser := middlewares.GetPrincipal(r)
|
||||
|
||||
if requestedUser != authorizedUser.ID && requestedUser != "current" {
|
||||
w.WriteHeader(http.StatusForbidden)
|
||||
@ -80,7 +80,7 @@ func (h *AllTimeHandler) loadUserSummary(user *models.User) (*models.Summary, er
|
||||
retrieveSummary = h.summarySrvc.Summarize
|
||||
}
|
||||
|
||||
summary, err := h.summarySrvc.Aliased(summaryParams.From, summaryParams.To, summaryParams.User, retrieveSummary)
|
||||
summary, err := h.summarySrvc.Aliased(summaryParams.From, summaryParams.To, summaryParams.User, retrieveSummary, summaryParams.Recompute)
|
||||
if err != nil {
|
||||
return nil, err, http.StatusInternalServerError
|
||||
}
|
||||
|
@ -45,10 +45,7 @@ func (h *StatsHandler) Get(w http.ResponseWriter, r *http.Request) {
|
||||
var vars = mux.Vars(r)
|
||||
var authorizedUser, requestedUser *models.User
|
||||
|
||||
if u := r.Context().Value(models.UserKey); u != nil {
|
||||
authorizedUser = u.(*models.User)
|
||||
}
|
||||
|
||||
authorizedUser = middlewares.GetPrincipal(r)
|
||||
if authorizedUser != nil && vars["user"] == "current" {
|
||||
vars["user"] = authorizedUser.ID
|
||||
}
|
||||
@ -117,7 +114,7 @@ func (h *StatsHandler) loadUserSummary(user *models.User, start, end time.Time)
|
||||
Recompute: false,
|
||||
}
|
||||
|
||||
summary, err := h.summarySrvc.Aliased(overallParams.From, overallParams.To, user, h.summarySrvc.Retrieve)
|
||||
summary, err := h.summarySrvc.Aliased(overallParams.From, overallParams.To, user, h.summarySrvc.Retrieve, false)
|
||||
if err != nil {
|
||||
return nil, err, http.StatusInternalServerError
|
||||
}
|
||||
|
@ -56,7 +56,7 @@ func (h *SummariesHandler) RegisterRoutes(router *mux.Router) {
|
||||
func (h *SummariesHandler) Get(w http.ResponseWriter, r *http.Request) {
|
||||
vars := mux.Vars(r)
|
||||
requestedUser := vars["user"]
|
||||
authorizedUser := r.Context().Value(models.UserKey).(*models.User)
|
||||
authorizedUser := middlewares.GetPrincipal(r)
|
||||
|
||||
if requestedUser != authorizedUser.ID && requestedUser != "current" {
|
||||
w.WriteHeader(http.StatusForbidden)
|
||||
@ -80,7 +80,7 @@ func (h *SummariesHandler) Get(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
func (h *SummariesHandler) loadUserSummaries(r *http.Request) ([]*models.Summary, error, int) {
|
||||
user := r.Context().Value(models.UserKey).(*models.User)
|
||||
user := middlewares.GetPrincipal(r)
|
||||
params := r.URL.Query()
|
||||
rangeParam, startParam, endParam := params.Get("range"), params.Get("start"), params.Get("end")
|
||||
|
||||
@ -121,7 +121,7 @@ func (h *SummariesHandler) loadUserSummaries(r *http.Request) ([]*models.Summary
|
||||
summaries := make([]*models.Summary, len(intervals))
|
||||
|
||||
for i, interval := range intervals {
|
||||
summary, err := h.summarySrvc.Aliased(interval[0], interval[1], user, h.summarySrvc.Retrieve)
|
||||
summary, err := h.summarySrvc.Aliased(interval[0], interval[1], user, h.summarySrvc.Retrieve, false)
|
||||
if err != nil {
|
||||
return nil, err, http.StatusInternalServerError
|
||||
}
|
||||
|
@ -35,6 +35,9 @@ func loadTemplates() {
|
||||
"toRunes": utils.ToRunes,
|
||||
"entityTypes": models.SummaryTypes,
|
||||
"typeName": typeName,
|
||||
"isDev": func() bool {
|
||||
return config.Get().IsDev()
|
||||
},
|
||||
"getBasePath": func() string {
|
||||
return config.Get().Server.BasePath
|
||||
},
|
||||
|
@ -117,6 +117,8 @@ func (h *SettingsHandler) dispatchAction(action string) action {
|
||||
switch action {
|
||||
case "change_password":
|
||||
return h.actionChangePassword
|
||||
case "update_user":
|
||||
return h.actionUpdateUser
|
||||
case "reset_apikey":
|
||||
return h.actionResetApiKey
|
||||
case "delete_alias":
|
||||
@ -141,12 +143,40 @@ func (h *SettingsHandler) dispatchAction(action string) action {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (h *SettingsHandler) actionUpdateUser(w http.ResponseWriter, r *http.Request) (int, string, string) {
|
||||
if h.config.IsDev() {
|
||||
loadTemplates()
|
||||
}
|
||||
|
||||
user := middlewares.GetPrincipal(r)
|
||||
|
||||
var payload models.UserDataUpdate
|
||||
if err := r.ParseForm(); err != nil {
|
||||
return http.StatusBadRequest, "", "missing parameters"
|
||||
}
|
||||
if err := credentialsDecoder.Decode(&payload, r.PostForm); err != nil {
|
||||
return http.StatusBadRequest, "", "missing parameters"
|
||||
}
|
||||
|
||||
if !payload.IsValid() {
|
||||
return http.StatusBadRequest, "", "invalid parameters"
|
||||
}
|
||||
|
||||
user.Email = payload.Email
|
||||
|
||||
if _, err := h.userSrvc.Update(user); err != nil {
|
||||
return http.StatusInternalServerError, "", conf.ErrInternalServerError
|
||||
}
|
||||
|
||||
return http.StatusOK, "user updated successfully", ""
|
||||
}
|
||||
|
||||
func (h *SettingsHandler) actionChangePassword(w http.ResponseWriter, r *http.Request) (int, string, string) {
|
||||
if h.config.IsDev() {
|
||||
loadTemplates()
|
||||
}
|
||||
|
||||
user := r.Context().Value(models.UserKey).(*models.User)
|
||||
user := middlewares.GetPrincipal(r)
|
||||
|
||||
var credentials models.CredentialsReset
|
||||
if err := r.ParseForm(); err != nil {
|
||||
@ -193,7 +223,7 @@ func (h *SettingsHandler) actionResetApiKey(w http.ResponseWriter, r *http.Reque
|
||||
loadTemplates()
|
||||
}
|
||||
|
||||
user := r.Context().Value(models.UserKey).(*models.User)
|
||||
user := middlewares.GetPrincipal(r)
|
||||
if _, err := h.userSrvc.ResetApiKey(user); err != nil {
|
||||
return http.StatusInternalServerError, "", conf.ErrInternalServerError
|
||||
}
|
||||
@ -208,7 +238,7 @@ func (h *SettingsHandler) actionUpdateSharing(w http.ResponseWriter, r *http.Req
|
||||
}
|
||||
|
||||
var err error
|
||||
user := r.Context().Value(models.UserKey).(*models.User)
|
||||
user := middlewares.GetPrincipal(r)
|
||||
|
||||
defer h.userSrvc.FlushCache()
|
||||
|
||||
@ -235,7 +265,7 @@ func (h *SettingsHandler) actionDeleteAlias(w http.ResponseWriter, r *http.Reque
|
||||
loadTemplates()
|
||||
}
|
||||
|
||||
user := r.Context().Value(models.UserKey).(*models.User)
|
||||
user := middlewares.GetPrincipal(r)
|
||||
aliasKey := r.PostFormValue("key")
|
||||
aliasType, err := strconv.Atoi(r.PostFormValue("type"))
|
||||
if err != nil {
|
||||
@ -255,7 +285,7 @@ func (h *SettingsHandler) actionAddAlias(w http.ResponseWriter, r *http.Request)
|
||||
if h.config.IsDev() {
|
||||
loadTemplates()
|
||||
}
|
||||
user := r.Context().Value(models.UserKey).(*models.User)
|
||||
user := middlewares.GetPrincipal(r)
|
||||
aliasKey := r.PostFormValue("key")
|
||||
aliasValue := r.PostFormValue("value")
|
||||
aliasType, err := strconv.Atoi(r.PostFormValue("type"))
|
||||
@ -283,19 +313,20 @@ func (h *SettingsHandler) actionDeleteLanguageMapping(w http.ResponseWriter, r *
|
||||
loadTemplates()
|
||||
}
|
||||
|
||||
user := r.Context().Value(models.UserKey).(*models.User)
|
||||
user := middlewares.GetPrincipal(r)
|
||||
id, err := strconv.Atoi(r.PostFormValue("mapping_id"))
|
||||
if err != nil {
|
||||
return http.StatusInternalServerError, "", "could not delete mapping"
|
||||
}
|
||||
|
||||
if mapping, err := h.languageMappingSrvc.GetById(uint(id)); err != nil || mapping == nil {
|
||||
mapping, err := h.languageMappingSrvc.GetById(uint(id))
|
||||
if err != nil || mapping == nil {
|
||||
return http.StatusNotFound, "", "mapping not found"
|
||||
} else if mapping.UserID != user.ID {
|
||||
return http.StatusForbidden, "", "not allowed to delete mapping"
|
||||
}
|
||||
|
||||
if err := h.languageMappingSrvc.Delete(&models.LanguageMapping{ID: uint(id)}); err != nil {
|
||||
if err := h.languageMappingSrvc.Delete(mapping); err != nil {
|
||||
return http.StatusInternalServerError, "", "could not delete mapping"
|
||||
}
|
||||
|
||||
@ -306,7 +337,7 @@ func (h *SettingsHandler) actionAddLanguageMapping(w http.ResponseWriter, r *htt
|
||||
if h.config.IsDev() {
|
||||
loadTemplates()
|
||||
}
|
||||
user := r.Context().Value(models.UserKey).(*models.User)
|
||||
user := middlewares.GetPrincipal(r)
|
||||
extension := r.PostFormValue("extension")
|
||||
language := r.PostFormValue("language")
|
||||
|
||||
@ -332,7 +363,7 @@ func (h *SettingsHandler) actionSetWakatimeApiKey(w http.ResponseWriter, r *http
|
||||
loadTemplates()
|
||||
}
|
||||
|
||||
user := r.Context().Value(models.UserKey).(*models.User)
|
||||
user := middlewares.GetPrincipal(r)
|
||||
apiKey := r.PostFormValue("api_key")
|
||||
|
||||
// Healthcheck, if a new API key is set, i.e. the feature is activated
|
||||
@ -352,7 +383,7 @@ func (h *SettingsHandler) actionImportWaktime(w http.ResponseWriter, r *http.Req
|
||||
loadTemplates()
|
||||
}
|
||||
|
||||
user := r.Context().Value(models.UserKey).(*models.User)
|
||||
user := middlewares.GetPrincipal(r)
|
||||
if user.WakatimeApiKey == "" {
|
||||
return http.StatusForbidden, "", "not connected to wakatime"
|
||||
}
|
||||
@ -420,13 +451,13 @@ func (h *SettingsHandler) actionRegenerateSummaries(w http.ResponseWriter, r *ht
|
||||
loadTemplates()
|
||||
}
|
||||
|
||||
user := r.Context().Value(models.UserKey).(*models.User)
|
||||
go func(user *models.User) {
|
||||
if err := h.regenerateSummaries(user); err != nil {
|
||||
logbuch.Error("failed to regenerate summaries for user '%s' – %v", user.ID, err)
|
||||
}
|
||||
}(middlewares.GetPrincipal(r))
|
||||
|
||||
if err := h.regenerateSummaries(user); err != nil {
|
||||
return http.StatusInternalServerError, "", "failed to regenerate summaries"
|
||||
}
|
||||
|
||||
return http.StatusOK, "summaries are being regenerated – this may take a few seconds", ""
|
||||
return http.StatusAccepted, "summaries are being regenerated – this may take a up to a couple of minutes, please come back later", ""
|
||||
}
|
||||
|
||||
func (h *SettingsHandler) actionDeleteUser(w http.ResponseWriter, r *http.Request) (int, string, string) {
|
||||
@ -434,7 +465,7 @@ func (h *SettingsHandler) actionDeleteUser(w http.ResponseWriter, r *http.Reques
|
||||
loadTemplates()
|
||||
}
|
||||
|
||||
user := r.Context().Value(models.UserKey).(*models.User)
|
||||
user := middlewares.GetPrincipal(r)
|
||||
go func(user *models.User) {
|
||||
logbuch.Info("deleting user '%s' shortly", user.ID)
|
||||
time.Sleep(5 * time.Minute)
|
||||
@ -493,7 +524,7 @@ func (h *SettingsHandler) regenerateSummaries(user *models.User) error {
|
||||
}
|
||||
|
||||
func (h *SettingsHandler) buildViewModel(r *http.Request) *view.SettingsViewModel {
|
||||
user := r.Context().Value(models.UserKey).(*models.User)
|
||||
user := middlewares.GetPrincipal(r)
|
||||
mappings, _ := h.languageMappingSrvc.GetByUser(user.ID)
|
||||
aliases, _ := h.aliasSrvc.GetByUser(user.ID)
|
||||
aliasMap := make(map[string][]*models.Alias)
|
||||
|
@ -53,7 +53,7 @@ func (h *SummaryHandler) GetIndex(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
user := r.Context().Value(models.UserKey).(*models.User)
|
||||
user := middlewares.GetPrincipal(r)
|
||||
if user == nil {
|
||||
w.WriteHeader(http.StatusUnauthorized)
|
||||
templates[conf.SummaryTemplate].Execute(w, h.buildViewModel(r).WithError("unauthorized"))
|
||||
|
@ -18,7 +18,7 @@ func LoadUserSummary(ss services.ISummaryService, r *http.Request) (*models.Summ
|
||||
retrieveSummary = ss.Summarize
|
||||
}
|
||||
|
||||
summary, err := ss.Aliased(summaryParams.From, summaryParams.To, summaryParams.User, retrieveSummary)
|
||||
summary, err := ss.Aliased(summaryParams.From, summaryParams.To, summaryParams.User, retrieveSummary, summaryParams.Recompute)
|
||||
if err != nil {
|
||||
return nil, err, http.StatusInternalServerError
|
||||
}
|
||||
|
@ -1,113 +0,0 @@
|
||||
#!/usr/bin/python3
|
||||
|
||||
import argparse
|
||||
import base64
|
||||
import random
|
||||
import string
|
||||
import sys
|
||||
from datetime import datetime, timedelta
|
||||
from typing import List, Union
|
||||
|
||||
import requests
|
||||
from tqdm import tqdm
|
||||
|
||||
MACHINE = "devmachine"
|
||||
UA = 'wakatime/13.0.7 (Linux-4.15.0-91-generic-x86_64-with-glibc2.4) Python3.8.0.final.0 generator/1.42.1 generator-wakatime/4.0.0'
|
||||
LANGUAGES = {
|
||||
'Go': 'go',
|
||||
'Java': 'java',
|
||||
'JavaScript': 'js',
|
||||
'Python': 'py'
|
||||
}
|
||||
|
||||
|
||||
class Heartbeat:
|
||||
def __init__(
|
||||
self,
|
||||
entity: str,
|
||||
project: str,
|
||||
language: str,
|
||||
time: float,
|
||||
is_write: bool = True,
|
||||
branch: str = 'master',
|
||||
type: str = 'file'
|
||||
):
|
||||
self.entity: str = entity
|
||||
self.project: str = project
|
||||
self.language: str = language
|
||||
self.time: float = time
|
||||
self.is_write: bool = is_write
|
||||
self.branch: str = branch
|
||||
self.type: str = type
|
||||
self.category: Union[str, None] = None
|
||||
|
||||
|
||||
def generate_data(n: int, n_projects: int = 5, n_past_hours: int = 24) -> List[Heartbeat]:
|
||||
data: List[Heartbeat] = []
|
||||
now: datetime = datetime.today()
|
||||
projects: List[str] = [randomword(random.randint(5, 10)) for _ in range(n_projects)]
|
||||
languages: List[str] = list(LANGUAGES.keys())
|
||||
|
||||
for _ in range(n):
|
||||
p: str = random.choice(projects)
|
||||
l: str = random.choice(languages)
|
||||
f: str = randomword(random.randint(2, 8))
|
||||
delta: timedelta = timedelta(
|
||||
hours=random.randint(0, n_past_hours - 1),
|
||||
minutes=random.randint(0, 59),
|
||||
seconds=random.randint(0, 59),
|
||||
milliseconds=random.randint(0, 999),
|
||||
microseconds=random.randint(0, 999)
|
||||
)
|
||||
|
||||
data.append(Heartbeat(
|
||||
entity=f'/home/me/dev/{p}/{f}.{LANGUAGES[l]}',
|
||||
project=p,
|
||||
language=l,
|
||||
time=(now - delta).timestamp()
|
||||
))
|
||||
|
||||
return data
|
||||
|
||||
|
||||
def post_data_sync(data: List[Heartbeat], url: str, api_key: str):
|
||||
encoded_key: str = str(base64.b64encode(api_key.encode('utf-8')), 'utf-8')
|
||||
|
||||
for h in tqdm(data):
|
||||
r = requests.post(url, json=[h.__dict__], headers={
|
||||
'User-Agent': UA,
|
||||
'Authorization': f'Basic {encoded_key}',
|
||||
'X-Machine-Name': MACHINE,
|
||||
})
|
||||
if r.status_code != 201:
|
||||
print(r.text)
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
def randomword(length: int) -> str:
|
||||
letters = string.ascii_lowercase + 'äöü💩' # test utf8 and utf8mb4 characters as well
|
||||
return ''.join(random.choice(letters) for _ in range(length))
|
||||
|
||||
|
||||
def parse_arguments():
|
||||
parser = argparse.ArgumentParser(description='Wakapi test data insertion script.')
|
||||
parser.add_argument('-n', type=int, default=20, help='total number of random heartbeats to generate and insert')
|
||||
parser.add_argument('-u', '--url', type=str, default='http://localhost:3000/api/heartbeat',
|
||||
help='url of your api\'s heartbeats endpoint')
|
||||
parser.add_argument('-k', '--apikey', type=str, required=True,
|
||||
help='your api key (to get one, go to the web interface, create a new user, log in and copy the key)')
|
||||
parser.add_argument('-p', '--projects', type=int, default=5, help='number of different fake projects to generate')
|
||||
parser.add_argument('-o', '--offset', type=int, default=24,
|
||||
help='negative time offset in hours from now for to be used as an interval within which to generate heartbeats for')
|
||||
parser.add_argument('-s', '--seed', type=int, default=2020,
|
||||
help='a seed for initializing the pseudo-random number generator')
|
||||
return parser.parse_args()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
args = parse_arguments()
|
||||
|
||||
random.seed(args.seed)
|
||||
|
||||
data: List[Heartbeat] = generate_data(args.n, args.projects, args.offset)
|
||||
post_data_sync(data, args.url, args.apikey)
|
271
scripts/sample_data.py
Normal file
271
scripts/sample_data.py
Normal file
@ -0,0 +1,271 @@
|
||||
#!/usr/bin/python3
|
||||
|
||||
import argparse
|
||||
import base64
|
||||
import random
|
||||
import string
|
||||
import sys
|
||||
from datetime import datetime, timedelta
|
||||
from typing import List, Union, Callable
|
||||
|
||||
import requests
|
||||
from tqdm import tqdm
|
||||
|
||||
MACHINE = "devmachine"
|
||||
UA = 'wakatime/13.0.7 (Linux-4.15.0-91-generic-x86_64-with-glibc2.4) Python3.8.0.final.0 generator/1.42.1 generator-wakatime/4.0.0'
|
||||
LANGUAGES = {
|
||||
'Go': 'go',
|
||||
'Java': 'java',
|
||||
'JavaScript': 'js',
|
||||
'Python': 'py'
|
||||
}
|
||||
|
||||
|
||||
class Heartbeat:
|
||||
def __init__(
|
||||
self,
|
||||
entity: str,
|
||||
project: str,
|
||||
language: str,
|
||||
time: float,
|
||||
is_write: bool = True,
|
||||
branch: str = 'master',
|
||||
type: str = 'file'
|
||||
):
|
||||
self.entity: str = entity
|
||||
self.project: str = project
|
||||
self.language: str = language
|
||||
self.time: float = time
|
||||
self.is_write: bool = is_write
|
||||
self.branch: str = branch
|
||||
self.type: str = type
|
||||
self.category: Union[str, None] = None
|
||||
|
||||
|
||||
class ConfigParams:
|
||||
def __init__(self):
|
||||
self.api_url = ''
|
||||
self.api_key = ''
|
||||
self.n = 0
|
||||
self.n_projects = 0
|
||||
self.offset = 0
|
||||
self.seed = 0
|
||||
|
||||
|
||||
def generate_data(n: int, n_projects: int = 5, n_past_hours: int = 24) -> List[Heartbeat]:
|
||||
data: List[Heartbeat] = []
|
||||
now: datetime = datetime.today()
|
||||
projects: List[str] = [randomword(random.randint(5, 10)) for _ in range(n_projects)]
|
||||
languages: List[str] = list(LANGUAGES.keys())
|
||||
|
||||
for _ in range(n):
|
||||
p: str = random.choice(projects)
|
||||
l: str = random.choice(languages)
|
||||
f: str = randomword(random.randint(2, 8))
|
||||
delta: timedelta = timedelta(
|
||||
hours=random.randint(0, n_past_hours - 1),
|
||||
minutes=random.randint(0, 59),
|
||||
seconds=random.randint(0, 59),
|
||||
milliseconds=random.randint(0, 999),
|
||||
microseconds=random.randint(0, 999)
|
||||
)
|
||||
|
||||
data.append(Heartbeat(
|
||||
entity=f'/home/me/dev/{p}/{f}.{LANGUAGES[l]}',
|
||||
project=p,
|
||||
language=l,
|
||||
time=(now - delta).timestamp()
|
||||
))
|
||||
|
||||
return data
|
||||
|
||||
|
||||
def post_data_sync(data: List[Heartbeat], url: str, api_key: str):
|
||||
encoded_key: str = str(base64.b64encode(api_key.encode('utf-8')), 'utf-8')
|
||||
|
||||
for h in data:
|
||||
r = requests.post(url, json=[h.__dict__], headers={
|
||||
'User-Agent': UA,
|
||||
'Authorization': f'Basic {encoded_key}',
|
||||
'X-Machine-Name': MACHINE,
|
||||
})
|
||||
if r.status_code != 201:
|
||||
print(r.text)
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
def make_gui(callback: Callable[[ConfigParams, Callable[[int], None]], None]) -> ('QApplication', 'QWidget'):
|
||||
from PyQt5.QtCore import Qt
|
||||
from PyQt5.QtWidgets import QApplication, QWidget, QFormLayout, QHBoxLayout, QVBoxLayout, QGroupBox, QLabel, \
|
||||
QLineEdit, QSpinBox, QProgressBar, QPushButton
|
||||
|
||||
# Main app
|
||||
app = QApplication([])
|
||||
|
||||
window = QWidget()
|
||||
window.setWindowTitle('Wakapi Sample Data Generator')
|
||||
window.setFixedSize(window.sizeHint())
|
||||
window.setMinimumWidth(350)
|
||||
|
||||
container_layout = QVBoxLayout()
|
||||
|
||||
# Top Controls
|
||||
form_layout_1 = QFormLayout()
|
||||
|
||||
url_input_label = QLabel('URL:')
|
||||
url_input = QLineEdit()
|
||||
url_input.setPlaceholderText('Wakatime API Url')
|
||||
url_input.setText('http://localhost:3000/api')
|
||||
|
||||
api_key_input_label = QLabel('API Key:')
|
||||
api_key_input = QLineEdit()
|
||||
api_key_input.setPlaceholderText(f'{"x"*8}-{"x"*4}-{"x"*4}-{"x"*4}-{"x"*12}')
|
||||
|
||||
form_layout_1.addRow(url_input_label, url_input)
|
||||
form_layout_1.addRow(api_key_input_label, api_key_input)
|
||||
|
||||
# Middle controls
|
||||
form_layout_2 = QFormLayout()
|
||||
params_container = QGroupBox('Parameters')
|
||||
params_container.setLayout(form_layout_2)
|
||||
|
||||
heartbeats_input_label = QLabel('# Heartbeats')
|
||||
heartbeats_input = QSpinBox()
|
||||
heartbeats_input.setMaximum(2147483647)
|
||||
heartbeats_input.setValue(100)
|
||||
|
||||
projects_input_label = QLabel('# Projects:')
|
||||
projects_input = QSpinBox()
|
||||
projects_input.setMinimum(1)
|
||||
projects_input.setValue(5)
|
||||
|
||||
offset_input_label = QLabel('Time Offset (hrs):')
|
||||
offset_input = QSpinBox()
|
||||
offset_input.setMinimum(-2147483647)
|
||||
offset_input.setMaximum(0)
|
||||
offset_input.setValue(-12)
|
||||
|
||||
seed_input_label = QLabel('Random Seed:')
|
||||
seed_input = QSpinBox()
|
||||
seed_input.setMaximum(2147483647)
|
||||
seed_input.setValue(1337)
|
||||
|
||||
form_layout_2.addRow(heartbeats_input_label, heartbeats_input)
|
||||
form_layout_2.addRow(projects_input_label, projects_input)
|
||||
form_layout_2.addRow(offset_input_label, offset_input)
|
||||
form_layout_2.addRow(seed_input_label, seed_input)
|
||||
|
||||
# Bottom controls
|
||||
bottom_layout = QHBoxLayout()
|
||||
|
||||
start_button = QPushButton('Generate')
|
||||
progress_bar = QProgressBar()
|
||||
|
||||
bottom_layout.addWidget(progress_bar)
|
||||
bottom_layout.addWidget(start_button)
|
||||
|
||||
# Wiring up
|
||||
container_layout.addLayout(form_layout_1)
|
||||
container_layout.addWidget(params_container)
|
||||
container_layout.addLayout(bottom_layout)
|
||||
container_layout.setStretch(1, 1)
|
||||
|
||||
window.setLayout(container_layout)
|
||||
|
||||
# Done dialog
|
||||
done_dialog = QWidget()
|
||||
done_dialog.setWindowTitle('Done')
|
||||
done_ok_button = QPushButton('Ok')
|
||||
done_layout = QVBoxLayout()
|
||||
done_layout.addWidget(QLabel('Done!'), alignment=Qt.AlignCenter)
|
||||
done_layout.addWidget(done_ok_button, alignment=Qt.AlignCenter)
|
||||
done_dialog.setFixedSize(done_dialog.sizeHint())
|
||||
done_ok_button.clicked.connect(done_dialog.close)
|
||||
done_dialog.setLayout(done_layout)
|
||||
|
||||
# Logic
|
||||
def parse_params() -> ConfigParams:
|
||||
params = ConfigParams()
|
||||
params.api_url = url_input.text()
|
||||
params.api_key = api_key_input.text()
|
||||
params.n = heartbeats_input.value()
|
||||
params.n_projects = projects_input.value()
|
||||
params.offset = offset_input.value()
|
||||
params.seed = seed_input.value()
|
||||
return params
|
||||
|
||||
def update_progress(inc=1):
|
||||
current = progress_bar.value()
|
||||
updated = current + inc
|
||||
if updated == progress_bar.maximum() - 1:
|
||||
progress_bar.setValue(0)
|
||||
start_button.setEnabled(True)
|
||||
done_dialog.show()
|
||||
return
|
||||
progress_bar.setValue(updated)
|
||||
|
||||
def call_back():
|
||||
params = parse_params()
|
||||
progress_bar.setMaximum(params.n)
|
||||
start_button.setEnabled(False)
|
||||
callback(params, update_progress)
|
||||
|
||||
start_button.clicked.connect(call_back)
|
||||
|
||||
return app, window
|
||||
|
||||
|
||||
def parse_arguments():
|
||||
parser = argparse.ArgumentParser(description='Wakapi test data insertion script.')
|
||||
parser.add_argument('--headless', default=False, help='do not show a gui', action='store_true')
|
||||
parser.add_argument('-n', type=int, default=20, help='total number of random heartbeats to generate and insert')
|
||||
parser.add_argument('-u', '--url', type=str, default='http://localhost:3000/api',
|
||||
help='url of your api\'s heartbeats endpoint')
|
||||
parser.add_argument('-k', '--apikey', type=str,
|
||||
help='your api key (to get one, go to the web interface, create a new user, log in and copy the key)')
|
||||
parser.add_argument('-p', '--projects', type=int, default=5, help='number of different fake projects to generate')
|
||||
parser.add_argument('-o', '--offset', type=int, default=24,
|
||||
help='negative time offset in hours from now for to be used as an interval within which to generate heartbeats for')
|
||||
parser.add_argument('-s', '--seed', type=int, default=2020,
|
||||
help='a seed for initializing the pseudo-random number generator')
|
||||
return parser.parse_args()
|
||||
|
||||
|
||||
def args_to_params(parsed_args: argparse.Namespace) -> (ConfigParams, bool):
|
||||
params = ConfigParams()
|
||||
params.n = parsed_args.n
|
||||
params.n_projects = parsed_args.projects
|
||||
params.offset = parsed_args.offset
|
||||
params.seed = parsed_args.seed
|
||||
params.api_url = parsed_args.url
|
||||
params.api_key = parsed_args.apikey
|
||||
return params, not parsed_args.headless
|
||||
|
||||
|
||||
def randomword(length: int) -> str:
|
||||
letters = string.ascii_lowercase + 'äöü💩' # test utf8 and utf8mb4 characters as well
|
||||
return ''.join(random.choice(letters) for _ in range(length))
|
||||
|
||||
|
||||
def run(params: ConfigParams, update_progress: Callable[[int], None]):
|
||||
random.seed(params.seed)
|
||||
data: List[Heartbeat] = generate_data(
|
||||
params.n,
|
||||
params.n_projects,
|
||||
params.offset * -1 if params.offset < 0 else params.offset
|
||||
)
|
||||
|
||||
for d in data:
|
||||
post_data_sync([d], f'{params.api_url}/heartbeats', params.api_key)
|
||||
update_progress(1)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
params, show_gui = args_to_params(parse_arguments())
|
||||
if show_gui:
|
||||
app, window = make_gui(callback=run)
|
||||
window.show()
|
||||
app.exec()
|
||||
else:
|
||||
pbar = tqdm(total=params.n)
|
||||
run(params, pbar.update)
|
@ -27,7 +27,18 @@ func (srv *HeartbeatService) Insert(heartbeat *models.Heartbeat) error {
|
||||
}
|
||||
|
||||
func (srv *HeartbeatService) InsertBatch(heartbeats []*models.Heartbeat) error {
|
||||
return srv.repository.InsertBatch(heartbeats)
|
||||
hashes := make(map[string]bool)
|
||||
|
||||
// https://github.com/muety/wakapi/issues/139
|
||||
filteredHeartbeats := make([]*models.Heartbeat, 0, len(heartbeats))
|
||||
for _, hb := range heartbeats {
|
||||
if _, ok := hashes[hb.Hash]; !ok {
|
||||
filteredHeartbeats = append(filteredHeartbeats, hb)
|
||||
hashes[hb.Hash] = true
|
||||
}
|
||||
}
|
||||
|
||||
return srv.repository.InsertBatch(filteredHeartbeats)
|
||||
}
|
||||
|
||||
func (srv *HeartbeatService) Count() (int64, error) {
|
||||
|
@ -79,7 +79,7 @@ func (srv *MiscService) runCountTotalTime() error {
|
||||
|
||||
func (srv *MiscService) countTotalTimeWorker(jobs <-chan *CountTotalTimeJob, results chan<- *CountTotalTimeResult) {
|
||||
for job := range jobs {
|
||||
if result, err := srv.summaryService.Aliased(time.Time{}, time.Now(), &models.User{ID: job.UserID}, srv.summaryService.Retrieve); err != nil {
|
||||
if result, err := srv.summaryService.Aliased(time.Time{}, time.Now(), &models.User{ID: job.UserID}, srv.summaryService.Retrieve, false); err != nil {
|
||||
logbuch.Error("failed to count total for user %s: %v", job.UserID, err)
|
||||
} else {
|
||||
logbuch.Info("successfully counted total for user %s", job.UserID)
|
||||
|
@ -53,7 +53,7 @@ type ILanguageMappingService interface {
|
||||
}
|
||||
|
||||
type ISummaryService interface {
|
||||
Aliased(time.Time, time.Time, *models.User, SummaryRetriever) (*models.Summary, error)
|
||||
Aliased(time.Time, time.Time, *models.User, SummaryRetriever, bool) (*models.Summary, error)
|
||||
Retrieve(time.Time, time.Time, *models.User) (*models.Summary, error)
|
||||
Summarize(time.Time, time.Time, *models.User) (*models.Summary, error)
|
||||
GetLatestByUser() ([]*models.TimeByUser, error)
|
||||
|
@ -36,10 +36,10 @@ func NewSummaryService(summaryRepo repositories.ISummaryRepository, heartbeatSer
|
||||
|
||||
// Public summary generation methods
|
||||
|
||||
func (srv *SummaryService) Aliased(from, to time.Time, user *models.User, f SummaryRetriever) (*models.Summary, error) {
|
||||
func (srv *SummaryService) Aliased(from, to time.Time, user *models.User, f SummaryRetriever, skipCache bool) (*models.Summary, error) {
|
||||
// Check cache
|
||||
cacheKey := srv.getHash(from.String(), to.String(), user.ID, "--aliased")
|
||||
if cacheResult, ok := srv.cache.Get(cacheKey); ok {
|
||||
if cacheResult, ok := srv.cache.Get(cacheKey); ok && !skipCache {
|
||||
return cacheResult.(*models.Summary), nil
|
||||
}
|
||||
|
||||
|
@ -253,7 +253,7 @@ func (suite *SummaryServiceTestSuite) TestSummaryService_Aliased() {
|
||||
suite.AliasService.On("GetAliasOrDefault", TestUserId, models.SummaryProject, TestProject1).Return(TestProject2, nil)
|
||||
suite.AliasService.On("GetAliasOrDefault", TestUserId, mock.Anything, mock.Anything).Return("", nil)
|
||||
|
||||
result, err = sut.Aliased(from, to, suite.TestUser, sut.Summarize)
|
||||
result, err = sut.Aliased(from, to, suite.TestUser, sut.Summarize, false)
|
||||
|
||||
assert.Nil(suite.T(), err)
|
||||
assert.NotNil(suite.T(), result)
|
||||
|
@ -68,6 +68,7 @@ func (srv *UserService) Count() (int64, error) {
|
||||
func (srv *UserService) CreateOrGet(signup *models.Signup, isAdmin bool) (*models.User, bool, error) {
|
||||
u := &models.User{
|
||||
ID: signup.Username,
|
||||
Email: signup.Email,
|
||||
ApiKey: uuid.NewV4().String(),
|
||||
Password: signup.Password,
|
||||
IsAdmin: isAdmin,
|
||||
|
@ -1,3 +1,3 @@
|
||||
sonar.exclusions=**/*_test.go,.idea/**,.vscode/**,mocks/**
|
||||
sonar.exclusions=**/*_test.go,.idea/**,.vscode/**,mocks/**,static/**
|
||||
sonar.tests=.
|
||||
sonar.go.coverage.reportPaths=coverage/coverage.out
|
@ -112,7 +112,7 @@ function draw(subselection) {
|
||||
xAxes: [{
|
||||
scaleLabel: {
|
||||
display: true,
|
||||
labelString: 'Minutes'
|
||||
labelString: 'Seconds'
|
||||
}
|
||||
}]
|
||||
},
|
||||
|
105251
static/assets/vendor/tailwind.css
vendored
Normal file
105251
static/assets/vendor/tailwind.css
vendored
Normal file
File diff suppressed because it is too large
Load Diff
1267
static/assets/vendor/tailwind.dist.css
vendored
Normal file
1267
static/assets/vendor/tailwind.dist.css
vendored
Normal file
File diff suppressed because it is too large
Load Diff
1
static/assets/vendor/tailwind.min.css
vendored
1
static/assets/vendor/tailwind.min.css
vendored
File diff suppressed because one or more lines are too long
7
tailwind.config.js
Normal file
7
tailwind.config.js
Normal file
@ -0,0 +1,7 @@
|
||||
module.exports = {
|
||||
purge: {
|
||||
enabled: true,
|
||||
mode: 'all',
|
||||
content: ['./views/*.tpl.html']
|
||||
}
|
||||
}
|
@ -71,7 +71,7 @@ func ResolveInterval(interval *models.IntervalKey) (err error, from, to time.Tim
|
||||
}
|
||||
|
||||
func ParseSummaryParams(r *http.Request) (*models.SummaryParams, error) {
|
||||
user := r.Context().Value(models.UserKey).(*models.User)
|
||||
user := extractUser(r)
|
||||
params := r.URL.Query()
|
||||
|
||||
var err error
|
||||
@ -108,3 +108,13 @@ func ParseSummaryParams(r *http.Request) (*models.SummaryParams, error) {
|
||||
Recompute: recompute,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func extractUser(r *http.Request) *models.User {
|
||||
type principalGetter interface {
|
||||
GetPrincipal() *models.User
|
||||
}
|
||||
if p := r.Context().Value("principal"); p != nil {
|
||||
return p.(principalGetter).GetPrincipal()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
@ -1 +1 @@
|
||||
1.24.4
|
||||
1.25.4
|
||||
|
@ -1,2 +1,2 @@
|
||||
<script src="assets/vendor/seedrandom.min.js" integrity="sha384-bFS5CG904xYIgxBcrDF4KFNXuM7KeSGsSvS/QTaDqMTEdbaaxjg2Y2TSU3Ygs7wG" crossorigin="anonymous"></script>
|
||||
<script src="assets/vendor/Chart.bundle.min.js" integrity="sha384-mZ3q69BYmd4GxHp59G3RrsaFdWDxVSoqd7oVYuWRm2qiXrduT63lQtlhdD9lKbm3" crossorigin="anonymous"></script>
|
||||
<script src="assets/vendor/seedrandom.min.js"></script>
|
||||
<script src="assets/vendor/Chart.bundle.min.js"></script>
|
@ -7,6 +7,10 @@
|
||||
<link rel="icon" type="image/png" sizes="16x16" href="assets/images/favicon-16x16.png">
|
||||
<link rel="manifest" href="assets/site.webmanifest">
|
||||
<link href="assets/vendor/roboto.css" rel="stylesheet">
|
||||
<link href="assets/vendor/tailwind.min.css" rel="stylesheet">
|
||||
{{ if isDev }}
|
||||
<link href="assets/vendor/tailwind.css" rel="stylesheet">
|
||||
{{ else }}
|
||||
<link href="assets/vendor/tailwind.dist.css" rel="stylesheet">
|
||||
{{ end }}
|
||||
<link href="assets/app.css" rel="stylesheet">
|
||||
</head>
|
@ -35,6 +35,32 @@
|
||||
<div class="flex flex-col flex-grow max-w-2xl mt-8">
|
||||
|
||||
<details class="my-8 pb-8 border-b border-gray-700">
|
||||
<summary class="cursor-pointer">
|
||||
<h2 class="font-semibold text-lg text-white m-0 border-b-2 border-green-700 inline-block"
|
||||
id="email-heading">
|
||||
Change E-Mail Address
|
||||
</h2>
|
||||
</summary>
|
||||
<div class="w-full">
|
||||
<form class="mt-10" action="" method="post">
|
||||
<input type="hidden" name="action" value="update_user">
|
||||
<div class="mb-8 flex justify-between items-center space-x-4">
|
||||
<label class="inline-block text-sm text-gray-500" for="password_old">E-Mail Address</label>
|
||||
<input class="shadow appearance-none bg-gray-800 focus:bg-gray-700 text-gray-300 border-green-700 focus:border-gray-500 border rounded flex-grow py-1 px-3"
|
||||
type="email" id="email"
|
||||
name="email" placeholder="Enter your e-mail address"
|
||||
value="{{ .User.Email }}">
|
||||
<button type="submit"
|
||||
class="py-1 px-3 rounded bg-green-700 hover:bg-green-800 text-white text-sm">
|
||||
Save
|
||||
</button>
|
||||
</div>
|
||||
<div class="text-gray-300 text-sm">E-Mail address is optional, but required for some features that you cannot use else. Also, if you do not add an e-mail address, you will not be able to reset your password in case you forget it.</div>
|
||||
</form>
|
||||
</div>
|
||||
</details>
|
||||
|
||||
<details class="mb-8 pb-8 border-b border-gray-700">
|
||||
<summary class="cursor-pointer">
|
||||
<h2 class="font-semibold text-lg text-white m-0 border-b-2 border-green-700 inline-block" id="password">
|
||||
Change Password
|
||||
|
@ -3,7 +3,7 @@
|
||||
|
||||
{{ template "head.tpl.html" . }}
|
||||
|
||||
<body class="bg-gray-800 text-gray-700 p-4 pt-10 flex flex-col min-h-screen max-w-screen-xl mx-auto justify-center">
|
||||
<body class="bg-gray-850 text-gray-700 p-4 pt-10 flex flex-col min-h-screen max-w-screen-xl mx-auto justify-center">
|
||||
<div class="w-full flex justify-center">
|
||||
<div class="flex items-center justify-between max-w-4xl flex-grow">
|
||||
<div><a href="" class="text-gray-500 text-sm">← Go back</a></div>
|
||||
@ -37,6 +37,13 @@
|
||||
type="text" id="username"
|
||||
name="username" placeholder="Choose a username" minlength="1" required autofocus>
|
||||
</div>
|
||||
<div class="mb-8">
|
||||
<label class="inline-block text-sm mb-1 text-gray-500" for="email">E-Mail</label>
|
||||
<input class="shadow appearance-none bg-gray-800 focus:bg-gray-700 text-gray-300 border-green-700 focus:border-gray-500 border rounded w-full py-1 px-3"
|
||||
type="email" id="email"
|
||||
name="email" placeholder="Optionally add your e-mail address">
|
||||
<div class="text-xs text-gray-500 mt-2 italic">E-Mail address is optional, but required for some features that you cannot use else. Also, if you do not add an e-mail address, you will not be able to reset your password in case you forget it.</div>
|
||||
</div>
|
||||
<div class="mb-8">
|
||||
<label class="inline-block text-sm mb-1 text-gray-500" for="password">Password</label>
|
||||
<input class="shadow appearance-none bg-gray-800 focus:bg-gray-700 text-gray-300 border-green-700 focus:border-gray-500 border rounded w-full py-1 px-3"
|
||||
|
@ -45,12 +45,12 @@
|
||||
<form class="text-white flex flex-nowrap items-center justify-center self-center max-w-xl flex-wrap space-x-8">
|
||||
<div class="flex space-x-1">
|
||||
<label for="from-date-picker" class="text-gray-300 pl-1">▶️ Start:</label>
|
||||
<input id="from-date-picker" type="date" name="from" class="text-sm text-gray-300 bg-gray-800 rounded-md text-center cursor-pointer"
|
||||
<input id="from-date-picker" type="date" name="from" max="{{ .ToTime.T | simpledate }}" class="text-sm text-gray-300 bg-gray-800 rounded-md text-center cursor-pointer"
|
||||
value="{{ .FromTime.T | simpledate }}" required>
|
||||
</div>
|
||||
<div class="flex space-x-1">
|
||||
<label for="to-date-picker" class="text-gray-300 pl-1">⏹️ End:</label>
|
||||
<input id="to-date-picker" type="date" name="to" class="text-sm text-gray-300 bg-gray-800 rounded-md text-center cursor-pointer"
|
||||
<input id="to-date-picker" type="date" name="to" min="{{ .FromTime.T | simpledate }}" class="text-sm text-gray-300 bg-gray-800 rounded-md text-center cursor-pointer"
|
||||
value="{{ .ToTime.T | simpledate }}" required>
|
||||
</div>
|
||||
<div>
|
||||
@ -88,7 +88,7 @@
|
||||
</span>
|
||||
|
||||
<div class="flex flex-wrap justify-center">
|
||||
<div class="w-full lg:w-1/2 p-1">
|
||||
<div class="w-full lg:w-1/2 p-1" style="max-width: 100vw;">
|
||||
<div class="p-4 pb-10 bg-gray-900 border border-gray-700 text-gray-300 rounded-md shadow m-2 flex flex-col" id="project-container" style="height: 300px">
|
||||
<div class="flex justify-between">
|
||||
<div class="w-1/4 flex-1"></div>
|
||||
@ -104,7 +104,7 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="w-full lg:w-1/2 p-1">
|
||||
<div class="w-full lg:w-1/2 p-1" style="max-width: 100vw;">
|
||||
<div class="p-4 pb-10 bg-gray-900 border border-gray-700 text-gray-300 rounded-md shadow m-2 flex flex-col" id="os-container" style="height: 300px">
|
||||
<div class="flex justify-between">
|
||||
<div class="w-1/4 flex-1"></div>
|
||||
@ -120,7 +120,7 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="w-full lg:w-1/2 p-1">
|
||||
<div class="w-full lg:w-1/2 p-1" style="max-width: 100vw;">
|
||||
<div class="p-4 pb-10 bg-gray-900 border border-gray-700 text-gray-300 rounded-md shadow m-2 flex flex-col relative" id="language-container" style="height: 300px">
|
||||
<div class="flex justify-between">
|
||||
<div class="w-1/4 flex-1"></div>
|
||||
@ -136,7 +136,7 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="w-full lg:w-1/2 p-1">
|
||||
<div class="w-full lg:w-1/2 p-1" style="max-width: 100vw;">
|
||||
<div class="p-4 pb-10 bg-gray-900 border border-gray-700 text-gray-300 rounded-md shadow m-2 flex flex-col" id="editor-container" style="height: 300px">
|
||||
<div class="flex justify-between">
|
||||
<div class="w-1/4 flex-1"></div>
|
||||
@ -152,7 +152,7 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="w-full lg:w-1/2 p-1">
|
||||
<div class="w-full lg:w-1/2 p-1" style="max-width: 100vw;">
|
||||
<div class="p-4 pb-10 bg-gray-900 border border-gray-700 text-gray-300 rounded-md shadow m-2 flex flex-col" id="machine-container" style="height: 300px">
|
||||
<div class="flex justify-between">
|
||||
<div class="w-1/4 flex-1"></div>
|
||||
@ -224,6 +224,17 @@
|
||||
wakapiData.editors = {{ .Editors | json }}
|
||||
wakapiData.languages = {{ .Languages | json }}
|
||||
wakapiData.machines = {{ .Machines | json }}
|
||||
|
||||
document.getElementById("to-date-picker").onchange = function () {
|
||||
var input = document.getElementById("from-date-picker");
|
||||
input.setAttribute("max", this.value);
|
||||
}
|
||||
|
||||
document.getElementById("from-date-picker").onchange = function () {
|
||||
var input = document.getElementById("to-date-picker");
|
||||
input.setAttribute("min", this.value);
|
||||
}
|
||||
|
||||
</script>
|
||||
<script src="assets/app.js"></script>
|
||||
|
||||
|
Reference in New Issue
Block a user