cleanup: refactor api architecture & add user roles
This commit is contained in:
parent
a3958595cd
commit
eaffaa70df
@ -1,3 +1,7 @@
|
||||
generate:
|
||||
rm graph/schema.graphqls
|
||||
for f in graph/schema/*.gql; do cat $f; echo; done > graph/schema.graphqls
|
||||
|
||||
start:
|
||||
docker container start test-db
|
||||
go run cmd/citadel/main.go
|
||||
|
@ -3,20 +3,50 @@ package main
|
||||
import (
|
||||
"fmt"
|
||||
_ "github.com/lib/pq"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/BurntSushi/toml"
|
||||
"github.com/jmoiron/sqlx"
|
||||
"github.com/jordanknott/project-citadel/api/router"
|
||||
"github.com/jordanknott/project-citadel/api/internal/route"
|
||||
log "github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
type Database struct {
|
||||
Host string
|
||||
Name string
|
||||
User string
|
||||
Password string
|
||||
}
|
||||
type AppConfig struct {
|
||||
Database Database
|
||||
}
|
||||
|
||||
func main() {
|
||||
dat, err := ioutil.ReadFile("conf/app.toml")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
var appConfig AppConfig
|
||||
_, err = toml.Decode(string(dat), &appConfig)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
Formatter := new(log.TextFormatter)
|
||||
Formatter.TimestampFormat = "02-01-2006 15:04:05"
|
||||
Formatter.FullTimestamp = true
|
||||
log.SetFormatter(Formatter)
|
||||
db, err := sqlx.Connect("postgres", "user=postgres password=test host=0.0.0.0 dbname=citadel sslmode=disable")
|
||||
log.SetLevel(log.InfoLevel)
|
||||
connection := fmt.Sprintf("user=%s password=%s host=%s dbname=%s sslmode=disable",
|
||||
appConfig.Database.User,
|
||||
appConfig.Database.Password,
|
||||
appConfig.Database.Host,
|
||||
appConfig.Database.Name,
|
||||
)
|
||||
db, err := sqlx.Connect("postgres", connection)
|
||||
if err != nil {
|
||||
log.Panic(err)
|
||||
}
|
||||
@ -27,6 +57,6 @@ func main() {
|
||||
defer db.Close()
|
||||
fmt.Println("starting graphql server on http://localhost:3333")
|
||||
fmt.Println("starting graphql playground on http://localhost:3333/__graphql")
|
||||
r, _ := router.NewRouter(db)
|
||||
r, _ := route.NewRouter(db)
|
||||
http.ListenAndServe(":3333", r)
|
||||
}
|
||||
|
@ -1,20 +1,43 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
// "context"
|
||||
// "fmt"
|
||||
// "io/ioutil"
|
||||
|
||||
"bytes"
|
||||
"context"
|
||||
"fmt"
|
||||
"github.com/BurntSushi/toml"
|
||||
"github.com/jmoiron/sqlx"
|
||||
"github.com/jordan-wright/email"
|
||||
"github.com/jordanknott/project-citadel/api/pg"
|
||||
"github.com/jordanknott/project-citadel/api/router"
|
||||
_ "github.com/lib/pq"
|
||||
"golang.org/x/crypto/bcrypt"
|
||||
"io/ioutil"
|
||||
"net/smtp"
|
||||
// "github.com/jmoiron/sqlx"
|
||||
// "github.com/jordanknott/project-citadel/api/pg"
|
||||
// "github.com/BurntSushi/toml"
|
||||
// "github.com/jordanknott/project-citadel/api/router"
|
||||
// "time"
|
||||
"text/template"
|
||||
"time"
|
||||
|
||||
"github.com/golang-migrate/migrate/v4"
|
||||
"github.com/golang-migrate/migrate/v4/database/postgres"
|
||||
_ "github.com/golang-migrate/migrate/v4/source/file"
|
||||
)
|
||||
|
||||
type Database struct {
|
||||
Host string
|
||||
Name string
|
||||
User string
|
||||
Password string
|
||||
}
|
||||
type AppConfig struct {
|
||||
Database Database
|
||||
}
|
||||
|
||||
type UserRegistration struct {
|
||||
Username string
|
||||
Year string
|
||||
AppName string
|
||||
AppURL string
|
||||
}
|
||||
|
||||
type color struct {
|
||||
Name string
|
||||
Color string
|
||||
@ -25,39 +48,136 @@ type colors struct {
|
||||
Color []color
|
||||
}
|
||||
|
||||
func main() {
|
||||
func SendEmail() {
|
||||
emailTmpl, err := ioutil.ReadFile("templates/mail/user/registered.tmpl")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
user := UserRegistration{Username: "jordanthedev", AppName: "Citadel", AppURL: "http://localhost:3000/", Year: "2020"}
|
||||
tmpl, err := template.New("registered").Parse(string(emailTmpl))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
var tpl bytes.Buffer
|
||||
if err := tmpl.Execute(&tpl, &user); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
result := tpl.String()
|
||||
|
||||
e := email.NewEmail()
|
||||
e.From = "Jordan Knott <no-reply@citadel.com>"
|
||||
e.To = []string{"jordan@jordanthedev.com"}
|
||||
e.Subject = "Jordan Knott (@jordanthedev) invited you to join the team \"Paradox\" on Citadel"
|
||||
e.Text = []byte("Text Body is, of course, supported!")
|
||||
e.HTML = []byte("<h1>Fancy HTML is supported, too!</h1>")
|
||||
e.HTML = []byte(result)
|
||||
e.Send("localhost:1025", smtp.PlainAuth("", "test@gmail.com", "password123", "localhost"))
|
||||
// dur := time.Hour * 24 * 7 * 30
|
||||
// token, err := router.NewAccessTokenCustomExpiration("21345076-6423-4a00-a6bd-cd9f830e2764", dur)
|
||||
// if err != nil {
|
||||
// panic(err)
|
||||
// }
|
||||
// fmt.Println(token)
|
||||
|
||||
// fmt.Println("seeding database...")
|
||||
|
||||
// dat, err := ioutil.ReadFile("data/colors.toml")
|
||||
// if err != nil {
|
||||
// panic(err)
|
||||
// }
|
||||
|
||||
// var labelColors colors
|
||||
// _, err = toml.Decode(string(dat), &labelColors)
|
||||
// if err != nil {
|
||||
// panic(err)
|
||||
// }
|
||||
// db, err := sqlx.Connect("postgres", "user=postgres password=test host=0.0.0.0 dbname=citadel sslmode=disable")
|
||||
// repository := pg.NewRepository(db)
|
||||
// for _, color := range labelColors.Color {
|
||||
// fmt.Printf("%v\n", color)
|
||||
// repository.CreateLabelColor(context.Background(), pg.CreateLabelColorParams{color.Name, color.Color, float64(color.Position)})
|
||||
// }
|
||||
|
||||
}
|
||||
|
||||
func Seed() {
|
||||
dur := time.Hour * 24 * 7 * 30
|
||||
token, err := router.NewAccessTokenCustomExpiration("21345076-6423-4a00-a6bd-cd9f830e2764", dur)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
fmt.Println(token)
|
||||
|
||||
fmt.Println("seeding database...")
|
||||
|
||||
dat, err := ioutil.ReadFile("data/dark_colors.toml")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
var labelColors colors
|
||||
_, err = toml.Decode(string(dat), &labelColors)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
db, err := sqlx.Connect("postgres", "user=postgres password=test host=0.0.0.0 dbname=citadel sslmode=disable")
|
||||
repository := pg.NewRepository(db)
|
||||
for _, color := range labelColors.Color {
|
||||
fmt.Printf("%v\n", color)
|
||||
repository.CreateLabelColor(context.Background(), pg.CreateLabelColorParams{color.Name, color.Color, float64(color.Position)})
|
||||
}
|
||||
}
|
||||
func Migrate() {
|
||||
dat, err := ioutil.ReadFile("conf/app.toml")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
var appConfig AppConfig
|
||||
_, err = toml.Decode(string(dat), &appConfig)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
connection := fmt.Sprintf("user=%s password=%s host=%s dbname=%s sslmode=disable",
|
||||
appConfig.Database.User,
|
||||
appConfig.Database.Password,
|
||||
appConfig.Database.Host,
|
||||
appConfig.Database.Name,
|
||||
)
|
||||
fmt.Println(connection)
|
||||
db, err := sqlx.Connect("postgres", connection)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
defer db.Close()
|
||||
driver, err := postgres.WithInstance(db.DB, &postgres.Config{})
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
m, err := migrate.NewWithDatabaseInstance(
|
||||
"file://migrations",
|
||||
"postgres", driver)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
err = m.Up()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
func main() {
|
||||
dat, err := ioutil.ReadFile("conf/app.toml")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
var appConfig AppConfig
|
||||
_, err = toml.Decode(string(dat), &appConfig)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
connection := fmt.Sprintf("user=%s password=%s host=%s dbname=%s sslmode=disable",
|
||||
appConfig.Database.User,
|
||||
appConfig.Database.Password,
|
||||
appConfig.Database.Host,
|
||||
appConfig.Database.Name,
|
||||
)
|
||||
fmt.Println(connection)
|
||||
db, err := sqlx.Connect("postgres", connection)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
|
||||
}
|
||||
createdAt := time.Now().UTC()
|
||||
hashedPwd, err := bcrypt.GenerateFromPassword([]byte("test"), 14)
|
||||
repo := pg.NewRepository(db)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
_, err = repo.CreateUserAccount(context.Background(), pg.CreateUserAccountParams{
|
||||
Username: "jordan",
|
||||
Initials: "JK",
|
||||
Email: "jordan@jordanthedev.com",
|
||||
PasswordHash: string(hashedPwd),
|
||||
CreatedAt: createdAt,
|
||||
RoleCode: "admin",
|
||||
})
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
56
api/cmd/send/main.go
Normal file
56
api/cmd/send/main.go
Normal file
@ -0,0 +1,56 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/RichardKnop/machinery/v1"
|
||||
"github.com/RichardKnop/machinery/v1/config"
|
||||
"github.com/RichardKnop/machinery/v1/tasks"
|
||||
)
|
||||
|
||||
func Add(args ...int64) (int64, error) {
|
||||
sum := int64(0)
|
||||
for _, arg := range args {
|
||||
sum += arg
|
||||
}
|
||||
return sum, nil
|
||||
}
|
||||
|
||||
func main() {
|
||||
var cnf = &config.Config{
|
||||
Broker: "amqp://guest:guest@localhost:5672/",
|
||||
DefaultQueue: "machinery_tasks",
|
||||
ResultBackend: "memcache://localhost:11211",
|
||||
AMQP: &config.AMQPConfig{
|
||||
Exchange: "machinery_exchange",
|
||||
ExchangeType: "direct",
|
||||
BindingKey: "machinery_task",
|
||||
},
|
||||
}
|
||||
|
||||
fmt.Println("starting server")
|
||||
server, err := machinery.NewServer(cnf)
|
||||
if err != nil {
|
||||
// do something with the error
|
||||
}
|
||||
|
||||
addTask0 := tasks.Signature{
|
||||
Name: "userRegistration",
|
||||
Args: []tasks.Arg{
|
||||
{
|
||||
Type: "string",
|
||||
Value: "21345076-6423-4a00-a6bd-cd9f830e2764",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
asyncResult, err := server.SendTask(&addTask0)
|
||||
if err != nil {
|
||||
fmt.Errorf("Could not send task: %s", err.Error())
|
||||
}
|
||||
fmt.Println(asyncResult.GetState())
|
||||
|
||||
// results, err := asyncResult.Get(time.Duration(time.Millisecond * 5))
|
||||
// fmt.Printf("split([\"foo\"]) = %v\n", tasks.HumanReadableResults(results))
|
||||
|
||||
}
|
66
api/cmd/worker/main.go
Normal file
66
api/cmd/worker/main.go
Normal file
@ -0,0 +1,66 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/RichardKnop/machinery/v1"
|
||||
"github.com/RichardKnop/machinery/v1/config"
|
||||
"github.com/google/uuid"
|
||||
"github.com/jmoiron/sqlx"
|
||||
"github.com/jordanknott/project-citadel/api/pg"
|
||||
_ "github.com/lib/pq"
|
||||
)
|
||||
|
||||
type MachineTasks struct {
|
||||
Repository pg.Repository
|
||||
}
|
||||
|
||||
func (m *MachineTasks) UserRegistration(userID string) (bool, error) {
|
||||
ctx := context.Background()
|
||||
uid, err := uuid.Parse(userID)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
user, err := m.Repository.GetUserAccountByID(ctx, uid)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
if user.Username == "jordan" {
|
||||
return true, nil
|
||||
}
|
||||
return false, nil
|
||||
}
|
||||
|
||||
func main() {
|
||||
var cnf = &config.Config{
|
||||
Broker: "amqp://guest:guest@localhost:5672/",
|
||||
DefaultQueue: "machinery_tasks",
|
||||
ResultBackend: "memcache://localhost:11211",
|
||||
AMQP: &config.AMQPConfig{
|
||||
Exchange: "machinery_exchange",
|
||||
ExchangeType: "direct",
|
||||
BindingKey: "machinery_task",
|
||||
},
|
||||
}
|
||||
|
||||
fmt.Println("starting server")
|
||||
server, err := machinery.NewServer(cnf)
|
||||
if err != nil {
|
||||
// do something with the error
|
||||
}
|
||||
|
||||
db, err := sqlx.Connect("postgres", "user=postgres password=test host=0.0.0.0 dbname=citadel sslmode=disable")
|
||||
repo := pg.NewRepository(db)
|
||||
tasks := MachineTasks{repo}
|
||||
server.RegisterTasks(map[string]interface{}{
|
||||
"userRegistration": tasks.UserRegistration,
|
||||
})
|
||||
|
||||
worker := server.NewWorker("citadel_worker", 10)
|
||||
fmt.Println("launching worker")
|
||||
err = worker.Launch()
|
||||
if err != nil {
|
||||
// do something with the error
|
||||
}
|
||||
}
|
5
api/conf/app.toml
Normal file
5
api/conf/app.toml
Normal file
@ -0,0 +1,5 @@
|
||||
[database]
|
||||
host = '0.0.0.0'
|
||||
name = 'citadel'
|
||||
user = 'postgres'
|
||||
password = 'test'
|
74
api/data/dark_colors.toml
Normal file
74
api/data/dark_colors.toml
Normal file
@ -0,0 +1,74 @@
|
||||
[[color]]
|
||||
name = "red"
|
||||
color = '#e8384f'
|
||||
position = 1
|
||||
|
||||
[[color]]
|
||||
name = "orange"
|
||||
color = '#fd612c'
|
||||
position = 2
|
||||
|
||||
[[color]]
|
||||
name = "yellow_orange"
|
||||
color = '#fd9a00'
|
||||
position = 3
|
||||
|
||||
[[color]]
|
||||
name = "yellow"
|
||||
color = '#eec300'
|
||||
position = 4
|
||||
|
||||
[[color]]
|
||||
name = "yellow_green"
|
||||
color = '#a4cf30'
|
||||
position = 5
|
||||
|
||||
[[color]]
|
||||
name = "green"
|
||||
color = '#62d26f'
|
||||
position = 6
|
||||
|
||||
[[color]]
|
||||
name = "blue_green"
|
||||
color = '#37c5ab'
|
||||
position = 7
|
||||
|
||||
[[color]]
|
||||
name = "aqua"
|
||||
color = '#20aaea'
|
||||
position = 8
|
||||
|
||||
[[color]]
|
||||
name = "blue"
|
||||
color = '#4186e0'
|
||||
position = 9
|
||||
|
||||
[[color]]
|
||||
name = "indigo"
|
||||
color = '#7a6ff0'
|
||||
position = 10
|
||||
|
||||
[[color]]
|
||||
name = "purple"
|
||||
color = '#aa62e3'
|
||||
position = 11
|
||||
|
||||
[[color]]
|
||||
name = "magenta"
|
||||
color = '#e362e3'
|
||||
position = 12
|
||||
|
||||
[[color]]
|
||||
name = "hot_pink"
|
||||
color = '#ea4e9d'
|
||||
position = 13
|
||||
|
||||
[[color]]
|
||||
name = "pink"
|
||||
color = '#fc91ad'
|
||||
position = 14
|
||||
|
||||
[[color]]
|
||||
name = "cool_gray"
|
||||
color = '#8da3a6'
|
||||
position = 15
|
16
api/data/dark_colors.yml
Normal file
16
api/data/dark_colors.yml
Normal file
@ -0,0 +1,16 @@
|
||||
colors:
|
||||
red: '#e8384f'
|
||||
orange: '#fd612c'
|
||||
yellow_orange: '#fd9a00'
|
||||
yellow: '#eec300'
|
||||
yellow_green: '#a4cf30'
|
||||
green: '#62d26f'
|
||||
blue_green: '#37c5ab'
|
||||
aqua: '#20aaea'
|
||||
blue: '#4186e0'
|
||||
indigo: '#7a6ff0'
|
||||
purple: '#aa62e3'
|
||||
magenta: '#e362e3'
|
||||
hot_pink: '#ea4e9d'
|
||||
pink: '#fc91ad'
|
||||
cool_gray: '#8da3a6'
|
@ -6,3 +6,14 @@ services:
|
||||
ports:
|
||||
- 1025:1025
|
||||
- 8025:8025
|
||||
broker:
|
||||
image: rabbitmq:3-management
|
||||
restart: always
|
||||
ports:
|
||||
- 8060:15672
|
||||
- 5672:5672
|
||||
result_store:
|
||||
image: memcached:1.6-alpine
|
||||
restart: always
|
||||
ports:
|
||||
- 11211:11211
|
||||
|
11
api/go.mod
11
api/go.mod
@ -5,25 +5,28 @@ go 1.13
|
||||
require (
|
||||
github.com/99designs/gqlgen v0.11.3
|
||||
github.com/BurntSushi/toml v0.3.1
|
||||
github.com/RichardKnop/machinery v1.8.6
|
||||
github.com/boyter/scc v2.12.0+incompatible // indirect
|
||||
github.com/dbaggerman/cuba v0.3.2 // indirect
|
||||
github.com/dgrijalva/jwt-go v3.2.0+incompatible
|
||||
github.com/go-chi/chi v3.3.2+incompatible
|
||||
github.com/go-chi/cors v1.0.0
|
||||
github.com/golang-migrate/migrate/v4 v4.11.0
|
||||
github.com/google/martian v2.1.0+incompatible
|
||||
github.com/google/uuid v1.1.1
|
||||
github.com/jmoiron/sqlx v1.2.0
|
||||
github.com/jordan-wright/email v0.0.0-20200602115436-fd8a7622303e
|
||||
github.com/lib/pq v1.0.0
|
||||
github.com/lib/pq v1.3.0
|
||||
github.com/magefile/mage v1.9.0
|
||||
github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1 // indirect
|
||||
github.com/monochromegane/go-gitignore v0.0.0-20200525100937-58356a36e03f // indirect
|
||||
github.com/pelletier/go-toml v1.8.0
|
||||
github.com/pkg/errors v0.8.1
|
||||
github.com/pkg/errors v0.9.1
|
||||
github.com/sirupsen/logrus v1.4.2
|
||||
github.com/spf13/cobra v1.0.0 // indirect
|
||||
github.com/spf13/pflag v1.0.5 // indirect
|
||||
github.com/urfave/cli v1.20.0 // indirect
|
||||
github.com/streadway/amqp v1.0.0
|
||||
github.com/vektah/gqlparser/v2 v2.0.1
|
||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550
|
||||
golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073
|
||||
golang.org/x/text v0.3.3 // indirect
|
||||
)
|
||||
|
476
api/go.sum
476
api/go.sum
@ -1,70 +1,217 @@
|
||||
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=
|
||||
cloud.google.com/go v0.37.4/go.mod h1:NHPJ89PdicEuT9hdPXMROBD91xc5uRDxsMtSB16k7hw=
|
||||
cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU=
|
||||
cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU=
|
||||
cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY=
|
||||
cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc=
|
||||
cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0=
|
||||
cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To=
|
||||
cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4=
|
||||
cloud.google.com/go v0.53.0 h1:MZQCQQaRwOrAcuKjiHWHrgKykt4fZyuwF2dtiG3fGW8=
|
||||
cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M=
|
||||
cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o=
|
||||
cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE=
|
||||
cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc=
|
||||
cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE=
|
||||
cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I=
|
||||
cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw=
|
||||
cloud.google.com/go/pubsub v1.2.0 h1:Lpy6hKgdcl7a3WGSfJIFmxmcdjSpP6OmBEfcOv1Y680=
|
||||
cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA=
|
||||
cloud.google.com/go/spanner v1.2.0/go.mod h1:LfwGAsK42Yz8IeLsd/oagGFBqTXt3xVWtm8/KD2vrEI=
|
||||
cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw=
|
||||
cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos=
|
||||
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
|
||||
github.com/99designs/gqlgen v0.11.1 h1:QoSL8/AAJ2T3UOeQbdnBR32JcG4pO08+P/g5jdbFkUg=
|
||||
github.com/99designs/gqlgen v0.11.1/go.mod h1:vjFOyBZ7NwDl+GdSD4PFn7BQn5Fy7ohJwXn7Vk8zz+c=
|
||||
github.com/99designs/gqlgen v0.11.3 h1:oFSxl1DFS9X///uHV3y6CEfpcXWrDUxVblR4Xib2bs4=
|
||||
github.com/99designs/gqlgen v0.11.3/go.mod h1:RgX5GRRdDWNkh4pBrdzNpNPFVsdoUFY2+adM6nb1N+4=
|
||||
github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8=
|
||||
github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
|
||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
|
||||
github.com/ClickHouse/clickhouse-go v1.3.12/go.mod h1:EaI/sW7Azgz9UATzd5ZdZHRUhHgv5+JMS9NSr2smCJI=
|
||||
github.com/Microsoft/go-winio v0.4.11/go.mod h1:VhR8bwka0BXejwEJY73c50VrPtXAaKcyvVC4A4RozmA=
|
||||
github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA=
|
||||
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
|
||||
github.com/RichardKnop/logging v0.0.0-20190827224416-1a693bdd4fae h1:DcFpTQBYQ9Ct2d6sC7ol0/ynxc2pO1cpGUM+f4t5adg=
|
||||
github.com/RichardKnop/logging v0.0.0-20190827224416-1a693bdd4fae/go.mod h1:rJJ84PyA/Wlmw1hO+xTzV2wsSUon6J5ktg0g8BF2PuU=
|
||||
github.com/RichardKnop/machinery v1.8.6 h1:IPdPeO/yVE32isMJME2hiCgJgNibCVLjhshyjrQIDFY=
|
||||
github.com/RichardKnop/machinery v1.8.6/go.mod h1:W87mnh7t91WdrwGbdnAjvDzqD/bqBV+0+GF276gv/bU=
|
||||
github.com/RichardKnop/redsync v1.2.0 h1:gK35hR3zZkQigHKm8wOGb9MpJ9BsrW6MzxezwjTcHP0=
|
||||
github.com/RichardKnop/redsync v1.2.0/go.mod h1:9b8nBGAX3bE2uCfJGSnsDvF23mKyHTZzmvmj5FH3Tp0=
|
||||
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/agnivade/levenshtein v1.0.1/go.mod h1:CURSv5d9Uaml+FovSIICkLbAUZ9S4RqaHDIsdSBg7lM=
|
||||
github.com/agnivade/levenshtein v1.0.3 h1:M5ZnqLOoZR8ygVq0FfkXsNOKzMCk0xRiow0R5+5VkQ0=
|
||||
github.com/agnivade/levenshtein v1.0.3/go.mod h1:4SFRZbbXWLF4MU1T9Qg0pGgH3Pjs+t6ie5efyrwRJXs=
|
||||
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
||||
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
||||
github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8=
|
||||
github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ=
|
||||
github.com/arbovm/levenshtein v0.0.0-20160628152529-48b4e1c0c4d0/go.mod h1:t2tdKJDJF9BV14lnkjHmOQgcvEKgtqs5a1N3LNdJhGE=
|
||||
github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
|
||||
github.com/aws/aws-sdk-go v1.17.7/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo=
|
||||
github.com/aws/aws-sdk-go v1.29.15 h1:0ms/213murpsujhsnxnNKNeVouW60aJqSd992Ks3mxs=
|
||||
github.com/aws/aws-sdk-go v1.29.15/go.mod h1:1KvfttTE3SPKMpo8g2c6jL3ZKfXtFvKscTgahTma5Xg=
|
||||
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/bitly/go-hostpool v0.0.0-20171023180738-a3a6125de932/go.mod h1:NOuUCSz6Q9T7+igc/hlvDOUdtWKryOrtFyIVABv/p7k=
|
||||
github.com/bkaradzic/go-lz4 v1.0.0/go.mod h1:0YdlkowM3VswSROI7qDxhRvJ3sLhlFrRRwjwegp5jy4=
|
||||
github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869/go.mod h1:Ekp36dRnpXw/yCqJaO+ZrUyxD+3VXMFFr56k5XYrpB4=
|
||||
github.com/boyter/scc v2.12.0+incompatible h1:Sxhi1Ry3gdreoaF0xEITQSdjR+pJT0cXHXhlDw5FHT0=
|
||||
github.com/boyter/scc v2.12.0+incompatible/go.mod h1:VB5w4e0dahmIiKnpZ7LRh/sjauoY0BmCWjIzZcShNY0=
|
||||
github.com/bradfitz/gomemcache v0.0.0-20190913173617-a41fca850d0b h1:L/QXpzIa3pOvUGt1D1lA5KjYhPBAN/3iWdP7xeFS9F0=
|
||||
github.com/bradfitz/gomemcache v0.0.0-20190913173617-a41fca850d0b/go.mod h1:H0wQNHz2YrLsuXOZozoeDmnHXkNCRmMW0gwFWDfEZDA=
|
||||
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
||||
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
|
||||
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
|
||||
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
|
||||
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
|
||||
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
||||
github.com/cloudflare/golz4 v0.0.0-20150217214814-ef862a3cdc58/go.mod h1:EOBUe0h4xcZ5GoxqC5SDxFQ8gwyZPKQoEzownBlhI80=
|
||||
github.com/cockroachdb/apd v1.1.0/go.mod h1:8Sl8LxpKi29FqWXR16WEFZRNSz3SoPzUzeMeY4+DwBQ=
|
||||
github.com/cockroachdb/cockroach-go v0.0.0-20190925194419-606b3d062051/go.mod h1:XGLbWH/ujMcbPbhZq52Nv6UrCghb1yGn//133kEsvDk=
|
||||
github.com/containerd/containerd v1.3.3/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA=
|
||||
github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk=
|
||||
github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
|
||||
github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
|
||||
github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
|
||||
github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
|
||||
github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d h1:U+s90UTSYgptZMwQh2aRr3LuazLJIa+Pg3Kc1ylSYVY=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
|
||||
github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY=
|
||||
github.com/cznic/mathutil v0.0.0-20180504122225-ca4c9f2c1369/go.mod h1:e6NPNENfs9mPDVNRekM7lKScauxd5kXTr1Mfyig6TDM=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/dbaggerman/cuba v0.3.2 h1:6ZbQX3FNvkocR222YyoAIZ8wi4avrb7JcJkPvVI2AS4=
|
||||
github.com/dbaggerman/cuba v0.3.2/go.mod h1:t9Oo05XRZGcjaVqsA/gFeNAOm7DYZYNhI17unI5FlwY=
|
||||
github.com/denisenkom/go-mssqldb v0.0.0-20190515213511-eb9f6a1743f3/go.mod h1:zAg7JM8CkOJ43xKXIj7eRO9kmWm/TW578qo+oDO6tuM=
|
||||
github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM=
|
||||
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
|
||||
github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no=
|
||||
github.com/dgryski/trifles v0.0.0-20190318185328-a8d75aae118c/go.mod h1:if7Fbed8SFyPtHLHbg49SI7NAdJiC5WIA09pe59rfAA=
|
||||
github.com/dhui/dktest v0.3.2/go.mod h1:l1/ib23a/CmxAe7yixtrYPc8Iy90Zy2udyaHINM5p58=
|
||||
github.com/docker/distribution v2.7.0+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
|
||||
github.com/docker/distribution v2.7.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
|
||||
github.com/docker/docker v1.4.2-0.20200213202729-31a86c4ab209/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
|
||||
github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec=
|
||||
github.com/docker/go-units v0.3.3/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
|
||||
github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
|
||||
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 v0.0.0-20170320065105-0bce6a688712/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M=
|
||||
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/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||
github.com/fsouza/fake-gcs-server v1.17.0/go.mod h1:D1rTE4YCyHFNa99oyJJ5HyclvN/0uQR+pM/VdlL83bw=
|
||||
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
||||
github.com/go-chi/chi v3.3.2+incompatible h1:uQNcQN3NsV1j4ANsPh42P4ew4t6rnRbJb8frvpp31qQ=
|
||||
github.com/go-chi/chi v3.3.2+incompatible/go.mod h1:eB3wogJHnLi3x/kFX2A+IbTBlXxmMeXJVKy9tTv1XzQ=
|
||||
github.com/go-chi/cors v1.0.0 h1:e6x8k7uWbUwYs+aXDoiUzeQFT6l0cygBYyNhD7/1Tg0=
|
||||
github.com/go-chi/cors v1.0.0/go.mod h1:K2Yje0VW/SJzxiyMYu6iPQYa7hMjQX2i/F491VChg1I=
|
||||
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
|
||||
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
||||
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
||||
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
|
||||
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-redis/redis v6.15.7+incompatible h1:3skhDh95XQMpnqeqNftPkQD9jL9e5e36z/1SUm6dy1U=
|
||||
github.com/go-redis/redis v6.15.7+incompatible/go.mod h1:NAIEuMOZ/fxfXJIrKDQDz8wamY7mA7PouImQ2Jvg6kA=
|
||||
github.com/go-sql-driver/mysql v1.4.0 h1:7LxgVwFb2hIQtMm87NdgAVfXjnt4OePseqT1tKx+opk=
|
||||
github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
|
||||
github.com/go-sql-driver/mysql v1.5.0 h1:ozyZYNQW3x3HtqT1jira07DN2PArx2v7/mN66gGcHOs=
|
||||
github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
|
||||
github.com/go-stack/stack v1.8.0 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk=
|
||||
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
||||
github.com/gobuffalo/attrs v0.0.0-20190224210810-a9411de4debd/go.mod h1:4duuawTqi2wkkpB4ePgWMaai6/Kc6WEz83bhFwpHzj0=
|
||||
github.com/gobuffalo/depgen v0.0.0-20190329151759-d478694a28d3/go.mod h1:3STtPUQYuzV0gBVOY3vy6CfMm/ljR4pABfrTeHNLHUY=
|
||||
github.com/gobuffalo/depgen v0.1.0/go.mod h1:+ifsuy7fhi15RWncXQQKjWS9JPkdah5sZvtHc2RXGlg=
|
||||
github.com/gobuffalo/envy v1.6.15/go.mod h1:n7DRkBerg/aorDM8kbduw5dN3oXGswK5liaSCx4T5NI=
|
||||
github.com/gobuffalo/envy v1.7.0/go.mod h1:n7DRkBerg/aorDM8kbduw5dN3oXGswK5liaSCx4T5NI=
|
||||
github.com/gobuffalo/flect v0.1.0/go.mod h1:d2ehjJqGOH/Kjqcoz+F7jHTBbmDb38yXA598Hb50EGs=
|
||||
github.com/gobuffalo/flect v0.1.1/go.mod h1:8JCgGVbRjJhVgD6399mQr4fx5rRfGKVzFjbj6RE/9UI=
|
||||
github.com/gobuffalo/flect v0.1.3/go.mod h1:8JCgGVbRjJhVgD6399mQr4fx5rRfGKVzFjbj6RE/9UI=
|
||||
github.com/gobuffalo/genny v0.0.0-20190329151137-27723ad26ef9/go.mod h1:rWs4Z12d1Zbf19rlsn0nurr75KqhYp52EAGGxTbBhNk=
|
||||
github.com/gobuffalo/genny v0.0.0-20190403191548-3ca520ef0d9e/go.mod h1:80lIj3kVJWwOrXWWMRzzdhW3DsrdjILVil/SFKBzF28=
|
||||
github.com/gobuffalo/genny v0.1.0/go.mod h1:XidbUqzak3lHdS//TPu2OgiFB+51Ur5f7CSnXZ/JDvo=
|
||||
github.com/gobuffalo/genny v0.1.1/go.mod h1:5TExbEyY48pfunL4QSXxlDOmdsD44RRq4mVZ0Ex28Xk=
|
||||
github.com/gobuffalo/gitgen v0.0.0-20190315122116-cc086187d211/go.mod h1:vEHJk/E9DmhejeLeNt7UVvlSGv3ziL+djtTr3yyzcOw=
|
||||
github.com/gobuffalo/gogen v0.0.0-20190315121717-8f38393713f5/go.mod h1:V9QVDIxsgKNZs6L2IYiGR8datgMhB577vzTDqypH360=
|
||||
github.com/gobuffalo/gogen v0.1.0/go.mod h1:8NTelM5qd8RZ15VjQTFkAW6qOMx5wBbW4dSCS3BY8gg=
|
||||
github.com/gobuffalo/gogen v0.1.1/go.mod h1:y8iBtmHmGc4qa3urIyo1shvOD8JftTtfcKi+71xfDNE=
|
||||
github.com/gobuffalo/here v0.6.0/go.mod h1:wAG085dHOYqUpf+Ap+WOdrPTp5IYcDAs/x7PLa8Y5fM=
|
||||
github.com/gobuffalo/logger v0.0.0-20190315122211-86e12af44bc2/go.mod h1:QdxcLw541hSGtBnhUc4gaNIXRjiDppFGaDqzbrBd3v8=
|
||||
github.com/gobuffalo/mapi v1.0.1/go.mod h1:4VAGh89y6rVOvm5A8fKFxYG+wIW6LO1FMTG9hnKStFc=
|
||||
github.com/gobuffalo/mapi v1.0.2/go.mod h1:4VAGh89y6rVOvm5A8fKFxYG+wIW6LO1FMTG9hnKStFc=
|
||||
github.com/gobuffalo/packd v0.0.0-20190315124812-a385830c7fc0/go.mod h1:M2Juc+hhDXf/PnmBANFCqx4DM3wRbgDvnVWeG2RIxq4=
|
||||
github.com/gobuffalo/packd v0.1.0/go.mod h1:M2Juc+hhDXf/PnmBANFCqx4DM3wRbgDvnVWeG2RIxq4=
|
||||
github.com/gobuffalo/packr/v2 v2.0.9/go.mod h1:emmyGweYTm6Kdper+iywB6YK5YzuKchGtJQZ0Odn4pQ=
|
||||
github.com/gobuffalo/packr/v2 v2.2.0/go.mod h1:CaAwI0GPIAv+5wKLtv8Afwl+Cm78K/I/VCm/3ptBN+0=
|
||||
github.com/gobuffalo/syncx v0.0.0-20190224160051-33c29581e754/go.mod h1:HhnNqWY95UYwwW3uSASeV7vtgYkT2t16hJgV3AEPUpw=
|
||||
github.com/gocql/gocql v0.0.0-20190301043612-f6df8288f9b4/go.mod h1:4Fw1eo5iaEhDUs8XyuhSVCVy52Jq3L+/3GJgYkwc+/0=
|
||||
github.com/gogo/protobuf v1.0.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
||||
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
||||
github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
||||
github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
|
||||
github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o=
|
||||
github.com/golang-migrate/migrate v3.5.4+incompatible h1:R7OzwvCJTCgwapPCiX6DyBiu2czIUMDCB118gFTKTUA=
|
||||
github.com/golang-migrate/migrate/v4 v4.11.0 h1:uqtd0ysK5WyBQ/T1K2uDIooJV0o2Obt6uPwP062DupQ=
|
||||
github.com/golang-migrate/migrate/v4 v4.11.0/go.mod h1:nqbpDbckcYjsCD5I8q5+NI9Tkk7SVcmaF40Ax1eAWhg=
|
||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
||||
github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e h1:1r7pUrabqp18hOBcwBwiTsbnFeTZHV9eER/QT5JVZxY=
|
||||
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
||||
github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
||||
github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y=
|
||||
github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
|
||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
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/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
|
||||
github.com/golang/protobuf v1.3.4 h1:87PNWwrRvUSnqS4dlcBU/ftvOIBep4sYuBLlh6rX2wk=
|
||||
github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
|
||||
github.com/golang/snappy v0.0.0-20170215233205-553a64147049/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||
github.com/golang/snappy v0.0.1 h1:Qgr9rKW7uDUkrbSmQeiDsGa8SjGyCOGtuasMWwvp2P4=
|
||||
github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||
github.com/gomodule/redigo v2.0.0+incompatible h1:K/R+8tc58AaqLkqG2Ol3Qk+DR/TlNuhuh457pBFPtt0=
|
||||
github.com/gomodule/redigo v2.0.0+incompatible/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 h1:xsAVV57WRhGj6kEIi8ReJzQlHHqcBYCElAvkovg3B/4=
|
||||
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ=
|
||||
github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck=
|
||||
github.com/google/martian v2.1.0+incompatible h1:/CP5g8u/VJHijgedC/Legn3BAbAaWPgecwXBIDzw5no=
|
||||
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
|
||||
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
|
||||
github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
|
||||
github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
|
||||
github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
|
||||
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
|
||||
github.com/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY=
|
||||
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
|
||||
github.com/googleapis/gax-go/v2 v2.0.5 h1:sjZBwGj9Jlw33ImPtvFviGYvseOtDM7hkSKB7+Tv3SM=
|
||||
github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
|
||||
github.com/gorilla/context v0.0.0-20160226214623-1ea25387ff6f/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg=
|
||||
github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg=
|
||||
github.com/gorilla/handlers v1.4.2/go.mod h1:Qkdc/uu4tH4g6mTK6auzZ766c4CA0Ng8+o/OAirnOIQ=
|
||||
github.com/gorilla/mux v1.6.1/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
|
||||
github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
|
||||
github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
|
||||
github.com/gorilla/mux v1.7.4/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
|
||||
github.com/gorilla/websocket v1.2.0 h1:VJtLvh6VQym50czpZzx07z/kw9EgAxI3x1ZB8taTMQQ=
|
||||
github.com/gorilla/websocket v1.2.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
|
||||
github.com/gorilla/websocket v1.4.0 h1:WDFjx/TMzVgy9VdMMQi2K2Emtwi2QcUQsztZ/zLaH/Q=
|
||||
@ -72,39 +219,102 @@ github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoA
|
||||
github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/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.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
|
||||
github.com/hailocab/go-hostpool v0.0.0-20160125115350-e80d13ce29ed/go.mod h1:tMWxXQ9wFIaZeTI9F+hmhFiGpFmhOHzyShyFUhRm0H4=
|
||||
github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA=
|
||||
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
|
||||
github.com/hashicorp/go-multierror v1.1.0 h1:B9UzwGQJehnUY1yNrnwREHc3fGbC2xefo8g4TbElacI=
|
||||
github.com/hashicorp/go-multierror v1.1.0/go.mod h1:spPvp8C1qA32ftKqdAHm4hHTbPw+vmowP0z+KUhOZdA=
|
||||
github.com/hashicorp/golang-lru v0.5.0 h1:CL2msUPvZTLb5O648aiLNJw3hnBxN2+1Jq8rCOH9wdo=
|
||||
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
||||
github.com/hashicorp/golang-lru v0.5.1 h1:0hERBMJE1eitiLkihrMvRVBYAkpHzc/J3QdDN+dAcgU=
|
||||
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
||||
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
|
||||
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
||||
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
|
||||
github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM=
|
||||
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
|
||||
github.com/jackc/chunkreader v1.0.0/go.mod h1:RT6O25fNZIuasFJRyZ4R/Y2BbhasbmZXF9QQ7T3kePo=
|
||||
github.com/jackc/chunkreader/v2 v2.0.0/go.mod h1:odVSm741yZoC3dpHEUXIqA9tQRhFrgOHwnPIn9lDKlk=
|
||||
github.com/jackc/chunkreader/v2 v2.0.1/go.mod h1:odVSm741yZoC3dpHEUXIqA9tQRhFrgOHwnPIn9lDKlk=
|
||||
github.com/jackc/pgconn v0.0.0-20190420214824-7e0022ef6ba3/go.mod h1:jkELnwuX+w9qN5YIfX0fl88Ehu4XC3keFuOJJk9pcnA=
|
||||
github.com/jackc/pgconn v0.0.0-20190824142844-760dd75542eb/go.mod h1:lLjNuW/+OfW9/pnVKPazfWOgNfH2aPem8YQ7ilXGvJE=
|
||||
github.com/jackc/pgconn v0.0.0-20190831204454-2fabfa3c18b7/go.mod h1:ZJKsE/KZfsUgOEh9hBm+xYTstcNHg7UPMVJqRfQxq4s=
|
||||
github.com/jackc/pgconn v1.3.2/go.mod h1:LvCquS3HbBKwgl7KbX9KyqEIumJAbm1UMcTvGaIf3bM=
|
||||
github.com/jackc/pgio v1.0.0/go.mod h1:oP+2QK2wFfUWgr+gxjoBH9KGBb31Eio69xUb0w5bYf8=
|
||||
github.com/jackc/pgmock v0.0.0-20190831213851-13a1b77aafa2/go.mod h1:fGZlG77KXmcq05nJLRkk0+p82V8B8Dw8KN2/V9c/OAE=
|
||||
github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg=
|
||||
github.com/jackc/pgproto3 v1.1.0/go.mod h1:eR5FA3leWg7p9aeAqi37XOTgTIbkABlvcPB3E5rlc78=
|
||||
github.com/jackc/pgproto3/v2 v2.0.0-alpha1.0.20190420180111-c116219b62db/go.mod h1:bhq50y+xrl9n5mRYyCBFKkpRVTLYJVWeCc+mEAI3yXA=
|
||||
github.com/jackc/pgproto3/v2 v2.0.0-alpha1.0.20190609003834-432c2951c711/go.mod h1:uH0AWtUmuShn0bcesswc4aBTWGvw0cAxIJp+6OB//Wg=
|
||||
github.com/jackc/pgproto3/v2 v2.0.0-rc3/go.mod h1:ryONWYqW6dqSg1Lw6vXNMXoBJhpzvWKnT95C46ckYeM=
|
||||
github.com/jackc/pgproto3/v2 v2.0.0-rc3.0.20190831210041-4c03ce451f29/go.mod h1:ryONWYqW6dqSg1Lw6vXNMXoBJhpzvWKnT95C46ckYeM=
|
||||
github.com/jackc/pgproto3/v2 v2.0.1/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA=
|
||||
github.com/jackc/pgtype v0.0.0-20190421001408-4ed0de4755e0/go.mod h1:hdSHsc1V01CGwFsrv11mJRHWJ6aifDLfdV3aVjFF0zg=
|
||||
github.com/jackc/pgtype v0.0.0-20190824184912-ab885b375b90/go.mod h1:KcahbBH1nCMSo2DXpzsoWOAfFkdEtEJpPbVLq8eE+mc=
|
||||
github.com/jackc/pgtype v0.0.0-20190828014616-a8802b16cc59/go.mod h1:MWlu30kVJrUS8lot6TQqcg7mtthZ9T0EoIBFiJcmcyw=
|
||||
github.com/jackc/pgx/v4 v4.0.0-20190420224344-cc3461e65d96/go.mod h1:mdxmSJJuR08CZQyj1PVQBHy9XOp5p8/SHH6a0psbY9Y=
|
||||
github.com/jackc/pgx/v4 v4.0.0-20190421002000-1b8f0016e912/go.mod h1:no/Y67Jkk/9WuGR0JG/JseM9irFbnEPbuWV2EELPNuM=
|
||||
github.com/jackc/pgx/v4 v4.0.0-pre1.0.20190824185557-6972a5742186/go.mod h1:X+GQnOEnf1dqHGpw7JmHqHc1NxDoalibchSk9/RWuDc=
|
||||
github.com/jackc/puddle v0.0.0-20190413234325-e4ced69a3a2b/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk=
|
||||
github.com/jackc/puddle v0.0.0-20190608224051-11cab39313c9/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk=
|
||||
github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af h1:pmfjZENx5imkbgOkpRUYLnmbU7UEFbjtDA2hxJ1ichM=
|
||||
github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
|
||||
github.com/jmoiron/sqlx v1.2.0 h1:41Ip0zITnmWNR/vHV+S4m+VoUivnWY5E4OJfLZjCJMA=
|
||||
github.com/jmoiron/sqlx v1.2.0/go.mod h1:1FEQNm3xlJgrMD+FBdI9+xvCksHtbpVBBw5dYhBSsks=
|
||||
github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg=
|
||||
github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
|
||||
github.com/jordan-wright/email v0.0.0-20200602115436-fd8a7622303e h1:OGunVjqY7y4U4laftpEHv+mvZBlr7UGimJXKEGQtg48=
|
||||
github.com/jordan-wright/email v0.0.0-20200602115436-fd8a7622303e/go.mod h1:Fy2gCFfZhay8jplf/Csj6cyH/oshQTkLQYZbKkcV+SY=
|
||||
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
|
||||
github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk=
|
||||
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
|
||||
github.com/kardianos/osext v0.0.0-20190222173326-2bc1f35cddc0/go.mod h1:1NbS8ALrpOvjt0rHPNLyCIeMtbizbir8U//inJ+zuB8=
|
||||
github.com/karrick/godirwalk v1.8.0/go.mod h1:H5KPZjojv4lE+QYImBI8xVtrBRgYrIVsaRPx4tDPEn4=
|
||||
github.com/karrick/godirwalk v1.10.3/go.mod h1:RoGL9dQei4vP9ilrpETWE8CLOZ1kiN0LhBygSwrAsHA=
|
||||
github.com/karrick/godirwalk v1.10.12/go.mod h1:RoGL9dQei4vP9ilrpETWE8CLOZ1kiN0LhBygSwrAsHA=
|
||||
github.com/kelseyhightower/envconfig v1.4.0 h1:Im6hONhd3pLkfDFsbRgu68RDNkGF1r3dvMUtDTo2cv8=
|
||||
github.com/kelseyhightower/envconfig v1.4.0/go.mod h1:cccZRl6mQpaq41TPp5QxidR+Sa3axMbJDNb//FQX6Gg=
|
||||
github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
|
||||
github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00=
|
||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||
github.com/klauspost/compress v1.9.5/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A=
|
||||
github.com/klauspost/compress v1.10.2 h1:Znfn6hXZAHaLPNnlqUYRrBSReFHYybslgv4PTiyz6P0=
|
||||
github.com/klauspost/compress v1.10.2/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGiHgQ4OO8tzTaLawm8vnODuwDk=
|
||||
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/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
|
||||
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
|
||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/pty v1.1.8/go.mod h1:O1sed60cT9XZ5uDucP5qwvh+TE3NnUj51EiZO/lmSfw=
|
||||
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
|
||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/lib/pq v1.0.0 h1:X5PMW56eZitiTeO7tKzZxFCSpbFZJtkMMooicw2us9A=
|
||||
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=
|
||||
github.com/lib/pq v1.3.0 h1:/qkRGz8zljWiDcFvgpwUpwIAPu3r07TDvs3Rws+o/pU=
|
||||
github.com/lib/pq v1.3.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
|
||||
github.com/logrusorgru/aurora v0.0.0-20200102142835-e9ef32dff381/go.mod h1:7rIyQOR62GCctdiQpZ/zOJlFyk6y+94wXzv6RNZgaR4=
|
||||
github.com/magefile/mage v1.9.0 h1:t3AU2wNwehMCW97vuqQLtw6puppWXHO+O2MHo5a50XE=
|
||||
github.com/magefile/mage v1.9.0/go.mod h1:z5UZb/iS3GoOSn0JgWuiw7dxlurVYTu+/jHXqQg881A=
|
||||
github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
|
||||
github.com/markbates/oncer v0.0.0-20181203154359-bf2de49a0be2/go.mod h1:Ld9puTsIW75CHf65OeIOkyKbteujpZVXDpWK6YGZbxE=
|
||||
github.com/markbates/pkger v0.15.1/go.mod h1:0JoVlrol20BSywW79rN3kdFFsE5xYM+rSCQDXbLhiuI=
|
||||
github.com/markbates/safe v1.0.1/go.mod h1:nAqgmRi7cY2nqMc92/bSEeQA+R4OheNU2T1kNSCBdG0=
|
||||
github.com/matryer/moq v0.0.0-20200106131100-75d0ddfc0007 h1:reVOUXwnhsYv/8UqjvhrMOu5CNT9UapHFLbQ2JcXsmg=
|
||||
github.com/matryer/moq v0.0.0-20200106131100-75d0ddfc0007/go.mod h1:9ELz6aaclSIGnZBoaSLZ3NAl1VTufbOrXBPvtcy6WiQ=
|
||||
github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ=
|
||||
github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
|
||||
github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
|
||||
github.com/mattn/go-isatty v0.0.7/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
|
||||
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
|
||||
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
|
||||
github.com/mattn/go-sqlite3 v1.9.0 h1:pDRiWfl+++eC2FEFRy6jXmQlvp4Yh3z1MJKg4UeYM/4=
|
||||
github.com/mattn/go-sqlite3 v1.9.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
|
||||
github.com/mattn/go-sqlite3 v1.10.0 h1:jbhqpg7tQe4SupckyijYiy0mJJ/pRyHvXf7JdWK860o=
|
||||
github.com/mattn/go-sqlite3 v1.10.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
|
||||
github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1 h1:lYpkrQH5ajf0OXOcUbGjvZxxijuBwbbmlSxLiuofa+g=
|
||||
github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1/go.mod h1:pD8RvIylQ358TN4wwqatJ8rNavkEINozVn9DtGI3dfQ=
|
||||
@ -115,44 +325,81 @@ github.com/mitchellh/mapstructure v1.1.2 h1:fmNYVwqnSfB9mZU6OS2O6GsXM+wcskZDuKQz
|
||||
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
||||
github.com/monochromegane/go-gitignore v0.0.0-20200525100937-58356a36e03f h1:0HN0GKijN4mr9SmYoW/Ni3ozuNeHiSxo2s7drhv7obY=
|
||||
github.com/monochromegane/go-gitignore v0.0.0-20200525100937-58356a36e03f/go.mod h1:Pm3mSP3c5uWn86xMLZ5Sa7JB9GsEZySvHYXCTK4E9q4=
|
||||
github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc=
|
||||
github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc=
|
||||
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
|
||||
github.com/nakagami/firebirdsql v0.0.0-20190310045651-3c02a58cfed8/go.mod h1:86wM1zFnC6/uDBfZGNwB65O+pR2OFi5q/YQaEUid1qA=
|
||||
github.com/neo4j-drivers/gobolt v1.7.4/go.mod h1:O9AUbip4Dgre+CD3p40dnMD4a4r52QBIfblg5k7CTbE=
|
||||
github.com/neo4j/neo4j-go-driver v1.7.4/go.mod h1:aPO0vVr+WnhEJne+FgFjfsjzAnssPFLucHgGZ76Zb/U=
|
||||
github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U=
|
||||
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.0/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/opencontainers/go-digest v1.0.0-rc1/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s=
|
||||
github.com/opencontainers/image-spec v1.0.1/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=
|
||||
github.com/opentracing/basictracer-go v1.0.0/go.mod h1:QfBfYuafItcjQuMwinw9GhYKwFXS9KnPs5lxoYwgW74=
|
||||
github.com/opentracing/opentracing-go v1.0.2/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=
|
||||
github.com/opentracing/opentracing-go v1.1.0 h1:pWlfV3Bxv7k65HYwkikxat0+s3pV4bsqf19k25Ur8rU=
|
||||
github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=
|
||||
github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw=
|
||||
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
|
||||
github.com/pelletier/go-toml v1.4.0/go.mod h1:PN7xzY2wHTK0K9p34ErDQMlFxa51Fk0OUruD3k1mMwo=
|
||||
github.com/pelletier/go-toml v1.8.0 h1:Keo9qb7iRJs2voHvunFtuuYFsbWeOBh8/P9v/kVMFtw=
|
||||
github.com/pelletier/go-toml v1.8.0/go.mod h1:D6yutnOGMveHEPV7VQOuvI/gXY61bv+9bAOTRnLElKs=
|
||||
github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY=
|
||||
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=
|
||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/profile v1.3.0/go.mod h1:hJw3o1OdXxsrSjjVksARp5W95eeEaEfptyVZyv6JUPA=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
|
||||
github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829/go.mod h1:p2iRAGwDERtqlqzRXnrOVns+ignqQo//hLXqYxZYVNs=
|
||||
github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso=
|
||||
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
|
||||
github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
|
||||
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||
github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
|
||||
github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
|
||||
github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
|
||||
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
|
||||
github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
|
||||
github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
|
||||
github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
|
||||
github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
|
||||
github.com/remyoudompheng/bigfft v0.0.0-20190728182440-6a916e37a237/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
|
||||
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
|
||||
github.com/rogpeppe/go-internal v1.1.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
||||
github.com/rogpeppe/go-internal v1.2.2/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
||||
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
||||
github.com/rs/cors v1.6.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU=
|
||||
github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ=
|
||||
github.com/rs/zerolog v1.13.0/go.mod h1:YbFCdg8HfsridGWAh22vktObvhZbQsZXe4/zB0OKkWU=
|
||||
github.com/rs/zerolog v1.15.0/go.mod h1:xYTKnLHcpfU2225ny5qZjxnj9NvkumZYjJHlAThCjNc=
|
||||
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/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0=
|
||||
github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
|
||||
github.com/shopspring/decimal v0.0.0-20180709203117-cd690d0c9e24/go.mod h1:M+9NzErvs504Cn4c5DxATwIqPbtswREoFCre64PpcG4=
|
||||
github.com/shurcooL/httpfs v0.0.0-20171119174359-809beceb2371/go.mod h1:ZY1cvUeJuFPAdZ/B6v7RHavJWZn2YPVFQ1OSXhCGOkg=
|
||||
github.com/shurcooL/sanitized_anchor_name v1.0.0 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5IYyJwS/kOiWx8mHo=
|
||||
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
|
||||
github.com/shurcooL/vfsgen v0.0.0-20180121065927-ffb13db8def0/go.mod h1:TrYk7fJVaAttu97ZZKrO9UbRa8izdowaMIZcxYMbVaw=
|
||||
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
|
||||
github.com/sirupsen/logrus v1.4.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
|
||||
github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q=
|
||||
github.com/sirupsen/logrus v1.4.2 h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4=
|
||||
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
|
||||
github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM=
|
||||
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
|
||||
github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
|
||||
github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
|
||||
github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=
|
||||
github.com/spf13/cobra v1.0.0 h1:6m/oheQuQ13N9ks4hubMG6BnvwOeaJrqSPLahSnczz8=
|
||||
github.com/spf13/cobra v1.0.0/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHNrgE=
|
||||
github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
|
||||
@ -161,90 +408,319 @@ github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnIn
|
||||
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
|
||||
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||
github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE=
|
||||
github.com/streadway/amqp v0.0.0-20200108173154-1c71cc93ed71/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw=
|
||||
github.com/streadway/amqp v1.0.0 h1:kuuDrUJFZL1QYL9hUNuCxNObNzB0bV/ZG5jV3RWAQgo=
|
||||
github.com/streadway/amqp v1.0.0/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE=
|
||||
github.com/stretchr/testify v1.2.1/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
|
||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||
github.com/stvp/tempredis v0.0.0-20181119212430-b82af8480203/go.mod h1:oqN97ltKNihBbwlX8dLpwxCl3+HnXKV/R0e+sRLd9C8=
|
||||
github.com/tidwall/pretty v0.0.0-20180105212114-65a9db5fad51/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk=
|
||||
github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk=
|
||||
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
|
||||
github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc=
|
||||
github.com/urfave/cli v1.20.0 h1:fDqGv3UG/4jbVl/QkFwEdddtEDjh/5Ov6X+0B/3bPaw=
|
||||
github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
|
||||
github.com/urfave/cli v1.22.2/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
|
||||
github.com/urfave/cli/v2 v2.1.1 h1:Qt8FeAtxE/vfdrLmR3rxR6JRE0RoVmbXu8+6kZtYU4k=
|
||||
github.com/urfave/cli/v2 v2.1.1/go.mod h1:SE9GqnLQmjVa0iPEY0f1w3ygNIYcIJ0OKPMoW2caLfQ=
|
||||
github.com/vektah/dataloaden v0.2.1-0.20190515034641-a19b9a6e7c9e h1:+w0Zm/9gaWpEAyDlU1eKOuk5twTjAjuevXqcJJw8hrg=
|
||||
github.com/vektah/dataloaden v0.2.1-0.20190515034641-a19b9a6e7c9e/go.mod h1:/HUdMve7rvxZma+2ZELQeNh88+003LL7Pf/CZ089j8U=
|
||||
github.com/vektah/gqlparser/v2 v2.0.1 h1:xgl5abVnsd4hkN9rk65OJID9bfcLSMuTaTcZj777q1o=
|
||||
github.com/vektah/gqlparser/v2 v2.0.1/go.mod h1:SyUiHgLATUR8BiYURfTirrTcGpcE+4XkV2se04Px1Ms=
|
||||
github.com/xanzy/go-gitlab v0.15.0/go.mod h1:8zdQa/ri1dfn8eS3Ir1SyfvOKlw7WBJ8DVThkpGiXrs=
|
||||
github.com/xdg/scram v0.0.0-20180814205039-7eeb5667e42c h1:u40Z8hqBAAQyv+vATcGgV0YCnDjqSL7/q/JyPhhJSPk=
|
||||
github.com/xdg/scram v0.0.0-20180814205039-7eeb5667e42c/go.mod h1:lB8K/P019DLNhemzwFU4jHLhdvlE6uDZjXFejJXr49I=
|
||||
github.com/xdg/stringprep v0.0.0-20180714160509-73f8eece6fdc/go.mod h1:Jhud4/sHMO4oL310DaZAKk9ZaJ08SJfe+sJh0HrGL1Y=
|
||||
github.com/xdg/stringprep v1.0.0 h1:d9X0esnoa3dFsV0FG35rAT0RIhYFlPq7MiP+DW89La0=
|
||||
github.com/xdg/stringprep v1.0.0/go.mod h1:Jhud4/sHMO4oL310DaZAKk9ZaJ08SJfe+sJh0HrGL1Y=
|
||||
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/zenazn/goji v0.9.0/go.mod h1:7S9M489iMyHBNxwZnk9/EHS098H4/F6TATF2mIxtB1Q=
|
||||
gitlab.com/nyarla/go-crypt v0.0.0-20160106005555-d9a5dc2b789b/go.mod h1:T3BPAOm2cqquPa0MKWeNkmOM5RQsRhkrwMWonFMN7fE=
|
||||
go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
|
||||
go.mongodb.org/mongo-driver v1.1.0/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM=
|
||||
go.mongodb.org/mongo-driver v1.3.0 h1:ew6uUIeJOo+qdUUv7LxFCUhtWmVv7ZV/Xuy4FAUsw2E=
|
||||
go.mongodb.org/mongo-driver v1.3.0/go.mod h1:MSWZXKOynuguX+JSvwP8i+58jYCXxbia8HS3gZBapIE=
|
||||
go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk=
|
||||
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
|
||||
go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
|
||||
go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
||||
go.opencensus.io v0.22.3 h1:8sGtKOrtQqkN1bp2AtX+misvLIlOmsEsNd+9NIcPEm8=
|
||||
go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
||||
go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
|
||||
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
|
||||
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
|
||||
go.uber.org/zap v1.9.1/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
|
||||
go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
|
||||
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20190411191339-88737f569e3a/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE=
|
||||
golang.org/x/crypto v0.0.0-20190422162423-af44ce270edf/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE=
|
||||
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20190530122614-20be4c3c3ed5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550 h1:ObdrDkeb4kJdCP557AjRjq69pTHfNouLtWZG7j9rPN8=
|
||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073 h1:xMPOj6Pz6UipU1wXLkrtqpHbR0AVFnyPEQq/wRWz9lM=
|
||||
golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
|
||||
golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek=
|
||||
golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY=
|
||||
golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
|
||||
golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
|
||||
golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
|
||||
golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
|
||||
golang.org/x/exp v0.0.0-20200213203834-85f925bdd4d0/go.mod h1:IX6Eufr4L0ErOUlzqX/aFlHqsiKZRbV42Kb69e9VsTE=
|
||||
golang.org/x/exp v0.0.0-20200228211341-fcea875c7e85/go.mod h1:4M0jN8W1tt0AVLNr8HDosyJCDCDuyL9N9+3m7wDWgKw=
|
||||
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
|
||||
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
|
||||
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
|
||||
golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||
golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||
golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||
golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||
golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs=
|
||||
golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
|
||||
golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
|
||||
golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
|
||||
golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o=
|
||||
golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
|
||||
golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY=
|
||||
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
|
||||
golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
|
||||
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20181108082009-03003ca0c849/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
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-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
|
||||
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859 h1:R/3boaszxrf1GEUWTVDzSKVwLmSJpwZ1yqXm8j0v2QI=
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/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-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200301022130-244492dfa37a h1:GuSPYbZzB5/dcLNCwLQLsg3obCJtX9IJhpXkvY7kzk0=
|
||||
golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/oauth2 v0.0.0-20181106182150-f42d05182288/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d h1:TzXSXBo42m9gQenoE3b9BGiEpg5IG2JkU5FkPIawgtw=
|
||||
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190412183630-56d357773e84/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e h1:vcxGaoTs7kV8m5Np9uUNQin4BrLOthgV7252N8V+FwY=
|
||||
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190419153524-e8e3143a4f4a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
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-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190531175056-4c3a928424d2/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/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-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200116001909-b77594299b42 h1:vEOn+mP2zCOVzKckCZy6YsCtDblrpj/w7B9nxGNELpg=
|
||||
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200124204421-9fbb57f87de9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527 h1:uYVVQ9WP/Ds2ROhcaGPeIdVq0RIXVLwsHlnvJ+cT1So=
|
||||
golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||
golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
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-20181030221726-6c7e314b6563/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-20190125232054-d66bd3c5d5a6/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-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20190329151228-23e29df326fe/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20190416151739-9c9e1878f421/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20190420181800-aa740d480789/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||
golang.org/x/tools v0.0.0-20190425163242-31fd60d6bfdc/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||
golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||
golang.org/x/tools v0.0.0-20190515012406-7d7faa4812bd/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||
golang.org/x/tools v0.0.0-20190531172133-b3315ee88b7d/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
||||
golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
||||
golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
||||
golang.org/x/tools v0.0.0-20190624222133-a101b041ded4/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
||||
golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
||||
golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20190823170909-c4a336ef6a2f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.0.0-20200114235610-7ae403b6b589 h1:rjUrONFu4kLchcZTfp3/96bR8bW8dIa8uz3cR5n0cgM=
|
||||
golang.org/x/tools v0.0.0-20200114235610-7ae403b6b589/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.0.0-20200128002243-345141a36859/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.0.0-20200213224642-88e652f7a869/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.0.0-20200303165918-5bcca83a7881/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/xerrors v0.0.0-20190410155217-1f06c39b4373/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20190513163551-3ee3066db522/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
google.golang.org/api v0.3.1/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMtkk=
|
||||
google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
|
||||
google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M=
|
||||
google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
|
||||
google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
|
||||
google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
|
||||
google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
|
||||
google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
|
||||
google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
|
||||
google.golang.org/api v0.19.0 h1:GwFK8+l5/gdsOYKz5p6M4UK+QT8OvmHWZPJCnf+5DjA=
|
||||
google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
|
||||
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
||||
google.golang.org/appengine v1.3.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||
google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||
google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0=
|
||||
google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
|
||||
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
||||
google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
||||
google.golang.org/genproto v0.0.0-20190404172233-64821d5d2107/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
||||
google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
||||
google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
||||
google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
||||
google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
|
||||
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
|
||||
google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8=
|
||||
google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
|
||||
google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
|
||||
google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
|
||||
google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
|
||||
google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
|
||||
google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
|
||||
google.golang.org/genproto v0.0.0-20200128133413-58ce757ed39b/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
|
||||
google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA=
|
||||
google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||
google.golang.org/genproto v0.0.0-20200303153909-beee998c1893 h1:OTjq5CN+5TpMIvzqxSFCjbBX3jNKjX0XOPi4SdBxQU8=
|
||||
google.golang.org/genproto v0.0.0-20200303153909-beee998c1893/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||
google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs=
|
||||
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
||||
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
|
||||
google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
|
||||
google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
|
||||
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
|
||||
google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
||||
google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
||||
google.golang.org/grpc v1.27.1 h1:zvIju4sqAGvwKspUQOhwnpcqSbzi7/H6QomNNjTL4sk=
|
||||
google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
||||
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo=
|
||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
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/inconshreveable/log15.v2 v2.0.0-20180818164646-67afb5ed74ec/go.mod h1:aPpfJ7XW+gOuirDoZ8gHhLh3kZ1B08FtV2bbmy7Jv3s=
|
||||
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
|
||||
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/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74=
|
||||
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.4 h1:/eiJrUcujPVeJ3xlSWaiNi3uSVmDGBK1pDHUHAnao1I=
|
||||
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.7/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.8/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=
|
||||
gotest.tools/v3 v3.0.2/go.mod h1:3SzNCllyD9/Y+b5r9JIKQ474KzkZyqLqEfYqMsX94Bk=
|
||||
honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
|
||||
honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
|
||||
modernc.org/b v1.0.0/go.mod h1:uZWcZfRj1BpYzfN9JTerzlNUnnPsV9O2ZA8JsRcubNg=
|
||||
modernc.org/db v1.0.0/go.mod h1:kYD/cO29L/29RM0hXYl4i3+Q5VojL31kTUVpVJDw0s8=
|
||||
modernc.org/file v1.0.0/go.mod h1:uqEokAEn1u6e+J45e54dsEA/pw4o7zLrA2GwyntZzjw=
|
||||
modernc.org/fileutil v1.0.0/go.mod h1:JHsWpkrk/CnVV1H/eGlFf85BEpfkrp56ro8nojIq9Q8=
|
||||
modernc.org/golex v1.0.0/go.mod h1:b/QX9oBD/LhixY6NDh+IdGv17hgB+51fET1i2kPSmvk=
|
||||
modernc.org/internal v1.0.0/go.mod h1:VUD/+JAkhCpvkUitlEOnhpVxCgsBI90oTzSCRcqQVSM=
|
||||
modernc.org/lldb v1.0.0/go.mod h1:jcRvJGWfCGodDZz8BPwiKMJxGJngQ/5DrRapkQnLob8=
|
||||
modernc.org/mathutil v1.0.0/go.mod h1:wU0vUrJsVWBZ4P6e7xtFJEhFSNsfRLJ8H458uRjg03k=
|
||||
modernc.org/ql v1.0.0/go.mod h1:xGVyrLIatPcO2C1JvI/Co8c0sr6y91HKFNy4pt9JXEY=
|
||||
modernc.org/sortutil v1.1.0/go.mod h1:ZyL98OQHJgH9IEfN71VsamvJgrtRX9Dj2gX+vH86L1k=
|
||||
modernc.org/strutil v1.1.0/go.mod h1:lstksw84oURvj9y3tn8lGvRxyRC1S2+g5uuIzNfIOBs=
|
||||
modernc.org/zappy v1.0.0/go.mod h1:hHe+oGahLVII/aTTyWK/b53VDHMAGCBYYeZ9sn83HC4=
|
||||
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
|
||||
rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
|
||||
rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
|
||||
sourcegraph.com/sourcegraph/appdash v0.0.0-20180110180208-2cc67fd64755/go.mod h1:hI742Nqp5OhwiqlzhgfbWU4mW4yO10fP+LoT9WOswdU=
|
||||
sourcegraph.com/sourcegraph/appdash-data v0.0.0-20151005221446-73f23eafcf67/go.mod h1:L5q+DGLGOQFpo1snNEkLOJT2d1YTW66rWNzatr3He1k=
|
||||
|
@ -1,10 +1,10 @@
|
||||
# Where are all the schema files located? globs are supported eg src/**/*.graphqls
|
||||
schema:
|
||||
- graph/*.graphqls
|
||||
- internal/graph/schema.graphqls
|
||||
|
||||
# Where should the generated server code go?
|
||||
exec:
|
||||
filename: graph/generated.go
|
||||
filename: internal/graph/generated.go
|
||||
package: graph
|
||||
|
||||
# Uncomment to enable federation
|
||||
@ -14,7 +14,7 @@ exec:
|
||||
|
||||
# Where should any generated models go?
|
||||
model:
|
||||
filename: graph/models_gen.go
|
||||
filename: internal/graph/models_gen.go
|
||||
package: graph
|
||||
|
||||
# Where should the resolver implementations go?
|
||||
@ -29,7 +29,7 @@ omit_slice_element_pointers: true
|
||||
# gqlgen will search for any type names in the schema in these go packages
|
||||
# if they match it will use them, otherwise it will generate them.
|
||||
autobind:
|
||||
- "github.com/jordanknott/project-citadel/api/pg"
|
||||
- "github.com/jordanknott/project-citadel/api/internal/db"
|
||||
|
||||
# This section declares type mapping between the GraphQL and go type systems
|
||||
#
|
||||
@ -38,10 +38,10 @@ autobind:
|
||||
# your liking
|
||||
models:
|
||||
ID:
|
||||
model: github.com/jordanknott/project-citadel/api/graph.UUID
|
||||
model: github.com/jordanknott/project-citadel/api/internal/graph.UUID
|
||||
Int:
|
||||
model:
|
||||
- github.com/99designs/gqlgen/graphql.Int
|
||||
|
||||
UUID:
|
||||
model: github.com/jordanknott/project-citadel/api/graph.UUID
|
||||
model: github.com/jordanknott/project-citadel/api/internal/graph.UUID
|
||||
|
@ -1,4 +1,4 @@
|
||||
package router
|
||||
package auth
|
||||
|
||||
import (
|
||||
"time"
|
||||
@ -7,6 +7,30 @@ import (
|
||||
log "github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
var jwtKey = []byte("citadel_test_key")
|
||||
|
||||
type AccessTokenClaims struct {
|
||||
UserID string `json:"userId"`
|
||||
jwt.StandardClaims
|
||||
}
|
||||
|
||||
type RefreshTokenClaims struct {
|
||||
UserID string `json:"userId"`
|
||||
jwt.StandardClaims
|
||||
}
|
||||
|
||||
type ErrExpiredToken struct{}
|
||||
|
||||
func (r *ErrExpiredToken) Error() string {
|
||||
return "token is expired"
|
||||
}
|
||||
|
||||
type ErrMalformedToken struct{}
|
||||
|
||||
func (r *ErrMalformedToken) Error() string {
|
||||
return "token is malformed"
|
||||
}
|
||||
|
||||
func NewAccessToken(userID string) (string, error) {
|
||||
accessExpirationTime := time.Now().Add(5 * time.Second)
|
||||
accessClaims := &AccessTokenClaims{
|
||||
@ -51,7 +75,7 @@ func ValidateAccessToken(accessTokenString string) (AccessTokenClaims, error) {
|
||||
log.WithFields(log.Fields{
|
||||
"token": accessTokenString,
|
||||
"timeToExpire": time.Unix(accessClaims.ExpiresAt, 0),
|
||||
}).Info("token is valid")
|
||||
}).Debug("token is valid")
|
||||
return *accessClaims, nil
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
// Code generated by sqlc. DO NOT EDIT.
|
||||
|
||||
package pg
|
||||
package db
|
||||
|
||||
import (
|
||||
"context"
|
@ -1,7 +1,7 @@
|
||||
// Code generated by sqlc. DO NOT EDIT.
|
||||
// source: label_color.sql
|
||||
|
||||
package pg
|
||||
package db
|
||||
|
||||
import (
|
||||
"context"
|
@ -1,6 +1,6 @@
|
||||
// Code generated by sqlc. DO NOT EDIT.
|
||||
|
||||
package pg
|
||||
package db
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
@ -38,6 +38,14 @@ type ProjectLabel struct {
|
||||
Name sql.NullString `json:"name"`
|
||||
}
|
||||
|
||||
type ProjectMember struct {
|
||||
ProjectMemberID uuid.UUID `json:"project_member_id"`
|
||||
ProjectID uuid.UUID `json:"project_id"`
|
||||
UserID uuid.UUID `json:"user_id"`
|
||||
AddedAt time.Time `json:"added_at"`
|
||||
RoleCode string `json:"role_code"`
|
||||
}
|
||||
|
||||
type RefreshToken struct {
|
||||
TokenID uuid.UUID `json:"token_id"`
|
||||
UserID uuid.UUID `json:"user_id"`
|
||||
@ -45,6 +53,11 @@ type RefreshToken struct {
|
||||
ExpiresAt time.Time `json:"expires_at"`
|
||||
}
|
||||
|
||||
type Role struct {
|
||||
Code string `json:"code"`
|
||||
Name string `json:"name"`
|
||||
}
|
||||
|
||||
type Task struct {
|
||||
TaskID uuid.UUID `json:"task_id"`
|
||||
TaskGroupID uuid.UUID `json:"task_group_id"`
|
||||
@ -101,6 +114,7 @@ type Team struct {
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
Name string `json:"name"`
|
||||
OrganizationID uuid.UUID `json:"organization_id"`
|
||||
Owner uuid.UUID `json:"owner"`
|
||||
}
|
||||
|
||||
type TeamMember struct {
|
||||
@ -108,6 +122,7 @@ type TeamMember struct {
|
||||
TeamID uuid.UUID `json:"team_id"`
|
||||
UserID uuid.UUID `json:"user_id"`
|
||||
Addeddate time.Time `json:"addeddate"`
|
||||
RoleCode string `json:"role_code"`
|
||||
}
|
||||
|
||||
type UserAccount struct {
|
||||
@ -120,4 +135,5 @@ type UserAccount struct {
|
||||
FullName string `json:"full_name"`
|
||||
Initials string `json:"initials"`
|
||||
ProfileAvatarUrl sql.NullString `json:"profile_avatar_url"`
|
||||
RoleCode string `json:"role_code"`
|
||||
}
|
@ -1,7 +1,7 @@
|
||||
// Code generated by sqlc. DO NOT EDIT.
|
||||
// source: organization.sql
|
||||
|
||||
package pg
|
||||
package db
|
||||
|
||||
import (
|
||||
"context"
|
294
api/internal/db/project.sql.go
Normal file
294
api/internal/db/project.sql.go
Normal file
@ -0,0 +1,294 @@
|
||||
// Code generated by sqlc. DO NOT EDIT.
|
||||
// source: project.sql
|
||||
|
||||
package db
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
const createProject = `-- name: CreateProject :one
|
||||
INSERT INTO project(owner, team_id, created_at, name) VALUES ($1, $2, $3, $4) RETURNING project_id, team_id, created_at, name, owner
|
||||
`
|
||||
|
||||
type CreateProjectParams struct {
|
||||
Owner uuid.UUID `json:"owner"`
|
||||
TeamID uuid.UUID `json:"team_id"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
Name string `json:"name"`
|
||||
}
|
||||
|
||||
func (q *Queries) CreateProject(ctx context.Context, arg CreateProjectParams) (Project, error) {
|
||||
row := q.db.QueryRowContext(ctx, createProject,
|
||||
arg.Owner,
|
||||
arg.TeamID,
|
||||
arg.CreatedAt,
|
||||
arg.Name,
|
||||
)
|
||||
var i Project
|
||||
err := row.Scan(
|
||||
&i.ProjectID,
|
||||
&i.TeamID,
|
||||
&i.CreatedAt,
|
||||
&i.Name,
|
||||
&i.Owner,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const createProjectMember = `-- name: CreateProjectMember :one
|
||||
INSERT INTO project_member (project_id, user_id, role_code, added_at) VALUES ($1, $2, $3, $4)
|
||||
RETURNING project_member_id, project_id, user_id, added_at, role_code
|
||||
`
|
||||
|
||||
type CreateProjectMemberParams struct {
|
||||
ProjectID uuid.UUID `json:"project_id"`
|
||||
UserID uuid.UUID `json:"user_id"`
|
||||
RoleCode string `json:"role_code"`
|
||||
AddedAt time.Time `json:"added_at"`
|
||||
}
|
||||
|
||||
func (q *Queries) CreateProjectMember(ctx context.Context, arg CreateProjectMemberParams) (ProjectMember, error) {
|
||||
row := q.db.QueryRowContext(ctx, createProjectMember,
|
||||
arg.ProjectID,
|
||||
arg.UserID,
|
||||
arg.RoleCode,
|
||||
arg.AddedAt,
|
||||
)
|
||||
var i ProjectMember
|
||||
err := row.Scan(
|
||||
&i.ProjectMemberID,
|
||||
&i.ProjectID,
|
||||
&i.UserID,
|
||||
&i.AddedAt,
|
||||
&i.RoleCode,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const deleteProjectByID = `-- name: DeleteProjectByID :exec
|
||||
DELETE FROM project WHERE project_id = $1
|
||||
`
|
||||
|
||||
func (q *Queries) DeleteProjectByID(ctx context.Context, projectID uuid.UUID) error {
|
||||
_, err := q.db.ExecContext(ctx, deleteProjectByID, projectID)
|
||||
return err
|
||||
}
|
||||
|
||||
const deleteProjectMember = `-- name: DeleteProjectMember :exec
|
||||
DELETE FROM project_member WHERE user_id = $1 AND project_id = $2
|
||||
`
|
||||
|
||||
type DeleteProjectMemberParams struct {
|
||||
UserID uuid.UUID `json:"user_id"`
|
||||
ProjectID uuid.UUID `json:"project_id"`
|
||||
}
|
||||
|
||||
func (q *Queries) DeleteProjectMember(ctx context.Context, arg DeleteProjectMemberParams) error {
|
||||
_, err := q.db.ExecContext(ctx, deleteProjectMember, arg.UserID, arg.ProjectID)
|
||||
return err
|
||||
}
|
||||
|
||||
const getAllProjects = `-- name: GetAllProjects :many
|
||||
SELECT project_id, team_id, created_at, name, owner FROM project
|
||||
`
|
||||
|
||||
func (q *Queries) GetAllProjects(ctx context.Context) ([]Project, error) {
|
||||
rows, err := q.db.QueryContext(ctx, getAllProjects)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
var items []Project
|
||||
for rows.Next() {
|
||||
var i Project
|
||||
if err := rows.Scan(
|
||||
&i.ProjectID,
|
||||
&i.TeamID,
|
||||
&i.CreatedAt,
|
||||
&i.Name,
|
||||
&i.Owner,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
items = append(items, i)
|
||||
}
|
||||
if err := rows.Close(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := rows.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return items, nil
|
||||
}
|
||||
|
||||
const getAllProjectsForTeam = `-- name: GetAllProjectsForTeam :many
|
||||
SELECT project_id, team_id, created_at, name, owner FROM project WHERE team_id = $1
|
||||
`
|
||||
|
||||
func (q *Queries) GetAllProjectsForTeam(ctx context.Context, teamID uuid.UUID) ([]Project, error) {
|
||||
rows, err := q.db.QueryContext(ctx, getAllProjectsForTeam, teamID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
var items []Project
|
||||
for rows.Next() {
|
||||
var i Project
|
||||
if err := rows.Scan(
|
||||
&i.ProjectID,
|
||||
&i.TeamID,
|
||||
&i.CreatedAt,
|
||||
&i.Name,
|
||||
&i.Owner,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
items = append(items, i)
|
||||
}
|
||||
if err := rows.Close(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := rows.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return items, nil
|
||||
}
|
||||
|
||||
const getProjectByID = `-- name: GetProjectByID :one
|
||||
SELECT project_id, team_id, created_at, name, owner FROM project WHERE project_id = $1
|
||||
`
|
||||
|
||||
func (q *Queries) GetProjectByID(ctx context.Context, projectID uuid.UUID) (Project, error) {
|
||||
row := q.db.QueryRowContext(ctx, getProjectByID, projectID)
|
||||
var i Project
|
||||
err := row.Scan(
|
||||
&i.ProjectID,
|
||||
&i.TeamID,
|
||||
&i.CreatedAt,
|
||||
&i.Name,
|
||||
&i.Owner,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const getProjectMembersForProjectID = `-- name: GetProjectMembersForProjectID :many
|
||||
SELECT project_member_id, project_id, user_id, added_at, role_code FROM project_member WHERE project_id = $1
|
||||
`
|
||||
|
||||
func (q *Queries) GetProjectMembersForProjectID(ctx context.Context, projectID uuid.UUID) ([]ProjectMember, error) {
|
||||
rows, err := q.db.QueryContext(ctx, getProjectMembersForProjectID, projectID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
var items []ProjectMember
|
||||
for rows.Next() {
|
||||
var i ProjectMember
|
||||
if err := rows.Scan(
|
||||
&i.ProjectMemberID,
|
||||
&i.ProjectID,
|
||||
&i.UserID,
|
||||
&i.AddedAt,
|
||||
&i.RoleCode,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
items = append(items, i)
|
||||
}
|
||||
if err := rows.Close(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := rows.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return items, nil
|
||||
}
|
||||
|
||||
const getRoleForProjectMemberByUserID = `-- name: GetRoleForProjectMemberByUserID :one
|
||||
SELECT code, role.name FROM project_member INNER JOIN role ON role.code = project_member.role_code
|
||||
WHERE user_id = $1 AND project_id = $2
|
||||
`
|
||||
|
||||
type GetRoleForProjectMemberByUserIDParams struct {
|
||||
UserID uuid.UUID `json:"user_id"`
|
||||
ProjectID uuid.UUID `json:"project_id"`
|
||||
}
|
||||
|
||||
func (q *Queries) GetRoleForProjectMemberByUserID(ctx context.Context, arg GetRoleForProjectMemberByUserIDParams) (Role, error) {
|
||||
row := q.db.QueryRowContext(ctx, getRoleForProjectMemberByUserID, arg.UserID, arg.ProjectID)
|
||||
var i Role
|
||||
err := row.Scan(&i.Code, &i.Name)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const setProjectOwner = `-- name: SetProjectOwner :one
|
||||
UPDATE project SET owner = $2 WHERE project_id = $1 RETURNING project_id, team_id, created_at, name, owner
|
||||
`
|
||||
|
||||
type SetProjectOwnerParams struct {
|
||||
ProjectID uuid.UUID `json:"project_id"`
|
||||
Owner uuid.UUID `json:"owner"`
|
||||
}
|
||||
|
||||
func (q *Queries) SetProjectOwner(ctx context.Context, arg SetProjectOwnerParams) (Project, error) {
|
||||
row := q.db.QueryRowContext(ctx, setProjectOwner, arg.ProjectID, arg.Owner)
|
||||
var i Project
|
||||
err := row.Scan(
|
||||
&i.ProjectID,
|
||||
&i.TeamID,
|
||||
&i.CreatedAt,
|
||||
&i.Name,
|
||||
&i.Owner,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const updateProjectMemberRole = `-- name: UpdateProjectMemberRole :one
|
||||
UPDATE project_member SET role_code = $3 WHERE project_id = $1 AND user_id = $2
|
||||
RETURNING project_member_id, project_id, user_id, added_at, role_code
|
||||
`
|
||||
|
||||
type UpdateProjectMemberRoleParams struct {
|
||||
ProjectID uuid.UUID `json:"project_id"`
|
||||
UserID uuid.UUID `json:"user_id"`
|
||||
RoleCode string `json:"role_code"`
|
||||
}
|
||||
|
||||
func (q *Queries) UpdateProjectMemberRole(ctx context.Context, arg UpdateProjectMemberRoleParams) (ProjectMember, error) {
|
||||
row := q.db.QueryRowContext(ctx, updateProjectMemberRole, arg.ProjectID, arg.UserID, arg.RoleCode)
|
||||
var i ProjectMember
|
||||
err := row.Scan(
|
||||
&i.ProjectMemberID,
|
||||
&i.ProjectID,
|
||||
&i.UserID,
|
||||
&i.AddedAt,
|
||||
&i.RoleCode,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const updateProjectNameByID = `-- name: UpdateProjectNameByID :one
|
||||
UPDATE project SET name = $2 WHERE project_id = $1 RETURNING project_id, team_id, created_at, name, owner
|
||||
`
|
||||
|
||||
type UpdateProjectNameByIDParams struct {
|
||||
ProjectID uuid.UUID `json:"project_id"`
|
||||
Name string `json:"name"`
|
||||
}
|
||||
|
||||
func (q *Queries) UpdateProjectNameByID(ctx context.Context, arg UpdateProjectNameByIDParams) (Project, error) {
|
||||
row := q.db.QueryRowContext(ctx, updateProjectNameByID, arg.ProjectID, arg.Name)
|
||||
var i Project
|
||||
err := row.Scan(
|
||||
&i.ProjectID,
|
||||
&i.TeamID,
|
||||
&i.CreatedAt,
|
||||
&i.Name,
|
||||
&i.Owner,
|
||||
)
|
||||
return i, err
|
||||
}
|
@ -1,7 +1,7 @@
|
||||
// Code generated by sqlc. DO NOT EDIT.
|
||||
// source: project_label.sql
|
||||
|
||||
package pg
|
||||
package db
|
||||
|
||||
import (
|
||||
"context"
|
@ -1,6 +1,6 @@
|
||||
// Code generated by sqlc. DO NOT EDIT.
|
||||
|
||||
package pg
|
||||
package db
|
||||
|
||||
import (
|
||||
"context"
|
||||
@ -13,6 +13,7 @@ type Querier interface {
|
||||
CreateOrganization(ctx context.Context, arg CreateOrganizationParams) (Organization, error)
|
||||
CreateProject(ctx context.Context, arg CreateProjectParams) (Project, error)
|
||||
CreateProjectLabel(ctx context.Context, arg CreateProjectLabelParams) (ProjectLabel, error)
|
||||
CreateProjectMember(ctx context.Context, arg CreateProjectMemberParams) (ProjectMember, error)
|
||||
CreateRefreshToken(ctx context.Context, arg CreateRefreshTokenParams) (RefreshToken, error)
|
||||
CreateTask(ctx context.Context, arg CreateTaskParams) (Task, error)
|
||||
CreateTaskAssigned(ctx context.Context, arg CreateTaskAssignedParams) (TaskAssigned, error)
|
||||
@ -26,6 +27,7 @@ type Querier interface {
|
||||
DeleteExpiredTokens(ctx context.Context) error
|
||||
DeleteProjectByID(ctx context.Context, projectID uuid.UUID) error
|
||||
DeleteProjectLabelByID(ctx context.Context, projectLabelID uuid.UUID) error
|
||||
DeleteProjectMember(ctx context.Context, arg DeleteProjectMemberParams) error
|
||||
DeleteRefreshTokenByID(ctx context.Context, tokenID uuid.UUID) error
|
||||
DeleteRefreshTokenByUserID(ctx context.Context, userID uuid.UUID) error
|
||||
DeleteTaskAssignedByID(ctx context.Context, arg DeleteTaskAssignedByIDParams) (TaskAssigned, error)
|
||||
@ -37,7 +39,7 @@ type Querier interface {
|
||||
DeleteTaskLabelForTaskByProjectLabelID(ctx context.Context, arg DeleteTaskLabelForTaskByProjectLabelIDParams) error
|
||||
DeleteTasksByTaskGroupID(ctx context.Context, taskGroupID uuid.UUID) (int64, error)
|
||||
DeleteTeamByID(ctx context.Context, teamID uuid.UUID) error
|
||||
DeleteTeamMemberByUserID(ctx context.Context, userID uuid.UUID) error
|
||||
DeleteTeamMember(ctx context.Context, arg DeleteTeamMemberParams) error
|
||||
DeleteUserAccountByID(ctx context.Context, userID uuid.UUID) error
|
||||
GetAllOrganizations(ctx context.Context) ([]Organization, error)
|
||||
GetAllProjects(ctx context.Context) ([]Project, error)
|
||||
@ -50,9 +52,14 @@ type Querier interface {
|
||||
GetLabelColorByID(ctx context.Context, labelColorID uuid.UUID) (LabelColor, error)
|
||||
GetLabelColors(ctx context.Context) ([]LabelColor, error)
|
||||
GetProjectByID(ctx context.Context, projectID uuid.UUID) (Project, error)
|
||||
GetProjectIDForTask(ctx context.Context, taskID uuid.UUID) (uuid.UUID, error)
|
||||
GetProjectLabelByID(ctx context.Context, projectLabelID uuid.UUID) (ProjectLabel, error)
|
||||
GetProjectLabelsForProject(ctx context.Context, projectID uuid.UUID) ([]ProjectLabel, error)
|
||||
GetProjectMembersForProjectID(ctx context.Context, projectID uuid.UUID) ([]ProjectMember, error)
|
||||
GetRefreshTokenByID(ctx context.Context, tokenID uuid.UUID) (RefreshToken, error)
|
||||
GetRoleForProjectMemberByUserID(ctx context.Context, arg GetRoleForProjectMemberByUserIDParams) (Role, error)
|
||||
GetRoleForTeamMember(ctx context.Context, arg GetRoleForTeamMemberParams) (Role, error)
|
||||
GetRoleForUserID(ctx context.Context, userID uuid.UUID) (GetRoleForUserIDRow, error)
|
||||
GetTaskByID(ctx context.Context, taskID uuid.UUID) (Task, error)
|
||||
GetTaskChecklistByID(ctx context.Context, taskChecklistID uuid.UUID) (TaskChecklist, error)
|
||||
GetTaskChecklistItemByID(ctx context.Context, taskChecklistItemID uuid.UUID) (TaskChecklistItem, error)
|
||||
@ -65,16 +72,20 @@ type Querier interface {
|
||||
GetTaskLabelsForTaskID(ctx context.Context, taskID uuid.UUID) ([]TaskLabel, error)
|
||||
GetTasksForTaskGroupID(ctx context.Context, taskGroupID uuid.UUID) ([]Task, error)
|
||||
GetTeamByID(ctx context.Context, teamID uuid.UUID) (Team, error)
|
||||
GetTeamMemberByID(ctx context.Context, arg GetTeamMemberByIDParams) (TeamMember, error)
|
||||
GetTeamMembersForTeamID(ctx context.Context, teamID uuid.UUID) ([]TeamMember, error)
|
||||
GetTeamsForOrganization(ctx context.Context, organizationID uuid.UUID) ([]Team, error)
|
||||
GetUserAccountByID(ctx context.Context, userID uuid.UUID) (UserAccount, error)
|
||||
GetUserAccountByUsername(ctx context.Context, username string) (UserAccount, error)
|
||||
SetProjectOwner(ctx context.Context, arg SetProjectOwnerParams) (Project, error)
|
||||
SetTaskChecklistItemComplete(ctx context.Context, arg SetTaskChecklistItemCompleteParams) (TaskChecklistItem, error)
|
||||
SetTaskComplete(ctx context.Context, arg SetTaskCompleteParams) (Task, error)
|
||||
SetTaskGroupName(ctx context.Context, arg SetTaskGroupNameParams) (TaskGroup, error)
|
||||
SetTeamOwner(ctx context.Context, arg SetTeamOwnerParams) (Team, error)
|
||||
UpdateProjectLabel(ctx context.Context, arg UpdateProjectLabelParams) (ProjectLabel, error)
|
||||
UpdateProjectLabelColor(ctx context.Context, arg UpdateProjectLabelColorParams) (ProjectLabel, error)
|
||||
UpdateProjectLabelName(ctx context.Context, arg UpdateProjectLabelNameParams) (ProjectLabel, error)
|
||||
UpdateProjectMemberRole(ctx context.Context, arg UpdateProjectMemberRoleParams) (ProjectMember, error)
|
||||
UpdateProjectNameByID(ctx context.Context, arg UpdateProjectNameByIDParams) (Project, error)
|
||||
UpdateTaskChecklistItemName(ctx context.Context, arg UpdateTaskChecklistItemNameParams) (TaskChecklistItem, error)
|
||||
UpdateTaskChecklistName(ctx context.Context, arg UpdateTaskChecklistNameParams) (TaskChecklist, error)
|
||||
@ -83,6 +94,7 @@ type Querier interface {
|
||||
UpdateTaskGroupLocation(ctx context.Context, arg UpdateTaskGroupLocationParams) (TaskGroup, error)
|
||||
UpdateTaskLocation(ctx context.Context, arg UpdateTaskLocationParams) (Task, error)
|
||||
UpdateTaskName(ctx context.Context, arg UpdateTaskNameParams) (Task, error)
|
||||
UpdateTeamMemberRole(ctx context.Context, arg UpdateTeamMemberRoleParams) (TeamMember, error)
|
||||
UpdateUserAccountProfileAvatarURL(ctx context.Context, arg UpdateUserAccountProfileAvatarURLParams) (UserAccount, error)
|
||||
}
|
||||
|
41
api/internal/db/query/project.sql
Normal file
41
api/internal/db/query/project.sql
Normal file
@ -0,0 +1,41 @@
|
||||
-- name: GetAllProjects :many
|
||||
SELECT * FROM project;
|
||||
|
||||
-- name: GetAllProjectsForTeam :many
|
||||
SELECT * FROM project WHERE team_id = $1;
|
||||
|
||||
-- name: GetProjectByID :one
|
||||
SELECT * FROM project WHERE project_id = $1;
|
||||
|
||||
-- name: CreateProject :one
|
||||
INSERT INTO project(owner, team_id, created_at, name) VALUES ($1, $2, $3, $4) RETURNING *;
|
||||
|
||||
-- name: SetProjectOwner :one
|
||||
UPDATE project SET owner = $2 WHERE project_id = $1 RETURNING *;
|
||||
|
||||
-- name: UpdateProjectNameByID :one
|
||||
UPDATE project SET name = $2 WHERE project_id = $1 RETURNING *;
|
||||
|
||||
-- name: DeleteProjectByID :exec
|
||||
DELETE FROM project WHERE project_id = $1;
|
||||
|
||||
-- name: GetProjectMembersForProjectID :many
|
||||
SELECT * FROM project_member WHERE project_id = $1;
|
||||
|
||||
-- name: GetRoleForProjectMemberByUserID :one
|
||||
SELECT code, role.name FROM project_member INNER JOIN role ON role.code = project_member.role_code
|
||||
WHERE user_id = $1 AND project_id = $2;
|
||||
|
||||
-- name: CreateProjectMember :one
|
||||
INSERT INTO project_member (project_id, user_id, role_code, added_at) VALUES ($1, $2, $3, $4)
|
||||
RETURNING *;
|
||||
|
||||
-- name: DeleteProjectMember :exec
|
||||
DELETE FROM project_member WHERE user_id = $1 AND project_id = $2;
|
||||
|
||||
-- name: UpdateProjectMemberRole :one
|
||||
UPDATE project_member SET role_code = $3 WHERE project_id = $1 AND user_id = $2
|
||||
RETURNING *;
|
||||
|
||||
|
||||
|
@ -31,3 +31,8 @@ UPDATE task SET due_date = $2 WHERE task_id = $1 RETURNING *;
|
||||
|
||||
-- name: SetTaskComplete :one
|
||||
UPDATE task SET complete = $2 WHERE task_id = $1 RETURNING *;
|
||||
|
||||
-- name: GetProjectIDForTask :one
|
||||
SELECT project_id FROM task
|
||||
INNER JOIN task_group ON task_group.task_group_id = task.task_group_id
|
||||
WHERE task_id = $1;
|
@ -5,10 +5,13 @@ SELECT * FROM team;
|
||||
SELECT * FROM team WHERE team_id = $1;
|
||||
|
||||
-- name: CreateTeam :one
|
||||
INSERT INTO team (organization_id, created_at, name) VALUES ($1, $2, $3) RETURNING *;
|
||||
INSERT INTO team (organization_id, created_at, name, owner) VALUES ($1, $2, $3, $4) RETURNING *;
|
||||
|
||||
-- name: DeleteTeamByID :exec
|
||||
DELETE FROM team WHERE team_id = $1;
|
||||
|
||||
-- name: GetTeamsForOrganization :many
|
||||
SELECT * FROM team WHERE organization_id = $1;
|
||||
|
||||
-- name: SetTeamOwner :one
|
||||
UPDATE team SET owner = $2 WHERE team_id = $1 RETURNING *;
|
21
api/internal/db/query/team_member.sql
Normal file
21
api/internal/db/query/team_member.sql
Normal file
@ -0,0 +1,21 @@
|
||||
-- name: CreateTeamMember :one
|
||||
INSERT INTO team_member (team_id, user_id, addedDate, role_code) VALUES ($1, $2, $3, $4)
|
||||
RETURNING *;
|
||||
|
||||
-- name: GetTeamMembersForTeamID :many
|
||||
SELECT * FROM team_member WHERE team_id = $1;
|
||||
|
||||
-- name: DeleteTeamMember :exec
|
||||
DELETE FROM team_member WHERE user_id = $1 AND team_id = $2;
|
||||
|
||||
-- name: GetRoleForTeamMember :one
|
||||
SELECT code, role.name FROM team_member
|
||||
INNER JOIN role ON role.code = team_member.role_code
|
||||
WHERE user_id = $1 AND team_id = $2;
|
||||
|
||||
-- name: UpdateTeamMemberRole :one
|
||||
UPDATE team_member SET role_code = $3 WHERE user_id = $2 AND team_id = $1
|
||||
RETURNING *;
|
||||
|
||||
-- name: GetTeamMemberByID :one
|
||||
SELECT * FROM team_member WHERE team_id = $1 AND user_id = $2;
|
@ -8,8 +8,8 @@ SELECT * FROM user_account;
|
||||
SELECT * FROM user_account WHERE username = $1;
|
||||
|
||||
-- name: CreateUserAccount :one
|
||||
INSERT INTO user_account(full_name, initials, email, username, created_at, password_hash)
|
||||
VALUES ($1, $2, $3, $4, $5, $6) RETURNING *;
|
||||
INSERT INTO user_account(full_name, initials, email, username, created_at, password_hash, role_code)
|
||||
VALUES ($1, $2, $3, $4, $5, $6, $7) RETURNING *;
|
||||
|
||||
-- name: UpdateUserAccountProfileAvatarURL :one
|
||||
UPDATE user_account SET profile_avatar_url = $2 WHERE user_id = $1
|
||||
@ -17,3 +17,8 @@ UPDATE user_account SET profile_avatar_url = $2 WHERE user_id = $1
|
||||
|
||||
-- name: DeleteUserAccountByID :exec
|
||||
DELETE FROM user_account WHERE user_id = $1;
|
||||
|
||||
-- name: GetRoleForUserID :one
|
||||
SELECT username, role.code, role.name FROM user_account
|
||||
INNER JOIN role ON role.code = user_account.role_code
|
||||
WHERE user_id = $1;
|
18
api/internal/db/repository.go
Normal file
18
api/internal/db/repository.go
Normal file
@ -0,0 +1,18 @@
|
||||
package db
|
||||
|
||||
import (
|
||||
"github.com/jmoiron/sqlx"
|
||||
)
|
||||
|
||||
type Repository struct {
|
||||
*Queries
|
||||
db *sqlx.DB
|
||||
}
|
||||
|
||||
// NewRepository returns an implementation of the Repository interface.
|
||||
func NewRepository(db *sqlx.DB) *Repository {
|
||||
return &Repository{
|
||||
Queries: New(db.DB),
|
||||
db: db,
|
||||
}
|
||||
}
|
@ -1,7 +1,7 @@
|
||||
// Code generated by sqlc. DO NOT EDIT.
|
||||
// source: task.sql
|
||||
|
||||
package pg
|
||||
package db
|
||||
|
||||
import (
|
||||
"context"
|
||||
@ -101,6 +101,19 @@ func (q *Queries) GetAllTasks(ctx context.Context) ([]Task, error) {
|
||||
return items, nil
|
||||
}
|
||||
|
||||
const getProjectIDForTask = `-- name: GetProjectIDForTask :one
|
||||
SELECT project_id FROM task
|
||||
INNER JOIN task_group ON task_group.task_group_id = task.task_group_id
|
||||
WHERE task_id = $1
|
||||
`
|
||||
|
||||
func (q *Queries) GetProjectIDForTask(ctx context.Context, taskID uuid.UUID) (uuid.UUID, error) {
|
||||
row := q.db.QueryRowContext(ctx, getProjectIDForTask, taskID)
|
||||
var project_id uuid.UUID
|
||||
err := row.Scan(&project_id)
|
||||
return project_id, err
|
||||
}
|
||||
|
||||
const getTaskByID = `-- name: GetTaskByID :one
|
||||
SELECT task_id, task_group_id, created_at, name, position, description, due_date, complete FROM task WHERE task_id = $1
|
||||
`
|
@ -1,7 +1,7 @@
|
||||
// Code generated by sqlc. DO NOT EDIT.
|
||||
// source: task_assigned.sql
|
||||
|
||||
package pg
|
||||
package db
|
||||
|
||||
import (
|
||||
"context"
|
@ -1,7 +1,7 @@
|
||||
// Code generated by sqlc. DO NOT EDIT.
|
||||
// source: task_checklist.sql
|
||||
|
||||
package pg
|
||||
package db
|
||||
|
||||
import (
|
||||
"context"
|
@ -1,7 +1,7 @@
|
||||
// Code generated by sqlc. DO NOT EDIT.
|
||||
// source: task_group.sql
|
||||
|
||||
package pg
|
||||
package db
|
||||
|
||||
import (
|
||||
"context"
|
@ -1,7 +1,7 @@
|
||||
// Code generated by sqlc. DO NOT EDIT.
|
||||
// source: task_label.sql
|
||||
|
||||
package pg
|
||||
package db
|
||||
|
||||
import (
|
||||
"context"
|
@ -1,7 +1,7 @@
|
||||
// Code generated by sqlc. DO NOT EDIT.
|
||||
// source: team.sql
|
||||
|
||||
package pg
|
||||
package db
|
||||
|
||||
import (
|
||||
"context"
|
||||
@ -11,23 +11,30 @@ import (
|
||||
)
|
||||
|
||||
const createTeam = `-- name: CreateTeam :one
|
||||
INSERT INTO team (organization_id, created_at, name) VALUES ($1, $2, $3) RETURNING team_id, created_at, name, organization_id
|
||||
INSERT INTO team (organization_id, created_at, name, owner) VALUES ($1, $2, $3, $4) RETURNING team_id, created_at, name, organization_id, owner
|
||||
`
|
||||
|
||||
type CreateTeamParams struct {
|
||||
OrganizationID uuid.UUID `json:"organization_id"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
Name string `json:"name"`
|
||||
Owner uuid.UUID `json:"owner"`
|
||||
}
|
||||
|
||||
func (q *Queries) CreateTeam(ctx context.Context, arg CreateTeamParams) (Team, error) {
|
||||
row := q.db.QueryRowContext(ctx, createTeam, arg.OrganizationID, arg.CreatedAt, arg.Name)
|
||||
row := q.db.QueryRowContext(ctx, createTeam,
|
||||
arg.OrganizationID,
|
||||
arg.CreatedAt,
|
||||
arg.Name,
|
||||
arg.Owner,
|
||||
)
|
||||
var i Team
|
||||
err := row.Scan(
|
||||
&i.TeamID,
|
||||
&i.CreatedAt,
|
||||
&i.Name,
|
||||
&i.OrganizationID,
|
||||
&i.Owner,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
@ -42,7 +49,7 @@ func (q *Queries) DeleteTeamByID(ctx context.Context, teamID uuid.UUID) error {
|
||||
}
|
||||
|
||||
const getAllTeams = `-- name: GetAllTeams :many
|
||||
SELECT team_id, created_at, name, organization_id FROM team
|
||||
SELECT team_id, created_at, name, organization_id, owner FROM team
|
||||
`
|
||||
|
||||
func (q *Queries) GetAllTeams(ctx context.Context) ([]Team, error) {
|
||||
@ -59,6 +66,7 @@ func (q *Queries) GetAllTeams(ctx context.Context) ([]Team, error) {
|
||||
&i.CreatedAt,
|
||||
&i.Name,
|
||||
&i.OrganizationID,
|
||||
&i.Owner,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -74,7 +82,7 @@ func (q *Queries) GetAllTeams(ctx context.Context) ([]Team, error) {
|
||||
}
|
||||
|
||||
const getTeamByID = `-- name: GetTeamByID :one
|
||||
SELECT team_id, created_at, name, organization_id FROM team WHERE team_id = $1
|
||||
SELECT team_id, created_at, name, organization_id, owner FROM team WHERE team_id = $1
|
||||
`
|
||||
|
||||
func (q *Queries) GetTeamByID(ctx context.Context, teamID uuid.UUID) (Team, error) {
|
||||
@ -85,12 +93,13 @@ func (q *Queries) GetTeamByID(ctx context.Context, teamID uuid.UUID) (Team, erro
|
||||
&i.CreatedAt,
|
||||
&i.Name,
|
||||
&i.OrganizationID,
|
||||
&i.Owner,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const getTeamsForOrganization = `-- name: GetTeamsForOrganization :many
|
||||
SELECT team_id, created_at, name, organization_id FROM team WHERE organization_id = $1
|
||||
SELECT team_id, created_at, name, organization_id, owner FROM team WHERE organization_id = $1
|
||||
`
|
||||
|
||||
func (q *Queries) GetTeamsForOrganization(ctx context.Context, organizationID uuid.UUID) ([]Team, error) {
|
||||
@ -107,6 +116,7 @@ func (q *Queries) GetTeamsForOrganization(ctx context.Context, organizationID uu
|
||||
&i.CreatedAt,
|
||||
&i.Name,
|
||||
&i.OrganizationID,
|
||||
&i.Owner,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -120,3 +130,25 @@ func (q *Queries) GetTeamsForOrganization(ctx context.Context, organizationID uu
|
||||
}
|
||||
return items, nil
|
||||
}
|
||||
|
||||
const setTeamOwner = `-- name: SetTeamOwner :one
|
||||
UPDATE team SET owner = $2 WHERE team_id = $1 RETURNING team_id, created_at, name, organization_id, owner
|
||||
`
|
||||
|
||||
type SetTeamOwnerParams struct {
|
||||
TeamID uuid.UUID `json:"team_id"`
|
||||
Owner uuid.UUID `json:"owner"`
|
||||
}
|
||||
|
||||
func (q *Queries) SetTeamOwner(ctx context.Context, arg SetTeamOwnerParams) (Team, error) {
|
||||
row := q.db.QueryRowContext(ctx, setTeamOwner, arg.TeamID, arg.Owner)
|
||||
var i Team
|
||||
err := row.Scan(
|
||||
&i.TeamID,
|
||||
&i.CreatedAt,
|
||||
&i.Name,
|
||||
&i.OrganizationID,
|
||||
&i.Owner,
|
||||
)
|
||||
return i, err
|
||||
}
|
152
api/internal/db/team_member.sql.go
Normal file
152
api/internal/db/team_member.sql.go
Normal file
@ -0,0 +1,152 @@
|
||||
// Code generated by sqlc. DO NOT EDIT.
|
||||
// source: team_member.sql
|
||||
|
||||
package db
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
const createTeamMember = `-- name: CreateTeamMember :one
|
||||
INSERT INTO team_member (team_id, user_id, addedDate, role_code) VALUES ($1, $2, $3, $4)
|
||||
RETURNING team_member_id, team_id, user_id, addeddate, role_code
|
||||
`
|
||||
|
||||
type CreateTeamMemberParams struct {
|
||||
TeamID uuid.UUID `json:"team_id"`
|
||||
UserID uuid.UUID `json:"user_id"`
|
||||
Addeddate time.Time `json:"addeddate"`
|
||||
RoleCode string `json:"role_code"`
|
||||
}
|
||||
|
||||
func (q *Queries) CreateTeamMember(ctx context.Context, arg CreateTeamMemberParams) (TeamMember, error) {
|
||||
row := q.db.QueryRowContext(ctx, createTeamMember,
|
||||
arg.TeamID,
|
||||
arg.UserID,
|
||||
arg.Addeddate,
|
||||
arg.RoleCode,
|
||||
)
|
||||
var i TeamMember
|
||||
err := row.Scan(
|
||||
&i.TeamMemberID,
|
||||
&i.TeamID,
|
||||
&i.UserID,
|
||||
&i.Addeddate,
|
||||
&i.RoleCode,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const deleteTeamMember = `-- name: DeleteTeamMember :exec
|
||||
DELETE FROM team_member WHERE user_id = $1 AND team_id = $2
|
||||
`
|
||||
|
||||
type DeleteTeamMemberParams struct {
|
||||
UserID uuid.UUID `json:"user_id"`
|
||||
TeamID uuid.UUID `json:"team_id"`
|
||||
}
|
||||
|
||||
func (q *Queries) DeleteTeamMember(ctx context.Context, arg DeleteTeamMemberParams) error {
|
||||
_, err := q.db.ExecContext(ctx, deleteTeamMember, arg.UserID, arg.TeamID)
|
||||
return err
|
||||
}
|
||||
|
||||
const getRoleForTeamMember = `-- name: GetRoleForTeamMember :one
|
||||
SELECT code, role.name FROM team_member
|
||||
INNER JOIN role ON role.code = team_member.role_code
|
||||
WHERE user_id = $1 AND team_id = $2
|
||||
`
|
||||
|
||||
type GetRoleForTeamMemberParams struct {
|
||||
UserID uuid.UUID `json:"user_id"`
|
||||
TeamID uuid.UUID `json:"team_id"`
|
||||
}
|
||||
|
||||
func (q *Queries) GetRoleForTeamMember(ctx context.Context, arg GetRoleForTeamMemberParams) (Role, error) {
|
||||
row := q.db.QueryRowContext(ctx, getRoleForTeamMember, arg.UserID, arg.TeamID)
|
||||
var i Role
|
||||
err := row.Scan(&i.Code, &i.Name)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const getTeamMemberByID = `-- name: GetTeamMemberByID :one
|
||||
SELECT team_member_id, team_id, user_id, addeddate, role_code FROM team_member WHERE team_id = $1 AND user_id = $2
|
||||
`
|
||||
|
||||
type GetTeamMemberByIDParams struct {
|
||||
TeamID uuid.UUID `json:"team_id"`
|
||||
UserID uuid.UUID `json:"user_id"`
|
||||
}
|
||||
|
||||
func (q *Queries) GetTeamMemberByID(ctx context.Context, arg GetTeamMemberByIDParams) (TeamMember, error) {
|
||||
row := q.db.QueryRowContext(ctx, getTeamMemberByID, arg.TeamID, arg.UserID)
|
||||
var i TeamMember
|
||||
err := row.Scan(
|
||||
&i.TeamMemberID,
|
||||
&i.TeamID,
|
||||
&i.UserID,
|
||||
&i.Addeddate,
|
||||
&i.RoleCode,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const getTeamMembersForTeamID = `-- name: GetTeamMembersForTeamID :many
|
||||
SELECT team_member_id, team_id, user_id, addeddate, role_code FROM team_member WHERE team_id = $1
|
||||
`
|
||||
|
||||
func (q *Queries) GetTeamMembersForTeamID(ctx context.Context, teamID uuid.UUID) ([]TeamMember, error) {
|
||||
rows, err := q.db.QueryContext(ctx, getTeamMembersForTeamID, teamID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
var items []TeamMember
|
||||
for rows.Next() {
|
||||
var i TeamMember
|
||||
if err := rows.Scan(
|
||||
&i.TeamMemberID,
|
||||
&i.TeamID,
|
||||
&i.UserID,
|
||||
&i.Addeddate,
|
||||
&i.RoleCode,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
items = append(items, i)
|
||||
}
|
||||
if err := rows.Close(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := rows.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return items, nil
|
||||
}
|
||||
|
||||
const updateTeamMemberRole = `-- name: UpdateTeamMemberRole :one
|
||||
UPDATE team_member SET role_code = $3 WHERE user_id = $2 AND team_id = $1
|
||||
RETURNING team_member_id, team_id, user_id, addeddate, role_code
|
||||
`
|
||||
|
||||
type UpdateTeamMemberRoleParams struct {
|
||||
TeamID uuid.UUID `json:"team_id"`
|
||||
UserID uuid.UUID `json:"user_id"`
|
||||
RoleCode string `json:"role_code"`
|
||||
}
|
||||
|
||||
func (q *Queries) UpdateTeamMemberRole(ctx context.Context, arg UpdateTeamMemberRoleParams) (TeamMember, error) {
|
||||
row := q.db.QueryRowContext(ctx, updateTeamMemberRole, arg.TeamID, arg.UserID, arg.RoleCode)
|
||||
var i TeamMember
|
||||
err := row.Scan(
|
||||
&i.TeamMemberID,
|
||||
&i.TeamID,
|
||||
&i.UserID,
|
||||
&i.Addeddate,
|
||||
&i.RoleCode,
|
||||
)
|
||||
return i, err
|
||||
}
|
@ -1,7 +1,7 @@
|
||||
// Code generated by sqlc. DO NOT EDIT.
|
||||
// source: token.sql
|
||||
|
||||
package pg
|
||||
package db
|
||||
|
||||
import (
|
||||
"context"
|
@ -1,7 +1,7 @@
|
||||
// Code generated by sqlc. DO NOT EDIT.
|
||||
// source: user_accounts.sql
|
||||
|
||||
package pg
|
||||
package db
|
||||
|
||||
import (
|
||||
"context"
|
||||
@ -12,8 +12,8 @@ import (
|
||||
)
|
||||
|
||||
const createUserAccount = `-- name: CreateUserAccount :one
|
||||
INSERT INTO user_account(full_name, initials, email, username, created_at, password_hash)
|
||||
VALUES ($1, $2, $3, $4, $5, $6) RETURNING user_id, created_at, email, username, password_hash, profile_bg_color, full_name, initials, profile_avatar_url
|
||||
INSERT INTO user_account(full_name, initials, email, username, created_at, password_hash, role_code)
|
||||
VALUES ($1, $2, $3, $4, $5, $6, $7) RETURNING user_id, created_at, email, username, password_hash, profile_bg_color, full_name, initials, profile_avatar_url, role_code
|
||||
`
|
||||
|
||||
type CreateUserAccountParams struct {
|
||||
@ -23,6 +23,7 @@ type CreateUserAccountParams struct {
|
||||
Username string `json:"username"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
PasswordHash string `json:"password_hash"`
|
||||
RoleCode string `json:"role_code"`
|
||||
}
|
||||
|
||||
func (q *Queries) CreateUserAccount(ctx context.Context, arg CreateUserAccountParams) (UserAccount, error) {
|
||||
@ -33,6 +34,7 @@ func (q *Queries) CreateUserAccount(ctx context.Context, arg CreateUserAccountPa
|
||||
arg.Username,
|
||||
arg.CreatedAt,
|
||||
arg.PasswordHash,
|
||||
arg.RoleCode,
|
||||
)
|
||||
var i UserAccount
|
||||
err := row.Scan(
|
||||
@ -45,6 +47,7 @@ func (q *Queries) CreateUserAccount(ctx context.Context, arg CreateUserAccountPa
|
||||
&i.FullName,
|
||||
&i.Initials,
|
||||
&i.ProfileAvatarUrl,
|
||||
&i.RoleCode,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
@ -59,7 +62,7 @@ func (q *Queries) DeleteUserAccountByID(ctx context.Context, userID uuid.UUID) e
|
||||
}
|
||||
|
||||
const getAllUserAccounts = `-- name: GetAllUserAccounts :many
|
||||
SELECT user_id, created_at, email, username, password_hash, profile_bg_color, full_name, initials, profile_avatar_url FROM user_account
|
||||
SELECT user_id, created_at, email, username, password_hash, profile_bg_color, full_name, initials, profile_avatar_url, role_code FROM user_account
|
||||
`
|
||||
|
||||
func (q *Queries) GetAllUserAccounts(ctx context.Context) ([]UserAccount, error) {
|
||||
@ -81,6 +84,7 @@ func (q *Queries) GetAllUserAccounts(ctx context.Context) ([]UserAccount, error)
|
||||
&i.FullName,
|
||||
&i.Initials,
|
||||
&i.ProfileAvatarUrl,
|
||||
&i.RoleCode,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -95,8 +99,27 @@ func (q *Queries) GetAllUserAccounts(ctx context.Context) ([]UserAccount, error)
|
||||
return items, nil
|
||||
}
|
||||
|
||||
const getRoleForUserID = `-- name: GetRoleForUserID :one
|
||||
SELECT username, role.code, role.name FROM user_account
|
||||
INNER JOIN role ON role.code = user_account.role_code
|
||||
WHERE user_id = $1
|
||||
`
|
||||
|
||||
type GetRoleForUserIDRow struct {
|
||||
Username string `json:"username"`
|
||||
Code string `json:"code"`
|
||||
Name string `json:"name"`
|
||||
}
|
||||
|
||||
func (q *Queries) GetRoleForUserID(ctx context.Context, userID uuid.UUID) (GetRoleForUserIDRow, error) {
|
||||
row := q.db.QueryRowContext(ctx, getRoleForUserID, userID)
|
||||
var i GetRoleForUserIDRow
|
||||
err := row.Scan(&i.Username, &i.Code, &i.Name)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const getUserAccountByID = `-- name: GetUserAccountByID :one
|
||||
SELECT user_id, created_at, email, username, password_hash, profile_bg_color, full_name, initials, profile_avatar_url FROM user_account WHERE user_id = $1
|
||||
SELECT user_id, created_at, email, username, password_hash, profile_bg_color, full_name, initials, profile_avatar_url, role_code FROM user_account WHERE user_id = $1
|
||||
`
|
||||
|
||||
func (q *Queries) GetUserAccountByID(ctx context.Context, userID uuid.UUID) (UserAccount, error) {
|
||||
@ -112,12 +135,13 @@ func (q *Queries) GetUserAccountByID(ctx context.Context, userID uuid.UUID) (Use
|
||||
&i.FullName,
|
||||
&i.Initials,
|
||||
&i.ProfileAvatarUrl,
|
||||
&i.RoleCode,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const getUserAccountByUsername = `-- name: GetUserAccountByUsername :one
|
||||
SELECT user_id, created_at, email, username, password_hash, profile_bg_color, full_name, initials, profile_avatar_url FROM user_account WHERE username = $1
|
||||
SELECT user_id, created_at, email, username, password_hash, profile_bg_color, full_name, initials, profile_avatar_url, role_code FROM user_account WHERE username = $1
|
||||
`
|
||||
|
||||
func (q *Queries) GetUserAccountByUsername(ctx context.Context, username string) (UserAccount, error) {
|
||||
@ -133,13 +157,14 @@ func (q *Queries) GetUserAccountByUsername(ctx context.Context, username string)
|
||||
&i.FullName,
|
||||
&i.Initials,
|
||||
&i.ProfileAvatarUrl,
|
||||
&i.RoleCode,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const updateUserAccountProfileAvatarURL = `-- name: UpdateUserAccountProfileAvatarURL :one
|
||||
UPDATE user_account SET profile_avatar_url = $2 WHERE user_id = $1
|
||||
RETURNING user_id, created_at, email, username, password_hash, profile_bg_color, full_name, initials, profile_avatar_url
|
||||
RETURNING user_id, created_at, email, username, password_hash, profile_bg_color, full_name, initials, profile_avatar_url, role_code
|
||||
`
|
||||
|
||||
type UpdateUserAccountProfileAvatarURLParams struct {
|
||||
@ -160,6 +185,7 @@ func (q *Queries) UpdateUserAccountProfileAvatarURL(ctx context.Context, arg Upd
|
||||
&i.FullName,
|
||||
&i.Initials,
|
||||
&i.ProfileAvatarUrl,
|
||||
&i.RoleCode,
|
||||
)
|
||||
return i, err
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -12,11 +12,11 @@ import (
|
||||
"github.com/99designs/gqlgen/graphql/handler/transport"
|
||||
"github.com/99designs/gqlgen/graphql/playground"
|
||||
"github.com/google/uuid"
|
||||
"github.com/jordanknott/project-citadel/api/pg"
|
||||
"github.com/jordanknott/project-citadel/api/internal/db"
|
||||
)
|
||||
|
||||
// NewHandler returns a new graphql endpoint handler.
|
||||
func NewHandler(repo pg.Repository) http.Handler {
|
||||
func NewHandler(repo db.Repository) http.Handler {
|
||||
srv := handler.New(NewExecutableSchema(Config{
|
||||
Resolvers: &Resolver{
|
||||
Repository: repo,
|
@ -3,10 +3,13 @@
|
||||
package graph
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"github.com/jordanknott/project-citadel/api/pg"
|
||||
"github.com/jordanknott/project-citadel/api/internal/db"
|
||||
)
|
||||
|
||||
type AddTaskLabelInput struct {
|
||||
@ -24,6 +27,16 @@ type ChecklistBadge struct {
|
||||
Total int `json:"total"`
|
||||
}
|
||||
|
||||
type CreateProjectMember struct {
|
||||
ProjectID uuid.UUID `json:"projectID"`
|
||||
UserID uuid.UUID `json:"userID"`
|
||||
}
|
||||
|
||||
type CreateProjectMemberPayload struct {
|
||||
Ok bool `json:"ok"`
|
||||
Member *Member `json:"member"`
|
||||
}
|
||||
|
||||
type CreateTaskChecklist struct {
|
||||
TaskID uuid.UUID `json:"taskID"`
|
||||
Name string `json:"name"`
|
||||
@ -42,8 +55,8 @@ type CreateTeamMember struct {
|
||||
}
|
||||
|
||||
type CreateTeamMemberPayload struct {
|
||||
Team *pg.Team `json:"team"`
|
||||
TeamMember *ProjectMember `json:"teamMember"`
|
||||
Team *db.Team `json:"team"`
|
||||
TeamMember *Member `json:"teamMember"`
|
||||
}
|
||||
|
||||
type DeleteProject struct {
|
||||
@ -54,9 +67,20 @@ type DeleteProjectLabel struct {
|
||||
ProjectLabelID uuid.UUID `json:"projectLabelID"`
|
||||
}
|
||||
|
||||
type DeleteProjectMember struct {
|
||||
ProjectID uuid.UUID `json:"projectID"`
|
||||
UserID uuid.UUID `json:"userID"`
|
||||
}
|
||||
|
||||
type DeleteProjectMemberPayload struct {
|
||||
Ok bool `json:"ok"`
|
||||
Member *Member `json:"member"`
|
||||
ProjectID uuid.UUID `json:"projectID"`
|
||||
}
|
||||
|
||||
type DeleteProjectPayload struct {
|
||||
Ok bool `json:"ok"`
|
||||
Project *pg.Project `json:"project"`
|
||||
Project *db.Project `json:"project"`
|
||||
}
|
||||
|
||||
type DeleteTaskChecklist struct {
|
||||
@ -69,12 +93,12 @@ type DeleteTaskChecklistItem struct {
|
||||
|
||||
type DeleteTaskChecklistItemPayload struct {
|
||||
Ok bool `json:"ok"`
|
||||
TaskChecklistItem *pg.TaskChecklistItem `json:"taskChecklistItem"`
|
||||
TaskChecklistItem *db.TaskChecklistItem `json:"taskChecklistItem"`
|
||||
}
|
||||
|
||||
type DeleteTaskChecklistPayload struct {
|
||||
Ok bool `json:"ok"`
|
||||
TaskChecklist *pg.TaskChecklist `json:"taskChecklist"`
|
||||
TaskChecklist *db.TaskChecklist `json:"taskChecklist"`
|
||||
}
|
||||
|
||||
type DeleteTaskGroupInput struct {
|
||||
@ -84,7 +108,7 @@ type DeleteTaskGroupInput struct {
|
||||
type DeleteTaskGroupPayload struct {
|
||||
Ok bool `json:"ok"`
|
||||
AffectedRows int `json:"affectedRows"`
|
||||
TaskGroup *pg.TaskGroup `json:"taskGroup"`
|
||||
TaskGroup *db.TaskGroup `json:"taskGroup"`
|
||||
}
|
||||
|
||||
type DeleteTaskInput struct {
|
||||
@ -99,10 +123,20 @@ type DeleteTeam struct {
|
||||
TeamID uuid.UUID `json:"teamID"`
|
||||
}
|
||||
|
||||
type DeleteTeamMember struct {
|
||||
TeamID uuid.UUID `json:"teamID"`
|
||||
UserID uuid.UUID `json:"userID"`
|
||||
}
|
||||
|
||||
type DeleteTeamMemberPayload struct {
|
||||
TeamID uuid.UUID `json:"teamID"`
|
||||
UserID uuid.UUID `json:"userID"`
|
||||
}
|
||||
|
||||
type DeleteTeamPayload struct {
|
||||
Ok bool `json:"ok"`
|
||||
Team *pg.Team `json:"team"`
|
||||
Projects []pg.Project `json:"projects"`
|
||||
Team *db.Team `json:"team"`
|
||||
Projects []db.Project `json:"projects"`
|
||||
}
|
||||
|
||||
type DeleteUserAccount struct {
|
||||
@ -111,7 +145,7 @@ type DeleteUserAccount struct {
|
||||
|
||||
type DeleteUserAccountPayload struct {
|
||||
Ok bool `json:"ok"`
|
||||
UserAccount *pg.UserAccount `json:"userAccount"`
|
||||
UserAccount *db.UserAccount `json:"userAccount"`
|
||||
}
|
||||
|
||||
type FindProject struct {
|
||||
@ -134,6 +168,14 @@ type LogoutUser struct {
|
||||
UserID string `json:"userID"`
|
||||
}
|
||||
|
||||
type Member struct {
|
||||
ID uuid.UUID `json:"id"`
|
||||
Role *db.Role `json:"role"`
|
||||
FullName string `json:"fullName"`
|
||||
Username string `json:"username"`
|
||||
ProfileIcon *ProfileIcon `json:"profileIcon"`
|
||||
}
|
||||
|
||||
type NewProject struct {
|
||||
UserID uuid.UUID `json:"userID"`
|
||||
TeamID uuid.UUID `json:"teamID"`
|
||||
@ -184,6 +226,7 @@ type NewUserAccount struct {
|
||||
FullName string `json:"fullName"`
|
||||
Initials string `json:"initials"`
|
||||
Password string `json:"password"`
|
||||
RoleCode string `json:"roleCode"`
|
||||
}
|
||||
|
||||
type ProfileIcon struct {
|
||||
@ -192,12 +235,6 @@ type ProfileIcon struct {
|
||||
BgColor *string `json:"bgColor"`
|
||||
}
|
||||
|
||||
type ProjectMember struct {
|
||||
ID uuid.UUID `json:"id"`
|
||||
FullName string `json:"fullName"`
|
||||
ProfileIcon *ProfileIcon `json:"profileIcon"`
|
||||
}
|
||||
|
||||
type ProjectsFilter struct {
|
||||
TeamID *uuid.UUID `json:"teamID"`
|
||||
}
|
||||
@ -206,6 +243,17 @@ type RemoveTaskLabelInput struct {
|
||||
TaskLabelID uuid.UUID `json:"taskLabelID"`
|
||||
}
|
||||
|
||||
type SetProjectOwner struct {
|
||||
ProjectID uuid.UUID `json:"projectID"`
|
||||
OwnerID uuid.UUID `json:"ownerID"`
|
||||
}
|
||||
|
||||
type SetProjectOwnerPayload struct {
|
||||
Ok bool `json:"ok"`
|
||||
PrevOwner *Member `json:"prevOwner"`
|
||||
NewOwner *Member `json:"newOwner"`
|
||||
}
|
||||
|
||||
type SetTaskChecklistItemComplete struct {
|
||||
TaskChecklistItemID uuid.UUID `json:"taskChecklistItemID"`
|
||||
Complete bool `json:"complete"`
|
||||
@ -216,6 +264,17 @@ type SetTaskComplete struct {
|
||||
Complete bool `json:"complete"`
|
||||
}
|
||||
|
||||
type SetTeamOwner struct {
|
||||
TeamID uuid.UUID `json:"teamID"`
|
||||
UserID uuid.UUID `json:"userID"`
|
||||
}
|
||||
|
||||
type SetTeamOwnerPayload struct {
|
||||
Ok bool `json:"ok"`
|
||||
PrevOwner *Member `json:"prevOwner"`
|
||||
NewOwner *Member `json:"newOwner"`
|
||||
}
|
||||
|
||||
type TaskBadges struct {
|
||||
Checklist *ChecklistBadge `json:"checklist"`
|
||||
}
|
||||
@ -227,7 +286,7 @@ type ToggleTaskLabelInput struct {
|
||||
|
||||
type ToggleTaskLabelPayload struct {
|
||||
Active bool `json:"active"`
|
||||
Task *pg.Task `json:"task"`
|
||||
Task *db.Task `json:"task"`
|
||||
}
|
||||
|
||||
type UnassignTaskInput struct {
|
||||
@ -251,6 +310,17 @@ type UpdateProjectLabelName struct {
|
||||
Name string `json:"name"`
|
||||
}
|
||||
|
||||
type UpdateProjectMemberRole struct {
|
||||
ProjectID uuid.UUID `json:"projectID"`
|
||||
UserID uuid.UUID `json:"userID"`
|
||||
RoleCode RoleCode `json:"roleCode"`
|
||||
}
|
||||
|
||||
type UpdateProjectMemberRolePayload struct {
|
||||
Ok bool `json:"ok"`
|
||||
Member *Member `json:"member"`
|
||||
}
|
||||
|
||||
type UpdateProjectName struct {
|
||||
ProjectID uuid.UUID `json:"projectID"`
|
||||
Name string `json:"name"`
|
||||
@ -283,10 +353,66 @@ type UpdateTaskGroupName struct {
|
||||
|
||||
type UpdateTaskLocationPayload struct {
|
||||
PreviousTaskGroupID uuid.UUID `json:"previousTaskGroupID"`
|
||||
Task *pg.Task `json:"task"`
|
||||
Task *db.Task `json:"task"`
|
||||
}
|
||||
|
||||
type UpdateTaskName struct {
|
||||
TaskID string `json:"taskID"`
|
||||
Name string `json:"name"`
|
||||
}
|
||||
|
||||
type UpdateTeamMemberRole struct {
|
||||
TeamID uuid.UUID `json:"teamID"`
|
||||
UserID uuid.UUID `json:"userID"`
|
||||
RoleCode RoleCode `json:"roleCode"`
|
||||
}
|
||||
|
||||
type UpdateTeamMemberRolePayload struct {
|
||||
Ok bool `json:"ok"`
|
||||
Member *Member `json:"member"`
|
||||
}
|
||||
|
||||
type RoleCode string
|
||||
|
||||
const (
|
||||
RoleCodeOwner RoleCode = "owner"
|
||||
RoleCodeAdmin RoleCode = "admin"
|
||||
RoleCodeMember RoleCode = "member"
|
||||
RoleCodeObserver RoleCode = "observer"
|
||||
)
|
||||
|
||||
var AllRoleCode = []RoleCode{
|
||||
RoleCodeOwner,
|
||||
RoleCodeAdmin,
|
||||
RoleCodeMember,
|
||||
RoleCodeObserver,
|
||||
}
|
||||
|
||||
func (e RoleCode) IsValid() bool {
|
||||
switch e {
|
||||
case RoleCodeOwner, RoleCodeAdmin, RoleCodeMember, RoleCodeObserver:
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (e RoleCode) String() string {
|
||||
return string(e)
|
||||
}
|
||||
|
||||
func (e *RoleCode) UnmarshalGQL(v interface{}) error {
|
||||
str, ok := v.(string)
|
||||
if !ok {
|
||||
return fmt.Errorf("enums must be strings")
|
||||
}
|
||||
|
||||
*e = RoleCode(str)
|
||||
if !e.IsValid() {
|
||||
return fmt.Errorf("%s is not a valid RoleCode", str)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (e RoleCode) MarshalGQL(w io.Writer) {
|
||||
fmt.Fprint(w, strconv.Quote(e.String()))
|
||||
}
|
@ -1,13 +1,14 @@
|
||||
//go:generate sh ../scripts/genSchema.sh
|
||||
//go:generate go run github.com/99designs/gqlgen
|
||||
package graph
|
||||
|
||||
import (
|
||||
"sync"
|
||||
|
||||
"github.com/jordanknott/project-citadel/api/pg"
|
||||
"github.com/jordanknott/project-citadel/api/internal/db"
|
||||
)
|
||||
|
||||
type Resolver struct {
|
||||
Repository pg.Repository
|
||||
Repository db.Repository
|
||||
mu sync.Mutex
|
||||
}
|
@ -2,6 +2,13 @@ scalar Time
|
||||
scalar UUID
|
||||
scalar Upload
|
||||
|
||||
enum RoleCode {
|
||||
owner
|
||||
admin
|
||||
member
|
||||
observer
|
||||
}
|
||||
|
||||
type ProjectLabel {
|
||||
id: ID!
|
||||
createdDate: Time!
|
||||
@ -28,9 +35,11 @@ type ProfileIcon {
|
||||
bgColor: String
|
||||
}
|
||||
|
||||
type ProjectMember {
|
||||
type Member {
|
||||
id: ID!
|
||||
role: Role!
|
||||
fullName: String!
|
||||
username: String!
|
||||
profileIcon: ProfileIcon!
|
||||
}
|
||||
|
||||
@ -41,12 +50,18 @@ type RefreshToken {
|
||||
createdAt: Time!
|
||||
}
|
||||
|
||||
type Role {
|
||||
code: String!
|
||||
name: String!
|
||||
}
|
||||
|
||||
type UserAccount {
|
||||
id: ID!
|
||||
email: String!
|
||||
createdAt: Time!
|
||||
fullName: String!
|
||||
initials: String!
|
||||
role: Role!
|
||||
username: String!
|
||||
profileIcon: ProfileIcon!
|
||||
}
|
||||
@ -55,7 +70,7 @@ type Team {
|
||||
id: ID!
|
||||
createdAt: Time!
|
||||
name: String!
|
||||
members: [ProjectMember!]!
|
||||
members: [Member!]!
|
||||
}
|
||||
|
||||
type Project {
|
||||
@ -63,9 +78,9 @@ type Project {
|
||||
createdAt: Time!
|
||||
name: String!
|
||||
team: Team!
|
||||
owner: ProjectMember!
|
||||
owner: Member!
|
||||
taskGroups: [TaskGroup!]!
|
||||
members: [ProjectMember!]!
|
||||
members: [Member!]!
|
||||
labels: [ProjectLabel!]!
|
||||
}
|
||||
|
||||
@ -96,127 +111,17 @@ type Task {
|
||||
description: String
|
||||
dueDate: Time
|
||||
complete: Boolean!
|
||||
assigned: [ProjectMember!]!
|
||||
assigned: [Member!]!
|
||||
labels: [TaskLabel!]!
|
||||
checklists: [TaskChecklist!]!
|
||||
badges: TaskBadges!
|
||||
}
|
||||
|
||||
input ProjectsFilter {
|
||||
teamID: UUID
|
||||
}
|
||||
|
||||
input FindUser {
|
||||
userId: String!
|
||||
}
|
||||
|
||||
input FindProject {
|
||||
projectId: String!
|
||||
}
|
||||
|
||||
input FindTask {
|
||||
taskID: UUID!
|
||||
}
|
||||
|
||||
type Organization {
|
||||
id: ID!
|
||||
name: String!
|
||||
}
|
||||
|
||||
input FindTeam {
|
||||
teamID: UUID!
|
||||
}
|
||||
|
||||
type Query {
|
||||
organizations: [Organization!]!
|
||||
users: [UserAccount!]!
|
||||
findUser(input: FindUser!): UserAccount!
|
||||
findProject(input: FindProject!): Project!
|
||||
findTask(input: FindTask!): Task!
|
||||
projects(input: ProjectsFilter): [Project!]!
|
||||
findTeam(input: FindTeam!): Team!
|
||||
teams: [Team!]!
|
||||
labelColors: [LabelColor!]!
|
||||
taskGroups: [TaskGroup!]!
|
||||
me: UserAccount!
|
||||
}
|
||||
|
||||
input NewRefreshToken {
|
||||
userId: String!
|
||||
}
|
||||
|
||||
input NewUserAccount {
|
||||
username: String!
|
||||
email: String!
|
||||
fullName: String!
|
||||
initials: String!
|
||||
password: String!
|
||||
}
|
||||
|
||||
input NewTeam {
|
||||
name: String!
|
||||
organizationID: UUID!
|
||||
}
|
||||
|
||||
input NewProject {
|
||||
userID: UUID!
|
||||
teamID: UUID!
|
||||
name: String!
|
||||
}
|
||||
|
||||
input NewTaskGroup {
|
||||
projectID: String!
|
||||
name: String!
|
||||
position: Float!
|
||||
}
|
||||
|
||||
input LogoutUser {
|
||||
userID: String!
|
||||
}
|
||||
input NewTask {
|
||||
taskGroupID: String!
|
||||
name: String!
|
||||
position: Float!
|
||||
}
|
||||
input NewTaskLocation {
|
||||
taskID: UUID!
|
||||
taskGroupID: UUID!
|
||||
position: Float!
|
||||
}
|
||||
|
||||
input DeleteTaskInput {
|
||||
taskID: String!
|
||||
}
|
||||
|
||||
type DeleteTaskPayload {
|
||||
taskID: String!
|
||||
}
|
||||
|
||||
input UpdateTaskName {
|
||||
taskID: String!
|
||||
name: String!
|
||||
}
|
||||
|
||||
input NewTaskGroupLocation {
|
||||
taskGroupID: UUID!
|
||||
position: Float!
|
||||
}
|
||||
|
||||
input DeleteTaskGroupInput {
|
||||
taskGroupID: UUID!
|
||||
}
|
||||
|
||||
type DeleteTaskGroupPayload {
|
||||
ok: Boolean!
|
||||
affectedRows: Int!
|
||||
taskGroup: TaskGroup!
|
||||
}
|
||||
|
||||
type DeleteTaskChecklistItemPayload {
|
||||
ok: Boolean!
|
||||
taskChecklistItem: TaskChecklistItem!
|
||||
}
|
||||
|
||||
type TaskChecklistItem {
|
||||
id: ID!
|
||||
name: String!
|
||||
@ -233,27 +138,75 @@ type TaskChecklist {
|
||||
items: [TaskChecklistItem!]!
|
||||
}
|
||||
|
||||
input AssignTaskInput {
|
||||
type Query {
|
||||
organizations: [Organization!]!
|
||||
users: [UserAccount!]!
|
||||
findUser(input: FindUser!): UserAccount!
|
||||
findProject(input: FindProject!): Project!
|
||||
findTask(input: FindTask!): Task!
|
||||
projects(input: ProjectsFilter): [Project!]!
|
||||
findTeam(input: FindTeam!): Team!
|
||||
teams: [Team!]!
|
||||
labelColors: [LabelColor!]!
|
||||
taskGroups: [TaskGroup!]!
|
||||
me: UserAccount!
|
||||
}
|
||||
|
||||
type Mutation
|
||||
|
||||
input ProjectsFilter {
|
||||
teamID: UUID
|
||||
}
|
||||
|
||||
input FindUser {
|
||||
userId: String!
|
||||
}
|
||||
|
||||
input FindProject {
|
||||
projectId: String!
|
||||
}
|
||||
|
||||
input FindTask {
|
||||
taskID: UUID!
|
||||
}
|
||||
|
||||
input FindTeam {
|
||||
teamID: UUID!
|
||||
}
|
||||
|
||||
extend type Mutation {
|
||||
createProject(input: NewProject!): Project!
|
||||
deleteProject(input: DeleteProject!): DeleteProjectPayload!
|
||||
updateProjectName(input: UpdateProjectName): Project!
|
||||
}
|
||||
|
||||
input NewProject {
|
||||
userID: UUID!
|
||||
teamID: UUID!
|
||||
name: String!
|
||||
}
|
||||
|
||||
input UnassignTaskInput {
|
||||
taskID: UUID!
|
||||
userID: UUID!
|
||||
}
|
||||
input UpdateTaskDescriptionInput {
|
||||
taskID: UUID!
|
||||
description: String!
|
||||
input UpdateProjectName {
|
||||
projectID: UUID!
|
||||
name: String!
|
||||
}
|
||||
|
||||
input AddTaskLabelInput {
|
||||
taskID: UUID!
|
||||
projectLabelID: UUID!
|
||||
input DeleteProject {
|
||||
projectID: UUID!
|
||||
}
|
||||
|
||||
input RemoveTaskLabelInput {
|
||||
taskLabelID: UUID!
|
||||
type DeleteProjectPayload {
|
||||
ok: Boolean!
|
||||
project: Project!
|
||||
}
|
||||
|
||||
|
||||
extend type Mutation {
|
||||
createProjectLabel(input: NewProjectLabel!): ProjectLabel!
|
||||
deleteProjectLabel(input: DeleteProjectLabel!): ProjectLabel!
|
||||
updateProjectLabel(input: UpdateProjectLabel!): ProjectLabel!
|
||||
updateProjectLabelName(input: UpdateProjectLabelName!): ProjectLabel!
|
||||
updateProjectLabelColor(input: UpdateProjectLabelColor!): ProjectLabel!
|
||||
}
|
||||
|
||||
input NewProjectLabel {
|
||||
@ -282,19 +235,88 @@ input UpdateProjectLabelColor {
|
||||
labelColorID: UUID!
|
||||
}
|
||||
|
||||
input ToggleTaskLabelInput {
|
||||
taskID: UUID!
|
||||
projectLabelID: UUID!
|
||||
extend type Mutation {
|
||||
createProjectMember(input: CreateProjectMember!): CreateProjectMemberPayload!
|
||||
deleteProjectMember(input: DeleteProjectMember!): DeleteProjectMemberPayload!
|
||||
updateProjectMemberRole(input: UpdateProjectMemberRole!): UpdateProjectMemberRolePayload!
|
||||
setProjectOwner(input: SetProjectOwner!): SetProjectOwnerPayload!
|
||||
}
|
||||
|
||||
type ToggleTaskLabelPayload {
|
||||
active: Boolean!
|
||||
task: Task!
|
||||
}
|
||||
|
||||
input UpdateProjectName {
|
||||
input CreateProjectMember {
|
||||
projectID: UUID!
|
||||
userID: UUID!
|
||||
}
|
||||
|
||||
type CreateProjectMemberPayload {
|
||||
ok: Boolean!
|
||||
member: Member!
|
||||
}
|
||||
|
||||
input DeleteProjectMember {
|
||||
projectID: UUID!
|
||||
userID: UUID!
|
||||
}
|
||||
|
||||
type DeleteProjectMemberPayload {
|
||||
ok: Boolean!
|
||||
member: Member!
|
||||
projectID: UUID!
|
||||
}
|
||||
|
||||
input UpdateProjectMemberRole {
|
||||
projectID: UUID!
|
||||
userID: UUID!
|
||||
roleCode: RoleCode!
|
||||
}
|
||||
|
||||
type UpdateProjectMemberRolePayload {
|
||||
ok: Boolean!
|
||||
member: Member!
|
||||
}
|
||||
|
||||
input SetProjectOwner {
|
||||
projectID: UUID!
|
||||
ownerID: UUID!
|
||||
}
|
||||
type SetProjectOwnerPayload {
|
||||
ok: Boolean!
|
||||
prevOwner: Member!
|
||||
newOwner: Member!
|
||||
}
|
||||
|
||||
extend type Mutation {
|
||||
createTask(input: NewTask!): Task!
|
||||
deleteTask(input: DeleteTaskInput!): DeleteTaskPayload!
|
||||
|
||||
updateTaskDescription(input: UpdateTaskDescriptionInput!): Task!
|
||||
updateTaskLocation(input: NewTaskLocation!): UpdateTaskLocationPayload!
|
||||
updateTaskName(input: UpdateTaskName!): Task!
|
||||
setTaskComplete(input: SetTaskComplete!): Task!
|
||||
updateTaskDueDate(input: UpdateTaskDueDate!): Task!
|
||||
|
||||
assignTask(input: AssignTaskInput): Task!
|
||||
unassignTask(input: UnassignTaskInput): Task!
|
||||
}
|
||||
|
||||
input NewTask {
|
||||
taskGroupID: String!
|
||||
name: String!
|
||||
position: Float!
|
||||
}
|
||||
|
||||
input AssignTaskInput {
|
||||
taskID: UUID!
|
||||
userID: UUID!
|
||||
}
|
||||
|
||||
input UnassignTaskInput {
|
||||
taskID: UUID!
|
||||
userID: UUID!
|
||||
}
|
||||
|
||||
input UpdateTaskDescriptionInput {
|
||||
taskID: UUID!
|
||||
description: String!
|
||||
}
|
||||
|
||||
type UpdateTaskLocationPayload {
|
||||
@ -302,11 +324,6 @@ type UpdateTaskLocationPayload {
|
||||
task: Task!
|
||||
}
|
||||
|
||||
input UpdateTaskGroupName {
|
||||
taskGroupID: UUID!
|
||||
name: String!
|
||||
}
|
||||
|
||||
input UpdateTaskDueDate {
|
||||
taskID: UUID!
|
||||
dueDate: Time
|
||||
@ -317,12 +334,46 @@ input SetTaskComplete {
|
||||
complete: Boolean!
|
||||
}
|
||||
|
||||
input NewTaskLocation {
|
||||
taskID: UUID!
|
||||
taskGroupID: UUID!
|
||||
position: Float!
|
||||
}
|
||||
|
||||
input DeleteTaskInput {
|
||||
taskID: String!
|
||||
}
|
||||
|
||||
type DeleteTaskPayload {
|
||||
taskID: String!
|
||||
}
|
||||
|
||||
input UpdateTaskName {
|
||||
taskID: String!
|
||||
name: String!
|
||||
}
|
||||
|
||||
extend type Mutation {
|
||||
createTaskChecklist(input: CreateTaskChecklist!): TaskChecklist!
|
||||
deleteTaskChecklist(input: DeleteTaskChecklist!): DeleteTaskChecklistPayload!
|
||||
updateTaskChecklistName(input: UpdateTaskChecklistName!): TaskChecklist!
|
||||
createTaskChecklistItem(input: CreateTaskChecklistItem!): TaskChecklistItem!
|
||||
updateTaskChecklistItemName(input: UpdateTaskChecklistItemName!): TaskChecklistItem!
|
||||
setTaskChecklistItemComplete(input: SetTaskChecklistItemComplete!): TaskChecklistItem!
|
||||
deleteTaskChecklistItem(input: DeleteTaskChecklistItem!): DeleteTaskChecklistItemPayload!
|
||||
}
|
||||
|
||||
input CreateTaskChecklist {
|
||||
taskID: UUID!
|
||||
name: String!
|
||||
position: Float!
|
||||
}
|
||||
|
||||
type DeleteTaskChecklistItemPayload {
|
||||
ok: Boolean!
|
||||
taskChecklistItem: TaskChecklistItem!
|
||||
}
|
||||
|
||||
input CreateTaskChecklistItem {
|
||||
taskChecklistID: UUID!
|
||||
name: String!
|
||||
@ -333,6 +384,7 @@ input SetTaskChecklistItemComplete {
|
||||
taskChecklistItemID: UUID!
|
||||
complete: Boolean!
|
||||
}
|
||||
|
||||
input DeleteTaskChecklistItem {
|
||||
taskChecklistItemID: UUID!
|
||||
}
|
||||
@ -342,44 +394,6 @@ input UpdateTaskChecklistItemName {
|
||||
name: String!
|
||||
}
|
||||
|
||||
input CreateTeamMember {
|
||||
userID: UUID!
|
||||
teamID: UUID!
|
||||
}
|
||||
|
||||
type CreateTeamMemberPayload {
|
||||
team: Team!
|
||||
teamMember: ProjectMember!
|
||||
}
|
||||
|
||||
input DeleteProject {
|
||||
projectID: UUID!
|
||||
}
|
||||
|
||||
type DeleteProjectPayload {
|
||||
ok: Boolean!
|
||||
project: Project!
|
||||
}
|
||||
|
||||
input DeleteTeam {
|
||||
teamID: UUID!
|
||||
}
|
||||
|
||||
type DeleteTeamPayload {
|
||||
ok: Boolean!
|
||||
team: Team!
|
||||
projects: [Project!]!
|
||||
}
|
||||
|
||||
input DeleteUserAccount {
|
||||
userID: UUID!
|
||||
}
|
||||
|
||||
type DeleteUserAccountPayload {
|
||||
ok: Boolean!
|
||||
userAccount: UserAccount!
|
||||
}
|
||||
|
||||
input UpdateTaskChecklistName {
|
||||
taskChecklistID: UUID!
|
||||
name: String!
|
||||
@ -391,54 +405,163 @@ type DeleteTaskChecklistPayload {
|
||||
ok: Boolean!
|
||||
taskChecklist: TaskChecklist!
|
||||
}
|
||||
type Mutation {
|
||||
createRefreshToken(input: NewRefreshToken!): RefreshToken!
|
||||
|
||||
createUserAccount(input: NewUserAccount!): UserAccount!
|
||||
deleteUserAccount(input: DeleteUserAccount!): DeleteUserAccountPayload!
|
||||
|
||||
deleteTeam(input: DeleteTeam!): DeleteTeamPayload!
|
||||
createTeam(input: NewTeam!): Team!
|
||||
clearProfileAvatar: UserAccount!
|
||||
|
||||
createTeamMember(input: CreateTeamMember!): CreateTeamMemberPayload!
|
||||
|
||||
createProject(input: NewProject!): Project!
|
||||
deleteProject(input: DeleteProject!): DeleteProjectPayload!
|
||||
updateProjectName(input: UpdateProjectName): Project!
|
||||
|
||||
createProjectLabel(input: NewProjectLabel!): ProjectLabel!
|
||||
deleteProjectLabel(input: DeleteProjectLabel!): ProjectLabel!
|
||||
updateProjectLabel(input: UpdateProjectLabel!): ProjectLabel!
|
||||
updateProjectLabelName(input: UpdateProjectLabelName!): ProjectLabel!
|
||||
updateProjectLabelColor(input: UpdateProjectLabelColor!): ProjectLabel!
|
||||
|
||||
extend type Mutation {
|
||||
createTaskGroup(input: NewTaskGroup!): TaskGroup!
|
||||
updateTaskGroupLocation(input: NewTaskGroupLocation!): TaskGroup!
|
||||
updateTaskGroupName(input: UpdateTaskGroupName!): TaskGroup!
|
||||
deleteTaskGroup(input: DeleteTaskGroupInput!): DeleteTaskGroupPayload!
|
||||
}
|
||||
|
||||
input NewTaskGroupLocation {
|
||||
taskGroupID: UUID!
|
||||
position: Float!
|
||||
}
|
||||
|
||||
input UpdateTaskGroupName {
|
||||
taskGroupID: UUID!
|
||||
name: String!
|
||||
}
|
||||
|
||||
input DeleteTaskGroupInput {
|
||||
taskGroupID: UUID!
|
||||
}
|
||||
|
||||
type DeleteTaskGroupPayload {
|
||||
ok: Boolean!
|
||||
affectedRows: Int!
|
||||
taskGroup: TaskGroup!
|
||||
}
|
||||
|
||||
input NewTaskGroup {
|
||||
projectID: String!
|
||||
name: String!
|
||||
position: Float!
|
||||
}
|
||||
|
||||
input AddTaskLabelInput {
|
||||
taskID: UUID!
|
||||
projectLabelID: UUID!
|
||||
}
|
||||
|
||||
input RemoveTaskLabelInput {
|
||||
taskLabelID: UUID!
|
||||
}
|
||||
input ToggleTaskLabelInput {
|
||||
taskID: UUID!
|
||||
projectLabelID: UUID!
|
||||
}
|
||||
|
||||
type ToggleTaskLabelPayload {
|
||||
active: Boolean!
|
||||
task: Task!
|
||||
}
|
||||
extend type Mutation {
|
||||
addTaskLabel(input: AddTaskLabelInput): Task!
|
||||
removeTaskLabel(input: RemoveTaskLabelInput): Task!
|
||||
toggleTaskLabel(input: ToggleTaskLabelInput!): ToggleTaskLabelPayload!
|
||||
|
||||
createTaskChecklist(input: CreateTaskChecklist!): TaskChecklist!
|
||||
deleteTaskChecklist(input: DeleteTaskChecklist!): DeleteTaskChecklistPayload!
|
||||
updateTaskChecklistName(input: UpdateTaskChecklistName!): TaskChecklist!
|
||||
createTaskChecklistItem(input: CreateTaskChecklistItem!): TaskChecklistItem!
|
||||
updateTaskChecklistItemName(input: UpdateTaskChecklistItemName!): TaskChecklistItem!
|
||||
setTaskChecklistItemComplete(input: SetTaskChecklistItemComplete!): TaskChecklistItem!
|
||||
deleteTaskChecklistItem(input: DeleteTaskChecklistItem!): DeleteTaskChecklistItemPayload!
|
||||
|
||||
createTask(input: NewTask!): Task!
|
||||
updateTaskDescription(input: UpdateTaskDescriptionInput!): Task!
|
||||
updateTaskLocation(input: NewTaskLocation!): UpdateTaskLocationPayload!
|
||||
updateTaskName(input: UpdateTaskName!): Task!
|
||||
setTaskComplete(input: SetTaskComplete!): Task!
|
||||
updateTaskDueDate(input: UpdateTaskDueDate!): Task!
|
||||
deleteTask(input: DeleteTaskInput!): DeleteTaskPayload!
|
||||
assignTask(input: AssignTaskInput): Task!
|
||||
unassignTask(input: UnassignTaskInput): Task!
|
||||
|
||||
logoutUser(input: LogoutUser!): Boolean!
|
||||
}
|
||||
|
||||
extend type Mutation {
|
||||
deleteTeam(input: DeleteTeam!): DeleteTeamPayload!
|
||||
createTeam(input: NewTeam!): Team!
|
||||
}
|
||||
|
||||
input NewTeam {
|
||||
name: String!
|
||||
organizationID: UUID!
|
||||
}
|
||||
|
||||
input DeleteTeam {
|
||||
teamID: UUID!
|
||||
}
|
||||
|
||||
type DeleteTeamPayload {
|
||||
ok: Boolean!
|
||||
team: Team!
|
||||
projects: [Project!]!
|
||||
}
|
||||
|
||||
extend type Mutation {
|
||||
setTeamOwner(input: SetTeamOwner!): SetTeamOwnerPayload!
|
||||
createTeamMember(input: CreateTeamMember!): CreateTeamMemberPayload!
|
||||
updateTeamMemberRole(input: UpdateTeamMemberRole!): UpdateTeamMemberRolePayload!
|
||||
deleteTeamMember(input: DeleteTeamMember!): DeleteTeamMemberPayload!
|
||||
}
|
||||
|
||||
input DeleteTeamMember {
|
||||
teamID: UUID!
|
||||
userID: UUID!
|
||||
}
|
||||
|
||||
type DeleteTeamMemberPayload {
|
||||
teamID: UUID!
|
||||
userID: UUID!
|
||||
}
|
||||
|
||||
input CreateTeamMember {
|
||||
userID: UUID!
|
||||
teamID: UUID!
|
||||
}
|
||||
|
||||
type CreateTeamMemberPayload {
|
||||
team: Team!
|
||||
teamMember: Member!
|
||||
}
|
||||
|
||||
input UpdateTeamMemberRole {
|
||||
teamID: UUID!
|
||||
userID: UUID!
|
||||
roleCode: RoleCode!
|
||||
}
|
||||
|
||||
type UpdateTeamMemberRolePayload {
|
||||
ok: Boolean!
|
||||
member: Member!
|
||||
}
|
||||
|
||||
input SetTeamOwner {
|
||||
teamID: UUID!
|
||||
userID: UUID!
|
||||
}
|
||||
|
||||
type SetTeamOwnerPayload {
|
||||
ok: Boolean!
|
||||
prevOwner: Member!
|
||||
newOwner: Member!
|
||||
}
|
||||
|
||||
extend type Mutation {
|
||||
createRefreshToken(input: NewRefreshToken!): RefreshToken!
|
||||
createUserAccount(input: NewUserAccount!): UserAccount!
|
||||
deleteUserAccount(input: DeleteUserAccount!): DeleteUserAccountPayload!
|
||||
logoutUser(input: LogoutUser!): Boolean!
|
||||
clearProfileAvatar: UserAccount!
|
||||
}
|
||||
|
||||
input NewRefreshToken {
|
||||
userId: String!
|
||||
}
|
||||
|
||||
input NewUserAccount {
|
||||
username: String!
|
||||
email: String!
|
||||
fullName: String!
|
||||
initials: String!
|
||||
password: String!
|
||||
roleCode: String!
|
||||
}
|
||||
|
||||
input LogoutUser {
|
||||
userID: String!
|
||||
}
|
||||
|
||||
input DeleteUserAccount {
|
||||
userID: UUID!
|
||||
}
|
||||
|
||||
type DeleteUserAccountPayload {
|
||||
ok: Boolean!
|
||||
userAccount: UserAccount!
|
||||
}
|
||||
|
560
api/internal/graph/schema.graphqls.bak
Normal file
560
api/internal/graph/schema.graphqls.bak
Normal file
@ -0,0 +1,560 @@
|
||||
scalar Time
|
||||
scalar UUID
|
||||
scalar Upload
|
||||
|
||||
enum RoleCode {
|
||||
owner
|
||||
admin
|
||||
member
|
||||
observer
|
||||
}
|
||||
|
||||
type ProjectLabel {
|
||||
id: ID!
|
||||
createdDate: Time!
|
||||
labelColor: LabelColor!
|
||||
name: String
|
||||
}
|
||||
|
||||
type LabelColor {
|
||||
id: ID!
|
||||
name: String!
|
||||
position: Float!
|
||||
colorHex: String!
|
||||
}
|
||||
|
||||
type TaskLabel {
|
||||
id: ID!
|
||||
projectLabel: ProjectLabel!
|
||||
assignedDate: Time!
|
||||
}
|
||||
|
||||
type ProfileIcon {
|
||||
url: String
|
||||
initials: String
|
||||
bgColor: String
|
||||
}
|
||||
|
||||
type Member {
|
||||
id: ID!
|
||||
role: Role!
|
||||
fullName: String!
|
||||
username: String!
|
||||
profileIcon: ProfileIcon!
|
||||
}
|
||||
|
||||
type RefreshToken {
|
||||
id: ID!
|
||||
userId: UUID!
|
||||
expiresAt: Time!
|
||||
createdAt: Time!
|
||||
}
|
||||
|
||||
type Role {
|
||||
code: String!
|
||||
name: String!
|
||||
}
|
||||
|
||||
type UserAccount {
|
||||
id: ID!
|
||||
email: String!
|
||||
createdAt: Time!
|
||||
fullName: String!
|
||||
initials: String!
|
||||
role: Role!
|
||||
username: String!
|
||||
profileIcon: ProfileIcon!
|
||||
}
|
||||
|
||||
type Team {
|
||||
id: ID!
|
||||
createdAt: Time!
|
||||
name: String!
|
||||
members: [Member!]!
|
||||
}
|
||||
|
||||
type Project {
|
||||
id: ID!
|
||||
createdAt: Time!
|
||||
name: String!
|
||||
team: Team!
|
||||
owner: Member!
|
||||
taskGroups: [TaskGroup!]!
|
||||
members: [Member!]!
|
||||
labels: [ProjectLabel!]!
|
||||
}
|
||||
|
||||
type TaskGroup {
|
||||
id: ID!
|
||||
projectID: String!
|
||||
createdAt: Time!
|
||||
name: String!
|
||||
position: Float!
|
||||
tasks: [Task!]!
|
||||
}
|
||||
|
||||
type ChecklistBadge {
|
||||
complete: Int!
|
||||
total: Int!
|
||||
}
|
||||
|
||||
type TaskBadges {
|
||||
checklist: ChecklistBadge
|
||||
}
|
||||
|
||||
type Task {
|
||||
id: ID!
|
||||
taskGroup: TaskGroup!
|
||||
createdAt: Time!
|
||||
name: String!
|
||||
position: Float!
|
||||
description: String
|
||||
dueDate: Time
|
||||
complete: Boolean!
|
||||
assigned: [Member!]!
|
||||
labels: [TaskLabel!]!
|
||||
checklists: [TaskChecklist!]!
|
||||
badges: TaskBadges!
|
||||
}
|
||||
|
||||
input ProjectsFilter {
|
||||
teamID: UUID
|
||||
}
|
||||
|
||||
input FindUser {
|
||||
userId: String!
|
||||
}
|
||||
|
||||
input FindProject {
|
||||
projectId: String!
|
||||
}
|
||||
|
||||
input FindTask {
|
||||
taskID: UUID!
|
||||
}
|
||||
|
||||
type Organization {
|
||||
id: ID!
|
||||
name: String!
|
||||
}
|
||||
|
||||
|
||||
input ProjectsFilter {
|
||||
teamID: UUID
|
||||
}
|
||||
|
||||
input FindUser {
|
||||
userId: String!
|
||||
}
|
||||
|
||||
input FindProject {
|
||||
projectId: String!
|
||||
}
|
||||
|
||||
input FindTask {
|
||||
taskID: UUID!
|
||||
}
|
||||
|
||||
type Organization {
|
||||
id: ID!
|
||||
name: String!
|
||||
}
|
||||
|
||||
input FindTeam {
|
||||
teamID: UUID!
|
||||
}
|
||||
|
||||
type Query {
|
||||
organizations: [Organization!]!
|
||||
users: [UserAccount!]!
|
||||
findUser(input: FindUser!): UserAccount!
|
||||
findProject(input: FindProject!): Project!
|
||||
findTask(input: FindTask!): Task!
|
||||
projects(input: ProjectsFilter): [Project!]!
|
||||
findTeam(input: FindTeam!): Team!
|
||||
teams: [Team!]!
|
||||
labelColors: [LabelColor!]!
|
||||
taskGroups: [TaskGroup!]!
|
||||
me: UserAccount!
|
||||
}
|
||||
|
||||
type Mutation {}
|
||||
|
||||
extend type Mutation {
|
||||
createTask(input: NewTask!): Task!
|
||||
deleteTask(input: DeleteTaskInput!): DeleteTaskPayload!
|
||||
|
||||
updateTaskDescription(input: UpdateTaskDescriptionInput!): Task!
|
||||
updateTaskLocation(input: NewTaskLocation!): UpdateTaskLocationPayload!
|
||||
updateTaskName(input: UpdateTaskName!): Task!
|
||||
setTaskComplete(input: SetTaskComplete!): Task!
|
||||
updateTaskDueDate(input: UpdateTaskDueDate!): Task!
|
||||
|
||||
assignTask(input: AssignTaskInput): Task!
|
||||
unassignTask(input: UnassignTaskInput): Task!
|
||||
}
|
||||
|
||||
input NewRefreshToken {
|
||||
userId: String!
|
||||
}
|
||||
|
||||
input NewUserAccount {
|
||||
username: String!
|
||||
email: String!
|
||||
fullName: String!
|
||||
initials: String!
|
||||
password: String!
|
||||
roleCode: String!
|
||||
}
|
||||
|
||||
input NewTeam {
|
||||
name: String!
|
||||
organizationID: UUID!
|
||||
}
|
||||
|
||||
input NewProject {
|
||||
userID: UUID!
|
||||
teamID: UUID!
|
||||
name: String!
|
||||
}
|
||||
|
||||
input NewTaskGroup {
|
||||
projectID: String!
|
||||
name: String!
|
||||
position: Float!
|
||||
}
|
||||
|
||||
input LogoutUser {
|
||||
userID: String!
|
||||
}
|
||||
input NewTask {
|
||||
taskGroupID: String!
|
||||
name: String!
|
||||
position: Float!
|
||||
}
|
||||
input NewTaskLocation {
|
||||
taskID: UUID!
|
||||
taskGroupID: UUID!
|
||||
position: Float!
|
||||
}
|
||||
|
||||
input DeleteTaskInput {
|
||||
taskID: String!
|
||||
}
|
||||
|
||||
type DeleteTaskPayload {
|
||||
taskID: String!
|
||||
}
|
||||
|
||||
input UpdateTaskName {
|
||||
taskID: String!
|
||||
name: String!
|
||||
}
|
||||
|
||||
input NewTaskGroupLocation {
|
||||
taskGroupID: UUID!
|
||||
position: Float!
|
||||
}
|
||||
|
||||
input DeleteTaskGroupInput {
|
||||
taskGroupID: UUID!
|
||||
}
|
||||
|
||||
type DeleteTaskGroupPayload {
|
||||
ok: Boolean!
|
||||
affectedRows: Int!
|
||||
taskGroup: TaskGroup!
|
||||
}
|
||||
|
||||
type DeleteTaskChecklistItemPayload {
|
||||
ok: Boolean!
|
||||
taskChecklistItem: TaskChecklistItem!
|
||||
}
|
||||
|
||||
type TaskChecklistItem {
|
||||
id: ID!
|
||||
name: String!
|
||||
taskChecklistID: UUID!
|
||||
complete: Boolean!
|
||||
position: Float!
|
||||
dueDate: Time!
|
||||
}
|
||||
|
||||
type TaskChecklist {
|
||||
id: ID!
|
||||
name: String!
|
||||
position: Float!
|
||||
items: [TaskChecklistItem!]!
|
||||
}
|
||||
|
||||
input AssignTaskInput {
|
||||
taskID: UUID!
|
||||
userID: UUID!
|
||||
}
|
||||
|
||||
input UnassignTaskInput {
|
||||
taskID: UUID!
|
||||
userID: UUID!
|
||||
}
|
||||
input UpdateTaskDescriptionInput {
|
||||
taskID: UUID!
|
||||
description: String!
|
||||
}
|
||||
|
||||
input AddTaskLabelInput {
|
||||
taskID: UUID!
|
||||
projectLabelID: UUID!
|
||||
}
|
||||
|
||||
input RemoveTaskLabelInput {
|
||||
taskLabelID: UUID!
|
||||
}
|
||||
|
||||
input NewProjectLabel {
|
||||
projectID: UUID!
|
||||
labelColorID: UUID!
|
||||
name: String
|
||||
}
|
||||
|
||||
input DeleteProjectLabel {
|
||||
projectLabelID: UUID!
|
||||
}
|
||||
|
||||
input UpdateProjectLabelName {
|
||||
projectLabelID: UUID!
|
||||
name: String!
|
||||
}
|
||||
|
||||
input UpdateProjectLabel {
|
||||
projectLabelID: UUID!
|
||||
labelColorID: UUID!
|
||||
name: String!
|
||||
}
|
||||
|
||||
input UpdateProjectLabelColor {
|
||||
projectLabelID: UUID!
|
||||
labelColorID: UUID!
|
||||
}
|
||||
|
||||
input ToggleTaskLabelInput {
|
||||
taskID: UUID!
|
||||
projectLabelID: UUID!
|
||||
}
|
||||
|
||||
type ToggleTaskLabelPayload {
|
||||
active: Boolean!
|
||||
task: Task!
|
||||
}
|
||||
|
||||
input UpdateProjectName {
|
||||
projectID: UUID!
|
||||
name: String!
|
||||
}
|
||||
|
||||
type UpdateTaskLocationPayload {
|
||||
previousTaskGroupID: UUID!
|
||||
task: Task!
|
||||
}
|
||||
|
||||
input UpdateTaskGroupName {
|
||||
taskGroupID: UUID!
|
||||
name: String!
|
||||
}
|
||||
|
||||
input UpdateTaskDueDate {
|
||||
taskID: UUID!
|
||||
dueDate: Time
|
||||
}
|
||||
|
||||
input SetTaskComplete {
|
||||
taskID: UUID!
|
||||
complete: Boolean!
|
||||
}
|
||||
|
||||
input CreateTaskChecklist {
|
||||
taskID: UUID!
|
||||
name: String!
|
||||
position: Float!
|
||||
}
|
||||
|
||||
input CreateTaskChecklistItem {
|
||||
taskChecklistID: UUID!
|
||||
name: String!
|
||||
position: Float!
|
||||
}
|
||||
|
||||
input SetTaskChecklistItemComplete {
|
||||
taskChecklistItemID: UUID!
|
||||
complete: Boolean!
|
||||
}
|
||||
input DeleteTaskChecklistItem {
|
||||
taskChecklistItemID: UUID!
|
||||
}
|
||||
|
||||
input UpdateTaskChecklistItemName {
|
||||
taskChecklistItemID: UUID!
|
||||
name: String!
|
||||
}
|
||||
|
||||
input CreateTeamMember {
|
||||
userID: UUID!
|
||||
teamID: UUID!
|
||||
}
|
||||
|
||||
type CreateTeamMemberPayload {
|
||||
team: Team!
|
||||
teamMember: Member!
|
||||
}
|
||||
|
||||
input DeleteProject {
|
||||
projectID: UUID!
|
||||
}
|
||||
|
||||
type DeleteProjectPayload {
|
||||
ok: Boolean!
|
||||
project: Project!
|
||||
}
|
||||
|
||||
input DeleteTeam {
|
||||
teamID: UUID!
|
||||
}
|
||||
|
||||
type DeleteTeamPayload {
|
||||
ok: Boolean!
|
||||
team: Team!
|
||||
projects: [Project!]!
|
||||
}
|
||||
|
||||
input DeleteUserAccount {
|
||||
userID: UUID!
|
||||
}
|
||||
|
||||
type DeleteUserAccountPayload {
|
||||
ok: Boolean!
|
||||
userAccount: UserAccount!
|
||||
}
|
||||
|
||||
input UpdateTaskChecklistName {
|
||||
taskChecklistID: UUID!
|
||||
name: String!
|
||||
}
|
||||
input DeleteTaskChecklist {
|
||||
taskChecklistID: UUID!
|
||||
}
|
||||
type DeleteTaskChecklistPayload {
|
||||
ok: Boolean!
|
||||
taskChecklist: TaskChecklist!
|
||||
}
|
||||
|
||||
input CreateProjectMember {
|
||||
projectID: UUID!
|
||||
userID: UUID!
|
||||
}
|
||||
|
||||
type CreateProjectMemberPayload {
|
||||
ok: Boolean!
|
||||
member: Member!
|
||||
}
|
||||
|
||||
input DeleteProjectMember {
|
||||
projectID: UUID!
|
||||
userID: UUID!
|
||||
}
|
||||
|
||||
type DeleteProjectMemberPayload {
|
||||
ok: Boolean!
|
||||
member: Member!
|
||||
projectID: UUID!
|
||||
}
|
||||
|
||||
input UpdateProjectMemberRole {
|
||||
projectID: UUID!
|
||||
userID: UUID!
|
||||
roleCode: RoleCode!
|
||||
}
|
||||
|
||||
type UpdateProjectMemberRolePayload {
|
||||
ok: Boolean!
|
||||
member: Member!
|
||||
}
|
||||
|
||||
input SetProjectOwner {
|
||||
projectID: UUID!
|
||||
ownerID: UUID!
|
||||
}
|
||||
type SetProjectOwnerPayload {
|
||||
ok: Boolean!
|
||||
prevOwner: Member!
|
||||
newOwner: Member!
|
||||
}
|
||||
|
||||
input UpdateTeamMemberRole {
|
||||
teamID: UUID!
|
||||
userID: UUID!
|
||||
roleCode: RoleCode!
|
||||
}
|
||||
|
||||
type UpdateTeamMemberRolePayload {
|
||||
ok: Boolean!
|
||||
member: Member!
|
||||
}
|
||||
|
||||
input SetTeamOwner {
|
||||
teamID: UUID!
|
||||
userID: UUID!
|
||||
}
|
||||
|
||||
type SetTeamOwnerPayload {
|
||||
ok: Boolean!
|
||||
prevOwner: Member!
|
||||
newOwner: Member!
|
||||
}
|
||||
|
||||
type Mutation {
|
||||
createRefreshToken(input: NewRefreshToken!): RefreshToken!
|
||||
|
||||
createUserAccount(input: NewUserAccount!): UserAccount!
|
||||
deleteUserAccount(input: DeleteUserAccount!): DeleteUserAccountPayload!
|
||||
|
||||
deleteTeam(input: DeleteTeam!): DeleteTeamPayload!
|
||||
createTeam(input: NewTeam!): Team!
|
||||
clearProfileAvatar: UserAccount!
|
||||
|
||||
createTeamMember(input: CreateTeamMember!): CreateTeamMemberPayload!
|
||||
updateTeamMemberRole(input: UpdateTeamMemberRole!): UpdateTeamMemberRolePayload!
|
||||
setTeamOwner(input: SetTeamOwner!): SetTeamOwnerPayload!
|
||||
|
||||
createProject(input: NewProject!): Project!
|
||||
deleteProject(input: DeleteProject!): DeleteProjectPayload!
|
||||
updateProjectName(input: UpdateProjectName): Project!
|
||||
createProjectMember(input: CreateProjectMember!): CreateProjectMemberPayload!
|
||||
deleteProjectMember(input: DeleteProjectMember!): DeleteProjectMemberPayload!
|
||||
updateProjectMemberRole(input: UpdateProjectMemberRole!): UpdateProjectMemberRolePayload!
|
||||
setProjectOwner(input: SetProjectOwner!): SetProjectOwnerPayload!
|
||||
|
||||
createProjectLabel(input: NewProjectLabel!): ProjectLabel!
|
||||
deleteProjectLabel(input: DeleteProjectLabel!): ProjectLabel!
|
||||
updateProjectLabel(input: UpdateProjectLabel!): ProjectLabel!
|
||||
updateProjectLabelName(input: UpdateProjectLabelName!): ProjectLabel!
|
||||
updateProjectLabelColor(input: UpdateProjectLabelColor!): ProjectLabel!
|
||||
|
||||
createTaskGroup(input: NewTaskGroup!): TaskGroup!
|
||||
updateTaskGroupLocation(input: NewTaskGroupLocation!): TaskGroup!
|
||||
updateTaskGroupName(input: UpdateTaskGroupName!): TaskGroup!
|
||||
deleteTaskGroup(input: DeleteTaskGroupInput!): DeleteTaskGroupPayload!
|
||||
|
||||
addTaskLabel(input: AddTaskLabelInput): Task!
|
||||
removeTaskLabel(input: RemoveTaskLabelInput): Task!
|
||||
toggleTaskLabel(input: ToggleTaskLabelInput!): ToggleTaskLabelPayload!
|
||||
|
||||
createTaskChecklist(input: CreateTaskChecklist!): TaskChecklist!
|
||||
deleteTaskChecklist(input: DeleteTaskChecklist!): DeleteTaskChecklistPayload!
|
||||
updateTaskChecklistName(input: UpdateTaskChecklistName!): TaskChecklist!
|
||||
createTaskChecklistItem(input: CreateTaskChecklistItem!): TaskChecklistItem!
|
||||
updateTaskChecklistItemName(input: UpdateTaskChecklistItemName!): TaskChecklistItem!
|
||||
setTaskChecklistItemComplete(input: SetTaskChecklistItemComplete!): TaskChecklistItem!
|
||||
deleteTaskChecklistItem(input: DeleteTaskChecklistItem!): DeleteTaskChecklistItemPayload!
|
||||
|
||||
logoutUser(input: LogoutUser!): Boolean!
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
139
api/internal/graph/schema/_models.gql
Normal file
139
api/internal/graph/schema/_models.gql
Normal file
@ -0,0 +1,139 @@
|
||||
scalar Time
|
||||
scalar UUID
|
||||
scalar Upload
|
||||
|
||||
enum RoleCode {
|
||||
owner
|
||||
admin
|
||||
member
|
||||
observer
|
||||
}
|
||||
|
||||
type ProjectLabel {
|
||||
id: ID!
|
||||
createdDate: Time!
|
||||
labelColor: LabelColor!
|
||||
name: String
|
||||
}
|
||||
|
||||
type LabelColor {
|
||||
id: ID!
|
||||
name: String!
|
||||
position: Float!
|
||||
colorHex: String!
|
||||
}
|
||||
|
||||
type TaskLabel {
|
||||
id: ID!
|
||||
projectLabel: ProjectLabel!
|
||||
assignedDate: Time!
|
||||
}
|
||||
|
||||
type ProfileIcon {
|
||||
url: String
|
||||
initials: String
|
||||
bgColor: String
|
||||
}
|
||||
|
||||
type Member {
|
||||
id: ID!
|
||||
role: Role!
|
||||
fullName: String!
|
||||
username: String!
|
||||
profileIcon: ProfileIcon!
|
||||
}
|
||||
|
||||
type RefreshToken {
|
||||
id: ID!
|
||||
userId: UUID!
|
||||
expiresAt: Time!
|
||||
createdAt: Time!
|
||||
}
|
||||
|
||||
type Role {
|
||||
code: String!
|
||||
name: String!
|
||||
}
|
||||
|
||||
type UserAccount {
|
||||
id: ID!
|
||||
email: String!
|
||||
createdAt: Time!
|
||||
fullName: String!
|
||||
initials: String!
|
||||
role: Role!
|
||||
username: String!
|
||||
profileIcon: ProfileIcon!
|
||||
}
|
||||
|
||||
type Team {
|
||||
id: ID!
|
||||
createdAt: Time!
|
||||
name: String!
|
||||
members: [Member!]!
|
||||
}
|
||||
|
||||
type Project {
|
||||
id: ID!
|
||||
createdAt: Time!
|
||||
name: String!
|
||||
team: Team!
|
||||
owner: Member!
|
||||
taskGroups: [TaskGroup!]!
|
||||
members: [Member!]!
|
||||
labels: [ProjectLabel!]!
|
||||
}
|
||||
|
||||
type TaskGroup {
|
||||
id: ID!
|
||||
projectID: String!
|
||||
createdAt: Time!
|
||||
name: String!
|
||||
position: Float!
|
||||
tasks: [Task!]!
|
||||
}
|
||||
|
||||
type ChecklistBadge {
|
||||
complete: Int!
|
||||
total: Int!
|
||||
}
|
||||
|
||||
type TaskBadges {
|
||||
checklist: ChecklistBadge
|
||||
}
|
||||
|
||||
type Task {
|
||||
id: ID!
|
||||
taskGroup: TaskGroup!
|
||||
createdAt: Time!
|
||||
name: String!
|
||||
position: Float!
|
||||
description: String
|
||||
dueDate: Time
|
||||
complete: Boolean!
|
||||
assigned: [Member!]!
|
||||
labels: [TaskLabel!]!
|
||||
checklists: [TaskChecklist!]!
|
||||
badges: TaskBadges!
|
||||
}
|
||||
|
||||
type Organization {
|
||||
id: ID!
|
||||
name: String!
|
||||
}
|
||||
|
||||
type TaskChecklistItem {
|
||||
id: ID!
|
||||
name: String!
|
||||
taskChecklistID: UUID!
|
||||
complete: Boolean!
|
||||
position: Float!
|
||||
dueDate: Time!
|
||||
}
|
||||
|
||||
type TaskChecklist {
|
||||
id: ID!
|
||||
name: String!
|
||||
position: Float!
|
||||
items: [TaskChecklistItem!]!
|
||||
}
|
35
api/internal/graph/schema/_root.gql
Normal file
35
api/internal/graph/schema/_root.gql
Normal file
@ -0,0 +1,35 @@
|
||||
type Query {
|
||||
organizations: [Organization!]!
|
||||
users: [UserAccount!]!
|
||||
findUser(input: FindUser!): UserAccount!
|
||||
findProject(input: FindProject!): Project!
|
||||
findTask(input: FindTask!): Task!
|
||||
projects(input: ProjectsFilter): [Project!]!
|
||||
findTeam(input: FindTeam!): Team!
|
||||
teams: [Team!]!
|
||||
labelColors: [LabelColor!]!
|
||||
taskGroups: [TaskGroup!]!
|
||||
me: UserAccount!
|
||||
}
|
||||
|
||||
type Mutation
|
||||
|
||||
input ProjectsFilter {
|
||||
teamID: UUID
|
||||
}
|
||||
|
||||
input FindUser {
|
||||
userId: String!
|
||||
}
|
||||
|
||||
input FindProject {
|
||||
projectId: String!
|
||||
}
|
||||
|
||||
input FindTask {
|
||||
taskID: UUID!
|
||||
}
|
||||
|
||||
input FindTeam {
|
||||
teamID: UUID!
|
||||
}
|
26
api/internal/graph/schema/project.gql
Normal file
26
api/internal/graph/schema/project.gql
Normal file
@ -0,0 +1,26 @@
|
||||
extend type Mutation {
|
||||
createProject(input: NewProject!): Project!
|
||||
deleteProject(input: DeleteProject!): DeleteProjectPayload!
|
||||
updateProjectName(input: UpdateProjectName): Project!
|
||||
}
|
||||
|
||||
input NewProject {
|
||||
userID: UUID!
|
||||
teamID: UUID!
|
||||
name: String!
|
||||
}
|
||||
|
||||
input UpdateProjectName {
|
||||
projectID: UUID!
|
||||
name: String!
|
||||
}
|
||||
|
||||
input DeleteProject {
|
||||
projectID: UUID!
|
||||
}
|
||||
|
||||
type DeleteProjectPayload {
|
||||
ok: Boolean!
|
||||
project: Project!
|
||||
}
|
||||
|
33
api/internal/graph/schema/project_label.gql
Normal file
33
api/internal/graph/schema/project_label.gql
Normal file
@ -0,0 +1,33 @@
|
||||
extend type Mutation {
|
||||
createProjectLabel(input: NewProjectLabel!): ProjectLabel!
|
||||
deleteProjectLabel(input: DeleteProjectLabel!): ProjectLabel!
|
||||
updateProjectLabel(input: UpdateProjectLabel!): ProjectLabel!
|
||||
updateProjectLabelName(input: UpdateProjectLabelName!): ProjectLabel!
|
||||
updateProjectLabelColor(input: UpdateProjectLabelColor!): ProjectLabel!
|
||||
}
|
||||
|
||||
input NewProjectLabel {
|
||||
projectID: UUID!
|
||||
labelColorID: UUID!
|
||||
name: String
|
||||
}
|
||||
|
||||
input DeleteProjectLabel {
|
||||
projectLabelID: UUID!
|
||||
}
|
||||
|
||||
input UpdateProjectLabelName {
|
||||
projectLabelID: UUID!
|
||||
name: String!
|
||||
}
|
||||
|
||||
input UpdateProjectLabel {
|
||||
projectLabelID: UUID!
|
||||
labelColorID: UUID!
|
||||
name: String!
|
||||
}
|
||||
|
||||
input UpdateProjectLabelColor {
|
||||
projectLabelID: UUID!
|
||||
labelColorID: UUID!
|
||||
}
|
48
api/internal/graph/schema/project_member.gql
Normal file
48
api/internal/graph/schema/project_member.gql
Normal file
@ -0,0 +1,48 @@
|
||||
extend type Mutation {
|
||||
createProjectMember(input: CreateProjectMember!): CreateProjectMemberPayload!
|
||||
deleteProjectMember(input: DeleteProjectMember!): DeleteProjectMemberPayload!
|
||||
updateProjectMemberRole(input: UpdateProjectMemberRole!): UpdateProjectMemberRolePayload!
|
||||
setProjectOwner(input: SetProjectOwner!): SetProjectOwnerPayload!
|
||||
}
|
||||
|
||||
input CreateProjectMember {
|
||||
projectID: UUID!
|
||||
userID: UUID!
|
||||
}
|
||||
|
||||
type CreateProjectMemberPayload {
|
||||
ok: Boolean!
|
||||
member: Member!
|
||||
}
|
||||
|
||||
input DeleteProjectMember {
|
||||
projectID: UUID!
|
||||
userID: UUID!
|
||||
}
|
||||
|
||||
type DeleteProjectMemberPayload {
|
||||
ok: Boolean!
|
||||
member: Member!
|
||||
projectID: UUID!
|
||||
}
|
||||
|
||||
input UpdateProjectMemberRole {
|
||||
projectID: UUID!
|
||||
userID: UUID!
|
||||
roleCode: RoleCode!
|
||||
}
|
||||
|
||||
type UpdateProjectMemberRolePayload {
|
||||
ok: Boolean!
|
||||
member: Member!
|
||||
}
|
||||
|
||||
input SetProjectOwner {
|
||||
projectID: UUID!
|
||||
ownerID: UUID!
|
||||
}
|
||||
type SetProjectOwnerPayload {
|
||||
ok: Boolean!
|
||||
prevOwner: Member!
|
||||
newOwner: Member!
|
||||
}
|
68
api/internal/graph/schema/task.gql
Normal file
68
api/internal/graph/schema/task.gql
Normal file
@ -0,0 +1,68 @@
|
||||
extend type Mutation {
|
||||
createTask(input: NewTask!): Task!
|
||||
deleteTask(input: DeleteTaskInput!): DeleteTaskPayload!
|
||||
|
||||
updateTaskDescription(input: UpdateTaskDescriptionInput!): Task!
|
||||
updateTaskLocation(input: NewTaskLocation!): UpdateTaskLocationPayload!
|
||||
updateTaskName(input: UpdateTaskName!): Task!
|
||||
setTaskComplete(input: SetTaskComplete!): Task!
|
||||
updateTaskDueDate(input: UpdateTaskDueDate!): Task!
|
||||
|
||||
assignTask(input: AssignTaskInput): Task!
|
||||
unassignTask(input: UnassignTaskInput): Task!
|
||||
}
|
||||
|
||||
input NewTask {
|
||||
taskGroupID: String!
|
||||
name: String!
|
||||
position: Float!
|
||||
}
|
||||
|
||||
input AssignTaskInput {
|
||||
taskID: UUID!
|
||||
userID: UUID!
|
||||
}
|
||||
|
||||
input UnassignTaskInput {
|
||||
taskID: UUID!
|
||||
userID: UUID!
|
||||
}
|
||||
|
||||
input UpdateTaskDescriptionInput {
|
||||
taskID: UUID!
|
||||
description: String!
|
||||
}
|
||||
|
||||
type UpdateTaskLocationPayload {
|
||||
previousTaskGroupID: UUID!
|
||||
task: Task!
|
||||
}
|
||||
|
||||
input UpdateTaskDueDate {
|
||||
taskID: UUID!
|
||||
dueDate: Time
|
||||
}
|
||||
|
||||
input SetTaskComplete {
|
||||
taskID: UUID!
|
||||
complete: Boolean!
|
||||
}
|
||||
|
||||
input NewTaskLocation {
|
||||
taskID: UUID!
|
||||
taskGroupID: UUID!
|
||||
position: Float!
|
||||
}
|
||||
|
||||
input DeleteTaskInput {
|
||||
taskID: String!
|
||||
}
|
||||
|
||||
type DeleteTaskPayload {
|
||||
taskID: String!
|
||||
}
|
||||
|
||||
input UpdateTaskName {
|
||||
taskID: String!
|
||||
name: String!
|
||||
}
|
52
api/internal/graph/schema/task_checklist.gql
Normal file
52
api/internal/graph/schema/task_checklist.gql
Normal file
@ -0,0 +1,52 @@
|
||||
extend type Mutation {
|
||||
createTaskChecklist(input: CreateTaskChecklist!): TaskChecklist!
|
||||
deleteTaskChecklist(input: DeleteTaskChecklist!): DeleteTaskChecklistPayload!
|
||||
updateTaskChecklistName(input: UpdateTaskChecklistName!): TaskChecklist!
|
||||
createTaskChecklistItem(input: CreateTaskChecklistItem!): TaskChecklistItem!
|
||||
updateTaskChecklistItemName(input: UpdateTaskChecklistItemName!): TaskChecklistItem!
|
||||
setTaskChecklistItemComplete(input: SetTaskChecklistItemComplete!): TaskChecklistItem!
|
||||
deleteTaskChecklistItem(input: DeleteTaskChecklistItem!): DeleteTaskChecklistItemPayload!
|
||||
}
|
||||
|
||||
input CreateTaskChecklist {
|
||||
taskID: UUID!
|
||||
name: String!
|
||||
position: Float!
|
||||
}
|
||||
|
||||
type DeleteTaskChecklistItemPayload {
|
||||
ok: Boolean!
|
||||
taskChecklistItem: TaskChecklistItem!
|
||||
}
|
||||
|
||||
input CreateTaskChecklistItem {
|
||||
taskChecklistID: UUID!
|
||||
name: String!
|
||||
position: Float!
|
||||
}
|
||||
|
||||
input SetTaskChecklistItemComplete {
|
||||
taskChecklistItemID: UUID!
|
||||
complete: Boolean!
|
||||
}
|
||||
|
||||
input DeleteTaskChecklistItem {
|
||||
taskChecklistItemID: UUID!
|
||||
}
|
||||
|
||||
input UpdateTaskChecklistItemName {
|
||||
taskChecklistItemID: UUID!
|
||||
name: String!
|
||||
}
|
||||
|
||||
input UpdateTaskChecklistName {
|
||||
taskChecklistID: UUID!
|
||||
name: String!
|
||||
}
|
||||
input DeleteTaskChecklist {
|
||||
taskChecklistID: UUID!
|
||||
}
|
||||
type DeleteTaskChecklistPayload {
|
||||
ok: Boolean!
|
||||
taskChecklist: TaskChecklist!
|
||||
}
|
32
api/internal/graph/schema/task_group.gql
Normal file
32
api/internal/graph/schema/task_group.gql
Normal file
@ -0,0 +1,32 @@
|
||||
extend type Mutation {
|
||||
createTaskGroup(input: NewTaskGroup!): TaskGroup!
|
||||
updateTaskGroupLocation(input: NewTaskGroupLocation!): TaskGroup!
|
||||
updateTaskGroupName(input: UpdateTaskGroupName!): TaskGroup!
|
||||
deleteTaskGroup(input: DeleteTaskGroupInput!): DeleteTaskGroupPayload!
|
||||
}
|
||||
|
||||
input NewTaskGroupLocation {
|
||||
taskGroupID: UUID!
|
||||
position: Float!
|
||||
}
|
||||
|
||||
input UpdateTaskGroupName {
|
||||
taskGroupID: UUID!
|
||||
name: String!
|
||||
}
|
||||
|
||||
input DeleteTaskGroupInput {
|
||||
taskGroupID: UUID!
|
||||
}
|
||||
|
||||
type DeleteTaskGroupPayload {
|
||||
ok: Boolean!
|
||||
affectedRows: Int!
|
||||
taskGroup: TaskGroup!
|
||||
}
|
||||
|
||||
input NewTaskGroup {
|
||||
projectID: String!
|
||||
name: String!
|
||||
position: Float!
|
||||
}
|
22
api/internal/graph/schema/task_label.gql
Normal file
22
api/internal/graph/schema/task_label.gql
Normal file
@ -0,0 +1,22 @@
|
||||
input AddTaskLabelInput {
|
||||
taskID: UUID!
|
||||
projectLabelID: UUID!
|
||||
}
|
||||
|
||||
input RemoveTaskLabelInput {
|
||||
taskLabelID: UUID!
|
||||
}
|
||||
input ToggleTaskLabelInput {
|
||||
taskID: UUID!
|
||||
projectLabelID: UUID!
|
||||
}
|
||||
|
||||
type ToggleTaskLabelPayload {
|
||||
active: Boolean!
|
||||
task: Task!
|
||||
}
|
||||
extend type Mutation {
|
||||
addTaskLabel(input: AddTaskLabelInput): Task!
|
||||
removeTaskLabel(input: RemoveTaskLabelInput): Task!
|
||||
toggleTaskLabel(input: ToggleTaskLabelInput!): ToggleTaskLabelPayload!
|
||||
}
|
19
api/internal/graph/schema/team.gql
Normal file
19
api/internal/graph/schema/team.gql
Normal file
@ -0,0 +1,19 @@
|
||||
extend type Mutation {
|
||||
deleteTeam(input: DeleteTeam!): DeleteTeamPayload!
|
||||
createTeam(input: NewTeam!): Team!
|
||||
}
|
||||
|
||||
input NewTeam {
|
||||
name: String!
|
||||
organizationID: UUID!
|
||||
}
|
||||
|
||||
input DeleteTeam {
|
||||
teamID: UUID!
|
||||
}
|
||||
|
||||
type DeleteTeamPayload {
|
||||
ok: Boolean!
|
||||
team: Team!
|
||||
projects: [Project!]!
|
||||
}
|
48
api/internal/graph/schema/team_member.gql
Normal file
48
api/internal/graph/schema/team_member.gql
Normal file
@ -0,0 +1,48 @@
|
||||
extend type Mutation {
|
||||
setTeamOwner(input: SetTeamOwner!): SetTeamOwnerPayload!
|
||||
createTeamMember(input: CreateTeamMember!): CreateTeamMemberPayload!
|
||||
updateTeamMemberRole(input: UpdateTeamMemberRole!): UpdateTeamMemberRolePayload!
|
||||
deleteTeamMember(input: DeleteTeamMember!): DeleteTeamMemberPayload!
|
||||
}
|
||||
|
||||
input DeleteTeamMember {
|
||||
teamID: UUID!
|
||||
userID: UUID!
|
||||
}
|
||||
|
||||
type DeleteTeamMemberPayload {
|
||||
teamID: UUID!
|
||||
userID: UUID!
|
||||
}
|
||||
|
||||
input CreateTeamMember {
|
||||
userID: UUID!
|
||||
teamID: UUID!
|
||||
}
|
||||
|
||||
type CreateTeamMemberPayload {
|
||||
team: Team!
|
||||
teamMember: Member!
|
||||
}
|
||||
|
||||
input UpdateTeamMemberRole {
|
||||
teamID: UUID!
|
||||
userID: UUID!
|
||||
roleCode: RoleCode!
|
||||
}
|
||||
|
||||
type UpdateTeamMemberRolePayload {
|
||||
ok: Boolean!
|
||||
member: Member!
|
||||
}
|
||||
|
||||
input SetTeamOwner {
|
||||
teamID: UUID!
|
||||
userID: UUID!
|
||||
}
|
||||
|
||||
type SetTeamOwnerPayload {
|
||||
ok: Boolean!
|
||||
prevOwner: Member!
|
||||
newOwner: Member!
|
||||
}
|
33
api/internal/graph/schema/user.gql
Normal file
33
api/internal/graph/schema/user.gql
Normal file
@ -0,0 +1,33 @@
|
||||
extend type Mutation {
|
||||
createRefreshToken(input: NewRefreshToken!): RefreshToken!
|
||||
createUserAccount(input: NewUserAccount!): UserAccount!
|
||||
deleteUserAccount(input: DeleteUserAccount!): DeleteUserAccountPayload!
|
||||
logoutUser(input: LogoutUser!): Boolean!
|
||||
clearProfileAvatar: UserAccount!
|
||||
}
|
||||
|
||||
input NewRefreshToken {
|
||||
userId: String!
|
||||
}
|
||||
|
||||
input NewUserAccount {
|
||||
username: String!
|
||||
email: String!
|
||||
fullName: String!
|
||||
initials: String!
|
||||
password: String!
|
||||
roleCode: String!
|
||||
}
|
||||
|
||||
input LogoutUser {
|
||||
userID: String!
|
||||
}
|
||||
|
||||
input DeleteUserAccount {
|
||||
userID: UUID!
|
||||
}
|
||||
|
||||
type DeleteUserAccountPayload {
|
||||
ok: Boolean!
|
||||
userAccount: UserAccount!
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
package router
|
||||
package logger
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
@ -57,8 +57,7 @@ func (l *StructuredLoggerEntry) Write(status, bytes int, elapsed time.Duration)
|
||||
"resp_status": status, "resp_bytes_length": bytes,
|
||||
"resp_elapsed_ms": float64(elapsed.Nanoseconds()) / 1000000.0,
|
||||
})
|
||||
|
||||
l.Logger.Infoln("request complete")
|
||||
l.Logger.Debugln("request complete")
|
||||
}
|
||||
|
||||
func (l *StructuredLoggerEntry) Panic(v interface{}, stack []byte) {
|
@ -1,13 +1,15 @@
|
||||
package router
|
||||
package route
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/dgrijalva/jwt-go"
|
||||
"github.com/go-chi/chi"
|
||||
"github.com/google/uuid"
|
||||
"github.com/jordanknott/project-citadel/api/pg"
|
||||
"github.com/jordanknott/project-citadel/api/internal/auth"
|
||||
"github.com/jordanknott/project-citadel/api/internal/db"
|
||||
log "github.com/sirupsen/logrus"
|
||||
"golang.org/x/crypto/bcrypt"
|
||||
)
|
||||
@ -16,6 +18,38 @@ var jwtKey = []byte("citadel_test_key")
|
||||
|
||||
type authResource struct{}
|
||||
|
||||
type AccessTokenClaims struct {
|
||||
UserID string `json:"userId"`
|
||||
jwt.StandardClaims
|
||||
}
|
||||
|
||||
type RefreshTokenClaims struct {
|
||||
UserID string `json:"userId"`
|
||||
jwt.StandardClaims
|
||||
}
|
||||
|
||||
type LoginRequestData struct {
|
||||
Username string
|
||||
Password string
|
||||
}
|
||||
|
||||
type LoginResponseData struct {
|
||||
AccessToken string `json:"accessToken"`
|
||||
}
|
||||
|
||||
type LogoutResponseData struct {
|
||||
Status string `json:"status"`
|
||||
}
|
||||
|
||||
type RefreshTokenResponseData struct {
|
||||
AccessToken string `json:"accessToken"`
|
||||
}
|
||||
|
||||
type AvatarUploadResponseData struct {
|
||||
UserID string `json:"userID"`
|
||||
URL string `json:"url"`
|
||||
}
|
||||
|
||||
func (h *CitadelHandler) RefreshTokenHandler(w http.ResponseWriter, r *http.Request) {
|
||||
c, err := r.Cookie("refreshToken")
|
||||
if err != nil {
|
||||
@ -35,14 +69,14 @@ func (h *CitadelHandler) RefreshTokenHandler(w http.ResponseWriter, r *http.Requ
|
||||
|
||||
refreshCreatedAt := time.Now().UTC()
|
||||
refreshExpiresAt := refreshCreatedAt.AddDate(0, 0, 1)
|
||||
refreshTokenString, err := h.repo.CreateRefreshToken(r.Context(), pg.CreateRefreshTokenParams{token.UserID, refreshCreatedAt, refreshExpiresAt})
|
||||
refreshTokenString, err := h.repo.CreateRefreshToken(r.Context(), db.CreateRefreshTokenParams{token.UserID, refreshCreatedAt, refreshExpiresAt})
|
||||
|
||||
err = h.repo.DeleteRefreshTokenByID(r.Context(), token.TokenID)
|
||||
if err != nil {
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
}
|
||||
|
||||
accessTokenString, err := NewAccessToken(token.UserID.String())
|
||||
accessTokenString, err := auth.NewAccessToken(token.UserID.String())
|
||||
if err != nil {
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
}
|
||||
@ -106,9 +140,9 @@ func (h *CitadelHandler) LoginHandler(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
refreshCreatedAt := time.Now().UTC()
|
||||
refreshExpiresAt := refreshCreatedAt.AddDate(0, 0, 1)
|
||||
refreshTokenString, err := h.repo.CreateRefreshToken(r.Context(), pg.CreateRefreshTokenParams{user.UserID, refreshCreatedAt, refreshExpiresAt})
|
||||
refreshTokenString, err := h.repo.CreateRefreshToken(r.Context(), db.CreateRefreshTokenParams{user.UserID, refreshCreatedAt, refreshExpiresAt})
|
||||
|
||||
accessTokenString, err := NewAccessToken(user.UserID.String())
|
||||
accessTokenString, err := auth.NewAccessToken(user.UserID.String())
|
||||
if err != nil {
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
}
|
52
api/internal/route/avatar.go
Normal file
52
api/internal/route/avatar.go
Normal file
@ -0,0 +1,52 @@
|
||||
package route
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"encoding/json"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
|
||||
"github.com/google/uuid"
|
||||
log "github.com/sirupsen/logrus"
|
||||
|
||||
"github.com/jordanknott/project-citadel/api/internal/db"
|
||||
)
|
||||
|
||||
func (h *CitadelHandler) ProfileImageUpload(w http.ResponseWriter, r *http.Request) {
|
||||
log.Info("preparing to upload file")
|
||||
userID, ok := r.Context().Value("userID").(uuid.UUID)
|
||||
if !ok {
|
||||
log.Error("not a valid uuid")
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
// Parse our multipart form, 10 << 20 specifies a maximum
|
||||
// upload of 10 MB files.
|
||||
r.ParseMultipartForm(10 << 20)
|
||||
|
||||
file, handler, err := r.FormFile("file")
|
||||
if err != nil {
|
||||
log.WithError(err).Error("issue while uploading file")
|
||||
return
|
||||
}
|
||||
defer file.Close()
|
||||
log.WithFields(log.Fields{"filename": handler.Filename, "size": handler.Size, "header": handler.Header}).Info("file metadata")
|
||||
|
||||
fileBytes, err := ioutil.ReadAll(file)
|
||||
if err != nil {
|
||||
log.WithError(err).Error("while reading file")
|
||||
return
|
||||
}
|
||||
err = ioutil.WriteFile("uploads/"+handler.Filename, fileBytes, 0644)
|
||||
if err != nil {
|
||||
log.WithError(err).Error("while reading file")
|
||||
return
|
||||
}
|
||||
|
||||
h.repo.UpdateUserAccountProfileAvatarURL(r.Context(), db.UpdateUserAccountProfileAvatarURLParams{UserID: userID, ProfileAvatarUrl: sql.NullString{String: "http://localhost:3333/uploads/" + handler.Filename, Valid: true}})
|
||||
// return that we have successfully uploaded our file!
|
||||
log.Info("file uploaded")
|
||||
json.NewEncoder(w).Encode(AvatarUploadResponseData{URL: "http://localhost:3333/uploads/" + handler.Filename, UserID: userID.String()})
|
||||
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
package router
|
||||
package route
|
||||
|
||||
import (
|
||||
"context"
|
||||
@ -6,6 +6,7 @@ import (
|
||||
"strings"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"github.com/jordanknott/project-citadel/api/internal/auth"
|
||||
log "github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
@ -13,17 +14,14 @@ func AuthenticationMiddleware(next http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
bearerTokenRaw := r.Header.Get("Authorization")
|
||||
splitToken := strings.Split(bearerTokenRaw, "Bearer")
|
||||
log.WithFields(log.Fields{
|
||||
"bearerToken": bearerTokenRaw,
|
||||
}).Warning("loading bearer token")
|
||||
if len(splitToken) != 2 {
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
accessTokenString := strings.TrimSpace(splitToken[1])
|
||||
accessClaims, err := ValidateAccessToken(accessTokenString)
|
||||
accessClaims, err := auth.ValidateAccessToken(accessTokenString)
|
||||
if err != nil {
|
||||
if _, ok := err.(*ErrExpiredToken); ok {
|
||||
if _, ok := err.(*auth.ErrExpiredToken); ok {
|
||||
w.WriteHeader(http.StatusUnauthorized)
|
||||
w.Write([]byte(`{
|
||||
"data": {},
|
66
api/internal/route/route.go
Normal file
66
api/internal/route/route.go
Normal file
@ -0,0 +1,66 @@
|
||||
package route
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/go-chi/chi"
|
||||
"github.com/go-chi/chi/middleware"
|
||||
"github.com/go-chi/cors"
|
||||
"github.com/jmoiron/sqlx"
|
||||
log "github.com/sirupsen/logrus"
|
||||
|
||||
"github.com/jordanknott/project-citadel/api/internal/db"
|
||||
"github.com/jordanknott/project-citadel/api/internal/graph"
|
||||
"github.com/jordanknott/project-citadel/api/internal/logger"
|
||||
)
|
||||
|
||||
type CitadelHandler struct {
|
||||
repo db.Repository
|
||||
}
|
||||
|
||||
func NewRouter(dbConnection *sqlx.DB) (chi.Router, error) {
|
||||
formatter := new(log.TextFormatter)
|
||||
formatter.TimestampFormat = "02-01-2006 15:04:05"
|
||||
formatter.FullTimestamp = true
|
||||
|
||||
routerLogger := log.New()
|
||||
routerLogger.SetLevel(log.InfoLevel)
|
||||
routerLogger.Formatter = formatter
|
||||
r := chi.NewRouter()
|
||||
cors := cors.New(cors.Options{
|
||||
// AllowedOrigins: []string{"https://foo.com"}, // Use this to allow specific origin hosts
|
||||
AllowedOrigins: []string{"*"},
|
||||
// AllowOriginFunc: func(r *http.Request, origin string) bool { return true },
|
||||
AllowedMethods: []string{"GET", "POST", "PUT", "DELETE", "OPTIONS"},
|
||||
AllowedHeaders: []string{"Accept", "Authorization", "Content-Type", "X-CSRF-Token", "Cookie"},
|
||||
ExposedHeaders: []string{"Link"},
|
||||
AllowCredentials: true,
|
||||
MaxAge: 300, // Maximum value not ignored by any of major browsers
|
||||
})
|
||||
|
||||
r.Use(cors.Handler)
|
||||
r.Use(middleware.RequestID)
|
||||
r.Use(middleware.RealIP)
|
||||
r.Use(logger.NewStructuredLogger(routerLogger))
|
||||
r.Use(middleware.Recoverer)
|
||||
r.Use(middleware.Timeout(60 * time.Second))
|
||||
|
||||
repository := db.NewRepository(dbConnection)
|
||||
citadelHandler := CitadelHandler{*repository}
|
||||
|
||||
var imgServer = http.FileServer(http.Dir("./uploads/"))
|
||||
r.Group(func(mux chi.Router) {
|
||||
mux.Mount("/auth", authResource{}.Routes(citadelHandler))
|
||||
mux.Handle("/__graphql", graph.NewPlaygroundHandler("/graphql"))
|
||||
mux.Mount("/uploads/", http.StripPrefix("/uploads/", imgServer))
|
||||
|
||||
})
|
||||
r.Group(func(mux chi.Router) {
|
||||
mux.Use(AuthenticationMiddleware)
|
||||
mux.Post("/users/me/avatar", citadelHandler.ProfileImageUpload)
|
||||
mux.Handle("/graphql", graph.NewHandler(*repository))
|
||||
})
|
||||
|
||||
return r, nil
|
||||
}
|
45
api/magefile.go
Normal file
45
api/magefile.go
Normal file
@ -0,0 +1,45 @@
|
||||
//+build mage
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/magefile/mage/sh"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"strings"
|
||||
)
|
||||
|
||||
var Aliases = map[string]interface{}{
|
||||
"g": Generate,
|
||||
}
|
||||
|
||||
// Runs go mod download and then installs the binary.
|
||||
func Generate() error {
|
||||
|
||||
files, err := ioutil.ReadDir("graph/schema/")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
var schema strings.Builder
|
||||
for _, file := range files {
|
||||
filename := "graph/schema/" + file.Name()
|
||||
fmt.Println(filename)
|
||||
f, err := os.Open(filename)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
content, err := ioutil.ReadAll(f)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
fmt.Fprintln(&schema, string(content))
|
||||
}
|
||||
// return sh.Run("go", "install", "./...")
|
||||
// fmt.Println(schema.String())
|
||||
err = ioutil.WriteFile("graph/schema.graphqls", []byte(schema.String()), os.FileMode(0755))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return sh.Run("gqlgen")
|
||||
}
|
@ -1,3 +1,5 @@
|
||||
CREATE EXTENSION IF NOT EXISTS "uuid-ossp";
|
||||
|
||||
CREATE TABLE refresh_token (
|
||||
token_id uuid PRIMARY KEY DEFAULT uuid_generate_v4(),
|
||||
user_id uuid NOT NULL,
|
||||
|
@ -3,3 +3,5 @@ CREATE TABLE organization (
|
||||
created_at timestamptz NOT NULL,
|
||||
name text NOT NULL
|
||||
);
|
||||
|
||||
INSERT INTO organization (created_at, name) VALUES (NOW(), 'sys_default_organization');
|
||||
|
6
api/migrations/0037_add-project_member-table.up.sql
Normal file
6
api/migrations/0037_add-project_member-table.up.sql
Normal file
@ -0,0 +1,6 @@
|
||||
CREATE TABLE project_member (
|
||||
project_member_id uuid PRIMARY KEY DEFAULT uuid_generate_v4(),
|
||||
project_id uuid NOT NULL REFERENCES project(project_id) ON DELETE CASCADE,
|
||||
user_id uuid NOT NULL REFERENCES user_account(user_id) ON DELETE CASCADE,
|
||||
added_at timestamptz NOT NULL
|
||||
);
|
9
api/migrations/0038_add-role-table.up.sql
Normal file
9
api/migrations/0038_add-role-table.up.sql
Normal file
@ -0,0 +1,9 @@
|
||||
CREATE TABLE role (
|
||||
code TEXT PRIMARY KEY,
|
||||
name TEXT NOT NULL
|
||||
);
|
||||
|
||||
INSERT INTO role VALUES ('owner', 'Owner');
|
||||
INSERT INTO role VALUES ('admin', 'Admin');
|
||||
INSERT INTO role VALUES ('member', 'Member');
|
||||
INSERT INTO role VALUES ('observer', 'Observer');
|
@ -0,0 +1,2 @@
|
||||
ALTER TABLE user_account ADD COLUMN role_code text
|
||||
NOT NULL REFERENCES role(code) ON DELETE CASCADE DEFAULT 'member';
|
@ -0,0 +1 @@
|
||||
ALTER TABLE project_member ADD UNIQUE (project_id, user_id);
|
@ -0,0 +1,2 @@
|
||||
ALTER TABLE project_member ADD COLUMN role_code TEXT
|
||||
NOT NULL REFERENCES role(code) ON DELETE CASCADE DEFAULT 'member';
|
@ -0,0 +1 @@
|
||||
ALTER TABLE user_account ALTER COLUMN profile_avatar_url SET DEFAULT null;
|
@ -0,0 +1 @@
|
||||
ALTER TABLE team_member ADD COLUMN role_code TEXT NOT NULL REFERENCES role(code) ON DELETE CASCADE;
|
4
api/migrations/0044_add-owner-to-team-table.up.sql
Normal file
4
api/migrations/0044_add-owner-to-team-table.up.sql
Normal file
@ -0,0 +1,4 @@
|
||||
ALTER TABLE team ADD COLUMN owner uuid REFERENCES user_account(user_id) ON DELETE
|
||||
CASCADE;
|
||||
UPDATE team SET owner = (SELECT user_id FROM user_account WHERE role_code = 'admin' LIMIT 1);
|
||||
ALTER TABLE team ALTER COLUMN owner SET NOT NULL;
|
114
api/pg/pg.go
114
api/pg/pg.go
@ -1,114 +0,0 @@
|
||||
package pg
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/google/uuid"
|
||||
"github.com/jmoiron/sqlx"
|
||||
)
|
||||
|
||||
type Repository interface {
|
||||
CreateTeamMember(ctx context.Context, arg CreateTeamMemberParams) (TeamMember, error)
|
||||
DeleteTeamMemberByUserID(ctx context.Context, userID uuid.UUID) error
|
||||
GetTeamMembersForTeamID(ctx context.Context, teamID uuid.UUID) ([]TeamMember, error)
|
||||
|
||||
CreateTeam(ctx context.Context, arg CreateTeamParams) (Team, error)
|
||||
DeleteTeamByID(ctx context.Context, teamID uuid.UUID) error
|
||||
GetTeamByID(ctx context.Context, teamID uuid.UUID) (Team, error)
|
||||
GetAllTeams(ctx context.Context) ([]Team, error)
|
||||
|
||||
DeleteProjectByID(ctx context.Context, projectID uuid.UUID) error
|
||||
DeleteUserAccountByID(ctx context.Context, userID uuid.UUID) error
|
||||
|
||||
GetTaskChecklistByID(ctx context.Context, taskChecklistID uuid.UUID) (TaskChecklist, error)
|
||||
DeleteTaskChecklistByID(ctx context.Context, taskChecklistID uuid.UUID) error
|
||||
UpdateTaskChecklistName(ctx context.Context, arg UpdateTaskChecklistNameParams) (TaskChecklist, error)
|
||||
CreateProject(ctx context.Context, arg CreateProjectParams) (Project, error)
|
||||
GetAllProjects(ctx context.Context) ([]Project, error)
|
||||
GetAllProjectsForTeam(ctx context.Context, teamID uuid.UUID) ([]Project, error)
|
||||
GetProjectByID(ctx context.Context, projectID uuid.UUID) (Project, error)
|
||||
|
||||
UpdateTaskChecklistItemName(ctx context.Context, arg UpdateTaskChecklistItemNameParams) (TaskChecklistItem, error)
|
||||
GetTaskChecklistItemByID(ctx context.Context, taskChecklistItemID uuid.UUID) (TaskChecklistItem, error)
|
||||
CreateTaskChecklist(ctx context.Context, arg CreateTaskChecklistParams) (TaskChecklist, error)
|
||||
CreateTaskChecklistItem(ctx context.Context, arg CreateTaskChecklistItemParams) (TaskChecklistItem, error)
|
||||
GetTaskChecklistItemsForTaskChecklist(ctx context.Context, taskChecklistID uuid.UUID) ([]TaskChecklistItem, error)
|
||||
GetTaskChecklistsForTask(ctx context.Context, taskID uuid.UUID) ([]TaskChecklist, error)
|
||||
SetTaskChecklistItemComplete(ctx context.Context, arg SetTaskChecklistItemCompleteParams) (TaskChecklistItem, error)
|
||||
DeleteTaskChecklistItem(ctx context.Context, taskChecklistItemID uuid.UUID) error
|
||||
|
||||
UpdateUserAccountProfileAvatarURL(ctx context.Context, arg UpdateUserAccountProfileAvatarURLParams) (UserAccount, error)
|
||||
|
||||
CreateUserAccount(ctx context.Context, arg CreateUserAccountParams) (UserAccount, error)
|
||||
GetUserAccountByID(ctx context.Context, userID uuid.UUID) (UserAccount, error)
|
||||
GetUserAccountByUsername(ctx context.Context, username string) (UserAccount, error)
|
||||
GetAllUserAccounts(ctx context.Context) ([]UserAccount, error)
|
||||
|
||||
GetTaskLabelByID(ctx context.Context, taskLabelID uuid.UUID) (TaskLabel, error)
|
||||
|
||||
SetTaskComplete(ctx context.Context, arg SetTaskCompleteParams) (Task, error)
|
||||
DeleteTaskLabelForTaskByProjectLabelID(ctx context.Context, arg DeleteTaskLabelForTaskByProjectLabelIDParams) error
|
||||
GetTaskLabelForTaskByProjectLabelID(ctx context.Context, arg GetTaskLabelForTaskByProjectLabelIDParams) (TaskLabel, error)
|
||||
UpdateProjectNameByID(ctx context.Context, arg UpdateProjectNameByIDParams) (Project, error)
|
||||
|
||||
DeleteTaskLabelByID(ctx context.Context, taskLabelID uuid.UUID) error
|
||||
UpdateTaskDueDate(ctx context.Context, arg UpdateTaskDueDateParams) (Task, error)
|
||||
CreateProjectLabel(ctx context.Context, arg CreateProjectLabelParams) (ProjectLabel, error)
|
||||
GetProjectLabelsForProject(ctx context.Context, projectID uuid.UUID) ([]ProjectLabel, error)
|
||||
GetProjectLabelByID(ctx context.Context, projectLabelID uuid.UUID) (ProjectLabel, error)
|
||||
DeleteProjectLabelByID(ctx context.Context, projectLabelID uuid.UUID) error
|
||||
UpdateProjectLabelColor(ctx context.Context, arg UpdateProjectLabelColorParams) (ProjectLabel, error)
|
||||
UpdateProjectLabelName(ctx context.Context, arg UpdateProjectLabelNameParams) (ProjectLabel, error)
|
||||
UpdateProjectLabel(ctx context.Context, arg UpdateProjectLabelParams) (ProjectLabel, error)
|
||||
|
||||
GetLabelColors(ctx context.Context) ([]LabelColor, error)
|
||||
CreateLabelColor(ctx context.Context, arg CreateLabelColorParams) (LabelColor, error)
|
||||
|
||||
CreateRefreshToken(ctx context.Context, arg CreateRefreshTokenParams) (RefreshToken, error)
|
||||
GetRefreshTokenByID(ctx context.Context, tokenID uuid.UUID) (RefreshToken, error)
|
||||
DeleteRefreshTokenByID(ctx context.Context, tokenID uuid.UUID) error
|
||||
DeleteRefreshTokenByUserID(ctx context.Context, userID uuid.UUID) error
|
||||
|
||||
SetTaskGroupName(ctx context.Context, arg SetTaskGroupNameParams) (TaskGroup, error)
|
||||
DeleteTaskGroupByID(ctx context.Context, taskGroupID uuid.UUID) (int64, error)
|
||||
DeleteTasksByTaskGroupID(ctx context.Context, taskGroupID uuid.UUID) (int64, error)
|
||||
UpdateTaskGroupLocation(ctx context.Context, arg UpdateTaskGroupLocationParams) (TaskGroup, error)
|
||||
CreateTaskGroup(ctx context.Context, arg CreateTaskGroupParams) (TaskGroup, error)
|
||||
GetAllTaskGroups(ctx context.Context) ([]TaskGroup, error)
|
||||
GetTaskGroupsForProject(ctx context.Context, projectID uuid.UUID) ([]TaskGroup, error)
|
||||
GetTaskGroupByID(ctx context.Context, taskGroupID uuid.UUID) (TaskGroup, error)
|
||||
|
||||
GetAllOrganizations(ctx context.Context) ([]Organization, error)
|
||||
CreateOrganization(ctx context.Context, arg CreateOrganizationParams) (Organization, error)
|
||||
|
||||
GetTeamsForOrganization(ctx context.Context, organizationID uuid.UUID) ([]Team, error)
|
||||
|
||||
CreateTask(ctx context.Context, arg CreateTaskParams) (Task, error)
|
||||
GetTaskByID(ctx context.Context, taskID uuid.UUID) (Task, error)
|
||||
GetAllTasks(ctx context.Context) ([]Task, error)
|
||||
GetTasksForTaskGroupID(ctx context.Context, taskGroupID uuid.UUID) ([]Task, error)
|
||||
UpdateTaskLocation(ctx context.Context, arg UpdateTaskLocationParams) (Task, error)
|
||||
DeleteTaskByID(ctx context.Context, taskID uuid.UUID) error
|
||||
UpdateTaskName(ctx context.Context, arg UpdateTaskNameParams) (Task, error)
|
||||
UpdateTaskDescription(ctx context.Context, arg UpdateTaskDescriptionParams) (Task, error)
|
||||
|
||||
CreateTaskLabelForTask(ctx context.Context, arg CreateTaskLabelForTaskParams) (TaskLabel, error)
|
||||
GetTaskLabelsForTaskID(ctx context.Context, taskID uuid.UUID) ([]TaskLabel, error)
|
||||
GetLabelColorByID(ctx context.Context, labelColorID uuid.UUID) (LabelColor, error)
|
||||
|
||||
CreateTaskAssigned(ctx context.Context, arg CreateTaskAssignedParams) (TaskAssigned, error)
|
||||
GetAssignedMembersForTask(ctx context.Context, taskID uuid.UUID) ([]TaskAssigned, error)
|
||||
DeleteTaskAssignedByID(ctx context.Context, arg DeleteTaskAssignedByIDParams) (TaskAssigned, error)
|
||||
}
|
||||
|
||||
type repoSvc struct {
|
||||
*Queries
|
||||
db *sqlx.DB
|
||||
}
|
||||
|
||||
// NewRepository returns an implementation of the Repository interface.
|
||||
func NewRepository(db *sqlx.DB) Repository {
|
||||
return &repoSvc{
|
||||
Queries: New(db.DB),
|
||||
db: db,
|
||||
}
|
||||
}
|
@ -1,154 +0,0 @@
|
||||
// Code generated by sqlc. DO NOT EDIT.
|
||||
// source: project.sql
|
||||
|
||||
package pg
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
const createProject = `-- name: CreateProject :one
|
||||
INSERT INTO project(owner, team_id, created_at, name) VALUES ($1, $2, $3, $4) RETURNING project_id, team_id, created_at, name, owner
|
||||
`
|
||||
|
||||
type CreateProjectParams struct {
|
||||
Owner uuid.UUID `json:"owner"`
|
||||
TeamID uuid.UUID `json:"team_id"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
Name string `json:"name"`
|
||||
}
|
||||
|
||||
func (q *Queries) CreateProject(ctx context.Context, arg CreateProjectParams) (Project, error) {
|
||||
row := q.db.QueryRowContext(ctx, createProject,
|
||||
arg.Owner,
|
||||
arg.TeamID,
|
||||
arg.CreatedAt,
|
||||
arg.Name,
|
||||
)
|
||||
var i Project
|
||||
err := row.Scan(
|
||||
&i.ProjectID,
|
||||
&i.TeamID,
|
||||
&i.CreatedAt,
|
||||
&i.Name,
|
||||
&i.Owner,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const deleteProjectByID = `-- name: DeleteProjectByID :exec
|
||||
DELETE FROM project WHERE project_id = $1
|
||||
`
|
||||
|
||||
func (q *Queries) DeleteProjectByID(ctx context.Context, projectID uuid.UUID) error {
|
||||
_, err := q.db.ExecContext(ctx, deleteProjectByID, projectID)
|
||||
return err
|
||||
}
|
||||
|
||||
const getAllProjects = `-- name: GetAllProjects :many
|
||||
SELECT project_id, team_id, created_at, name, owner FROM project
|
||||
`
|
||||
|
||||
func (q *Queries) GetAllProjects(ctx context.Context) ([]Project, error) {
|
||||
rows, err := q.db.QueryContext(ctx, getAllProjects)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
var items []Project
|
||||
for rows.Next() {
|
||||
var i Project
|
||||
if err := rows.Scan(
|
||||
&i.ProjectID,
|
||||
&i.TeamID,
|
||||
&i.CreatedAt,
|
||||
&i.Name,
|
||||
&i.Owner,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
items = append(items, i)
|
||||
}
|
||||
if err := rows.Close(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := rows.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return items, nil
|
||||
}
|
||||
|
||||
const getAllProjectsForTeam = `-- name: GetAllProjectsForTeam :many
|
||||
SELECT project_id, team_id, created_at, name, owner FROM project WHERE team_id = $1
|
||||
`
|
||||
|
||||
func (q *Queries) GetAllProjectsForTeam(ctx context.Context, teamID uuid.UUID) ([]Project, error) {
|
||||
rows, err := q.db.QueryContext(ctx, getAllProjectsForTeam, teamID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
var items []Project
|
||||
for rows.Next() {
|
||||
var i Project
|
||||
if err := rows.Scan(
|
||||
&i.ProjectID,
|
||||
&i.TeamID,
|
||||
&i.CreatedAt,
|
||||
&i.Name,
|
||||
&i.Owner,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
items = append(items, i)
|
||||
}
|
||||
if err := rows.Close(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := rows.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return items, nil
|
||||
}
|
||||
|
||||
const getProjectByID = `-- name: GetProjectByID :one
|
||||
SELECT project_id, team_id, created_at, name, owner FROM project WHERE project_id = $1
|
||||
`
|
||||
|
||||
func (q *Queries) GetProjectByID(ctx context.Context, projectID uuid.UUID) (Project, error) {
|
||||
row := q.db.QueryRowContext(ctx, getProjectByID, projectID)
|
||||
var i Project
|
||||
err := row.Scan(
|
||||
&i.ProjectID,
|
||||
&i.TeamID,
|
||||
&i.CreatedAt,
|
||||
&i.Name,
|
||||
&i.Owner,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const updateProjectNameByID = `-- name: UpdateProjectNameByID :one
|
||||
UPDATE project SET name = $2 WHERE project_id = $1 RETURNING project_id, team_id, created_at, name, owner
|
||||
`
|
||||
|
||||
type UpdateProjectNameByIDParams struct {
|
||||
ProjectID uuid.UUID `json:"project_id"`
|
||||
Name string `json:"name"`
|
||||
}
|
||||
|
||||
func (q *Queries) UpdateProjectNameByID(ctx context.Context, arg UpdateProjectNameByIDParams) (Project, error) {
|
||||
row := q.db.QueryRowContext(ctx, updateProjectNameByID, arg.ProjectID, arg.Name)
|
||||
var i Project
|
||||
err := row.Scan(
|
||||
&i.ProjectID,
|
||||
&i.TeamID,
|
||||
&i.CreatedAt,
|
||||
&i.Name,
|
||||
&i.Owner,
|
||||
)
|
||||
return i, err
|
||||
}
|
@ -1,75 +0,0 @@
|
||||
// Code generated by sqlc. DO NOT EDIT.
|
||||
// source: team_member.sql
|
||||
|
||||
package pg
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
const createTeamMember = `-- name: CreateTeamMember :one
|
||||
INSERT INTO team_member (team_id, user_id, addedDate) VALUES ($1, $2, $3)
|
||||
RETURNING team_member_id, team_id, user_id, addeddate
|
||||
`
|
||||
|
||||
type CreateTeamMemberParams struct {
|
||||
TeamID uuid.UUID `json:"team_id"`
|
||||
UserID uuid.UUID `json:"user_id"`
|
||||
Addeddate time.Time `json:"addeddate"`
|
||||
}
|
||||
|
||||
func (q *Queries) CreateTeamMember(ctx context.Context, arg CreateTeamMemberParams) (TeamMember, error) {
|
||||
row := q.db.QueryRowContext(ctx, createTeamMember, arg.TeamID, arg.UserID, arg.Addeddate)
|
||||
var i TeamMember
|
||||
err := row.Scan(
|
||||
&i.TeamMemberID,
|
||||
&i.TeamID,
|
||||
&i.UserID,
|
||||
&i.Addeddate,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const deleteTeamMemberByUserID = `-- name: DeleteTeamMemberByUserID :exec
|
||||
DELETE FROM team_member WHERE user_id = $1
|
||||
`
|
||||
|
||||
func (q *Queries) DeleteTeamMemberByUserID(ctx context.Context, userID uuid.UUID) error {
|
||||
_, err := q.db.ExecContext(ctx, deleteTeamMemberByUserID, userID)
|
||||
return err
|
||||
}
|
||||
|
||||
const getTeamMembersForTeamID = `-- name: GetTeamMembersForTeamID :many
|
||||
SELECT team_member_id, team_id, user_id, addeddate FROM team_member WHERE team_id = $1
|
||||
`
|
||||
|
||||
func (q *Queries) GetTeamMembersForTeamID(ctx context.Context, teamID uuid.UUID) ([]TeamMember, error) {
|
||||
rows, err := q.db.QueryContext(ctx, getTeamMembersForTeamID, teamID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
var items []TeamMember
|
||||
for rows.Next() {
|
||||
var i TeamMember
|
||||
if err := rows.Scan(
|
||||
&i.TeamMemberID,
|
||||
&i.TeamID,
|
||||
&i.UserID,
|
||||
&i.Addeddate,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
items = append(items, i)
|
||||
}
|
||||
if err := rows.Close(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := rows.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return items, nil
|
||||
}
|
@ -1,17 +0,0 @@
|
||||
-- name: GetAllProjects :many
|
||||
SELECT * FROM project;
|
||||
|
||||
-- name: GetAllProjectsForTeam :many
|
||||
SELECT * FROM project WHERE team_id = $1;
|
||||
|
||||
-- name: GetProjectByID :one
|
||||
SELECT * FROM project WHERE project_id = $1;
|
||||
|
||||
-- name: CreateProject :one
|
||||
INSERT INTO project(owner, team_id, created_at, name) VALUES ($1, $2, $3, $4) RETURNING *;
|
||||
|
||||
-- name: UpdateProjectNameByID :one
|
||||
UPDATE project SET name = $2 WHERE project_id = $1 RETURNING *;
|
||||
|
||||
-- name: DeleteProjectByID :exec
|
||||
DELETE FROM project WHERE project_id = $1;
|
@ -1,9 +0,0 @@
|
||||
-- name: CreateTeamMember :one
|
||||
INSERT INTO team_member (team_id, user_id, addedDate) VALUES ($1, $2, $3)
|
||||
RETURNING *;
|
||||
|
||||
-- name: GetTeamMembersForTeamID :many
|
||||
SELECT * FROM team_member WHERE team_id = $1;
|
||||
|
||||
-- name: DeleteTeamMemberByUserID :exec
|
||||
DELETE FROM team_member WHERE user_id = $1;
|
@ -1,13 +0,0 @@
|
||||
package router
|
||||
|
||||
type ErrExpiredToken struct{}
|
||||
|
||||
func (r *ErrExpiredToken) Error() string {
|
||||
return "token is expired"
|
||||
}
|
||||
|
||||
type ErrMalformedToken struct{}
|
||||
|
||||
func (r *ErrMalformedToken) Error() string {
|
||||
return "token is malformed"
|
||||
}
|
@ -1,7 +0,0 @@
|
||||
package router
|
||||
|
||||
import "github.com/jordanknott/project-citadel/api/pg"
|
||||
|
||||
type CitadelHandler struct {
|
||||
repo pg.Repository
|
||||
}
|
@ -1,37 +0,0 @@
|
||||
package router
|
||||
|
||||
import (
|
||||
"github.com/dgrijalva/jwt-go"
|
||||
)
|
||||
|
||||
type AccessTokenClaims struct {
|
||||
UserID string `json:"userId"`
|
||||
jwt.StandardClaims
|
||||
}
|
||||
|
||||
type RefreshTokenClaims struct {
|
||||
UserID string `json:"userId"`
|
||||
jwt.StandardClaims
|
||||
}
|
||||
|
||||
type LoginRequestData struct {
|
||||
Username string
|
||||
Password string
|
||||
}
|
||||
|
||||
type LoginResponseData struct {
|
||||
AccessToken string `json:"accessToken"`
|
||||
}
|
||||
|
||||
type LogoutResponseData struct {
|
||||
Status string `json:"status"`
|
||||
}
|
||||
|
||||
type RefreshTokenResponseData struct {
|
||||
AccessToken string `json:"accessToken"`
|
||||
}
|
||||
|
||||
type AvatarUploadResponseData struct {
|
||||
UserID string `json:"userID"`
|
||||
URL string `json:"url"`
|
||||
}
|
@ -1,108 +0,0 @@
|
||||
package router
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"encoding/json"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/go-chi/chi"
|
||||
"github.com/go-chi/chi/middleware"
|
||||
"github.com/go-chi/cors"
|
||||
"github.com/google/uuid"
|
||||
"github.com/jmoiron/sqlx"
|
||||
log "github.com/sirupsen/logrus"
|
||||
|
||||
"github.com/jordanknott/project-citadel/api/graph"
|
||||
"github.com/jordanknott/project-citadel/api/pg"
|
||||
)
|
||||
|
||||
func (h *CitadelHandler) PingHandler(w http.ResponseWriter, r *http.Request) {
|
||||
w.Write([]byte("pong"))
|
||||
}
|
||||
|
||||
func (h *CitadelHandler) ProfileImageUpload(w http.ResponseWriter, r *http.Request) {
|
||||
log.Info("preparing to upload file")
|
||||
userID, ok := r.Context().Value("userID").(uuid.UUID)
|
||||
if !ok {
|
||||
log.Error("not a valid uuid")
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
// Parse our multipart form, 10 << 20 specifies a maximum
|
||||
// upload of 10 MB files.
|
||||
r.ParseMultipartForm(10 << 20)
|
||||
|
||||
file, handler, err := r.FormFile("file")
|
||||
if err != nil {
|
||||
log.WithError(err).Error("issue while uploading file")
|
||||
return
|
||||
}
|
||||
defer file.Close()
|
||||
log.WithFields(log.Fields{"filename": handler.Filename, "size": handler.Size, "header": handler.Header}).Info("file metadata")
|
||||
|
||||
fileBytes, err := ioutil.ReadAll(file)
|
||||
if err != nil {
|
||||
log.WithError(err).Error("while reading file")
|
||||
return
|
||||
}
|
||||
err = ioutil.WriteFile("uploads/"+handler.Filename, fileBytes, 0644)
|
||||
if err != nil {
|
||||
log.WithError(err).Error("while reading file")
|
||||
return
|
||||
}
|
||||
|
||||
h.repo.UpdateUserAccountProfileAvatarURL(r.Context(), pg.UpdateUserAccountProfileAvatarURLParams{UserID: userID, ProfileAvatarUrl: sql.NullString{String: "http://localhost:3333/uploads/" + handler.Filename, Valid: true}})
|
||||
// return that we have successfully uploaded our file!
|
||||
log.Info("file uploaded")
|
||||
json.NewEncoder(w).Encode(AvatarUploadResponseData{URL: "http://localhost:3333/uploads/" + handler.Filename, UserID: userID.String()})
|
||||
|
||||
}
|
||||
|
||||
func NewRouter(db *sqlx.DB) (chi.Router, error) {
|
||||
formatter := new(log.TextFormatter)
|
||||
formatter.TimestampFormat = "02-01-2006 15:04:05"
|
||||
formatter.FullTimestamp = true
|
||||
|
||||
routerLogger := log.New()
|
||||
routerLogger.SetLevel(log.DebugLevel)
|
||||
routerLogger.Formatter = formatter
|
||||
r := chi.NewRouter()
|
||||
cors := cors.New(cors.Options{
|
||||
// AllowedOrigins: []string{"https://foo.com"}, // Use this to allow specific origin hosts
|
||||
AllowedOrigins: []string{"*"},
|
||||
// AllowOriginFunc: func(r *http.Request, origin string) bool { return true },
|
||||
AllowedMethods: []string{"GET", "POST", "PUT", "DELETE", "OPTIONS"},
|
||||
AllowedHeaders: []string{"Accept", "Authorization", "Content-Type", "X-CSRF-Token", "Cookie"},
|
||||
ExposedHeaders: []string{"Link"},
|
||||
AllowCredentials: true,
|
||||
MaxAge: 300, // Maximum value not ignored by any of major browsers
|
||||
})
|
||||
r.Use(cors.Handler)
|
||||
r.Use(middleware.RequestID)
|
||||
r.Use(middleware.RealIP)
|
||||
r.Use(NewStructuredLogger(routerLogger))
|
||||
r.Use(middleware.Recoverer)
|
||||
r.Use(middleware.Timeout(60 * time.Second))
|
||||
|
||||
repository := pg.NewRepository(db)
|
||||
citadelHandler := CitadelHandler{repository}
|
||||
|
||||
r.Group(func(mux chi.Router) {
|
||||
mux.Mount("/auth", authResource{}.Routes(citadelHandler))
|
||||
mux.Handle("/__graphql", graph.NewPlaygroundHandler("/graphql"))
|
||||
var imgServer = http.FileServer(http.Dir("./uploads/"))
|
||||
mux.Mount("/uploads/", http.StripPrefix("/uploads/", imgServer))
|
||||
|
||||
})
|
||||
r.Group(func(mux chi.Router) {
|
||||
mux.Use(AuthenticationMiddleware)
|
||||
mux.Post("/users/me/avatar", citadelHandler.ProfileImageUpload)
|
||||
mux.Get("/ping", citadelHandler.PingHandler)
|
||||
mux.Handle("/graphql", graph.NewHandler(repository))
|
||||
})
|
||||
|
||||
return r, nil
|
||||
}
|
@ -1,10 +1,10 @@
|
||||
version: "1"
|
||||
packages:
|
||||
- name: "pg"
|
||||
- name: "db"
|
||||
emit_json_tags: true
|
||||
emit_prepared_queries: false
|
||||
emit_interface: true
|
||||
path: "pg"
|
||||
queries: "./query/"
|
||||
path: "internal/db"
|
||||
queries: "./internal/db/query/"
|
||||
schema: "./migrations/"
|
||||
|
||||
|
12
api/templates/mail/user/registered.tmpl
Normal file
12
api/templates/mail/user/registered.tmpl
Normal file
@ -0,0 +1,12 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
<title>{{.Username}} has been registered</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<p>Hi <b>{{.Username}}</b>, thanks for registering at {{.AppName}}!</p>
|
||||
<p>© {{.Year}} <a target="_blank" rel="noopener noreferrer" href="{{.AppURL}}">{{.AppName}}</a></p>
|
||||
</body>
|
||||
</html>
|
501
web/report.20200630.191315.2921.0.001.json
Normal file
501
web/report.20200630.191315.2921.0.001.json
Normal file
@ -0,0 +1,501 @@
|
||||
|
||||
{
|
||||
"header": {
|
||||
"reportVersion": 1,
|
||||
"event": "Allocation failed - JavaScript heap out of memory",
|
||||
"trigger": "FatalError",
|
||||
"filename": "report.20200630.191315.2921.0.001.json",
|
||||
"dumpEventTime": "2020-06-30T19:13:15Z",
|
||||
"dumpEventTimeStamp": "1593562395582",
|
||||
"processId": 2921,
|
||||
"cwd": "/home/jordan/Projects/project-citadel/web",
|
||||
"commandLine": [
|
||||
"/usr/bin/node",
|
||||
"/home/jordan/.config/coc/extensions/node_modules/coc-tsserver/bin/tsserverForkStart",
|
||||
"/home/jordan/Projects/project-citadel/web/node_modules/typescript/lib/tsserver.js",
|
||||
"--allowLocalPluginLoads",
|
||||
"--useInferredProjectPerProjectRoot",
|
||||
"--cancellationPipeName",
|
||||
"/tmp/coc-nvim-tscancellation-de3655a46bee8a6c5461.sock*",
|
||||
"--npmLocation",
|
||||
"\"/usr/bin/npm\"",
|
||||
"--noGetErrOnBackgroundUpdate",
|
||||
"--validateDefaultNpmLocation"
|
||||
],
|
||||
"nodejsVersion": "v13.8.0",
|
||||
"glibcVersionRuntime": "2.30",
|
||||
"glibcVersionCompiler": "2.30",
|
||||
"wordSize": 64,
|
||||
"arch": "x64",
|
||||
"platform": "linux",
|
||||
"componentVersions": {
|
||||
"node": "13.8.0",
|
||||
"v8": "7.9.317.25-node.28",
|
||||
"uv": "1.34.1",
|
||||
"zlib": "1.2.11",
|
||||
"brotli": "1.0.7",
|
||||
"ares": "1.15.0",
|
||||
"modules": "79",
|
||||
"nghttp2": "1.39.2",
|
||||
"napi": "5",
|
||||
"llhttp": "2.0.4",
|
||||
"openssl": "1.1.1d",
|
||||
"cldr": "36.0",
|
||||
"icu": "65.1",
|
||||
"tz": "2019c",
|
||||
"unicode": "12.1"
|
||||
},
|
||||
"release": {
|
||||
"name": "node",
|
||||
"headersUrl": "https://nodejs.org/download/release/v13.8.0/node-v13.8.0-headers.tar.gz",
|
||||
"sourceUrl": "https://nodejs.org/download/release/v13.8.0/node-v13.8.0.tar.gz"
|
||||
},
|
||||
"osName": "Linux",
|
||||
"osRelease": "4.19.101-1-lts",
|
||||
"osVersion": "#1 SMP Sat, 01 Feb 2020 16:35:36 +0000",
|
||||
"osMachine": "x86_64",
|
||||
"cpus": [
|
||||
{
|
||||
"model": "Intel(R) Core(TM) i7-6500U CPU @ 2.50GHz",
|
||||
"speed": 928,
|
||||
"user": 17517600,
|
||||
"nice": 5000,
|
||||
"sys": 2658800,
|
||||
"idle": 54442200,
|
||||
"irq": 146200
|
||||
},
|
||||
{
|
||||
"model": "Intel(R) Core(TM) i7-6500U CPU @ 2.50GHz",
|
||||
"speed": 1192,
|
||||
"user": 16529500,
|
||||
"nice": 3900,
|
||||
"sys": 2713400,
|
||||
"idle": 55020300,
|
||||
"irq": 289200
|
||||
},
|
||||
{
|
||||
"model": "Intel(R) Core(TM) i7-6500U CPU @ 2.50GHz",
|
||||
"speed": 1197,
|
||||
"user": 16764400,
|
||||
"nice": 3600,
|
||||
"sys": 2584400,
|
||||
"idle": 55071500,
|
||||
"irq": 157600
|
||||
},
|
||||
{
|
||||
"model": "Intel(R) Core(TM) i7-6500U CPU @ 2.50GHz",
|
||||
"speed": 1196,
|
||||
"user": 16700100,
|
||||
"nice": 2500,
|
||||
"sys": 2588500,
|
||||
"idle": 55230400,
|
||||
"irq": 152300
|
||||
}
|
||||
],
|
||||
"networkInterfaces": [
|
||||
{
|
||||
"name": "lo",
|
||||
"internal": true,
|
||||
"mac": "00:00:00:00:00:00",
|
||||
"address": "127.0.0.1",
|
||||
"netmask": "255.0.0.0",
|
||||
"family": "IPv4"
|
||||
},
|
||||
{
|
||||
"name": "wlp3s0",
|
||||
"internal": false,
|
||||
"mac": "7c:b0:c2:fe:93:86",
|
||||
"address": "192.168.43.5",
|
||||
"netmask": "255.255.255.0",
|
||||
"family": "IPv4"
|
||||
},
|
||||
{
|
||||
"name": "docker0",
|
||||
"internal": false,
|
||||
"mac": "02:42:64:b5:eb:c5",
|
||||
"address": "172.17.0.1",
|
||||
"netmask": "255.255.0.0",
|
||||
"family": "IPv4"
|
||||
},
|
||||
{
|
||||
"name": "br-e929893879ec",
|
||||
"internal": false,
|
||||
"mac": "02:42:77:2b:e8:70",
|
||||
"address": "172.19.0.1",
|
||||
"netmask": "255.255.0.0",
|
||||
"family": "IPv4"
|
||||
},
|
||||
{
|
||||
"name": "lo",
|
||||
"internal": true,
|
||||
"mac": "00:00:00:00:00:00",
|
||||
"address": "::1",
|
||||
"netmask": "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff",
|
||||
"family": "IPv6",
|
||||
"scopeid": 0
|
||||
},
|
||||
{
|
||||
"name": "wlp3s0",
|
||||
"internal": false,
|
||||
"mac": "7c:b0:c2:fe:93:86",
|
||||
"address": "2600:100b:b011:583b:7eb0:c2ff:fefe:9386",
|
||||
"netmask": "ffff:ffff:ffff:ffff::",
|
||||
"family": "IPv6",
|
||||
"scopeid": 0
|
||||
},
|
||||
{
|
||||
"name": "wlp3s0",
|
||||
"internal": false,
|
||||
"mac": "7c:b0:c2:fe:93:86",
|
||||
"address": "fe80::7eb0:c2ff:fefe:9386",
|
||||
"netmask": "ffff:ffff:ffff:ffff::",
|
||||
"family": "IPv6",
|
||||
"scopeid": 3
|
||||
},
|
||||
{
|
||||
"name": "docker0",
|
||||
"internal": false,
|
||||
"mac": "02:42:64:b5:eb:c5",
|
||||
"address": "fe80::42:64ff:feb5:ebc5",
|
||||
"netmask": "ffff:ffff:ffff:ffff::",
|
||||
"family": "IPv6",
|
||||
"scopeid": 5
|
||||
},
|
||||
{
|
||||
"name": "br-e929893879ec",
|
||||
"internal": false,
|
||||
"mac": "02:42:77:2b:e8:70",
|
||||
"address": "fe80::42:77ff:fe2b:e870",
|
||||
"netmask": "ffff:ffff:ffff:ffff::",
|
||||
"family": "IPv6",
|
||||
"scopeid": 6
|
||||
},
|
||||
{
|
||||
"name": "veth9f2842e",
|
||||
"internal": false,
|
||||
"mac": "02:97:03:9d:e0:38",
|
||||
"address": "fe80::97:3ff:fe9d:e038",
|
||||
"netmask": "ffff:ffff:ffff:ffff::",
|
||||
"family": "IPv6",
|
||||
"scopeid": 8
|
||||
},
|
||||
{
|
||||
"name": "veth009c2b9",
|
||||
"internal": false,
|
||||
"mac": "e2:7b:8b:06:cb:6a",
|
||||
"address": "fe80::e07b:8bff:fe06:cb6a",
|
||||
"netmask": "ffff:ffff:ffff:ffff::",
|
||||
"family": "IPv6",
|
||||
"scopeid": 10
|
||||
},
|
||||
{
|
||||
"name": "vethcfe1d35",
|
||||
"internal": false,
|
||||
"mac": "de:ee:14:2d:7e:e7",
|
||||
"address": "fe80::dcee:14ff:fe2d:7ee7",
|
||||
"netmask": "ffff:ffff:ffff:ffff::",
|
||||
"family": "IPv6",
|
||||
"scopeid": 12
|
||||
},
|
||||
{
|
||||
"name": "vethff03ba3",
|
||||
"internal": false,
|
||||
"mac": "0e:99:63:87:38:fc",
|
||||
"address": "fe80::c99:63ff:fe87:38fc",
|
||||
"netmask": "ffff:ffff:ffff:ffff::",
|
||||
"family": "IPv6",
|
||||
"scopeid": 14
|
||||
}
|
||||
],
|
||||
"host": "archlinux"
|
||||
},
|
||||
"javascriptStack": {
|
||||
"message": "No stack.",
|
||||
"stack": [
|
||||
"Unavailable."
|
||||
]
|
||||
},
|
||||
"nativeStack": [
|
||||
{
|
||||
"pc": "0x000055daf3226e8a",
|
||||
"symbol": "report::TriggerNodeReport(v8::Isolate*, node::Environment*, char const*, char const*, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, v8::Local<v8::String>) [/usr/bin/node]"
|
||||
},
|
||||
{
|
||||
"pc": "0x000055daf30e7d48",
|
||||
"symbol": "node::OnFatalError(char const*, char const*) [/usr/bin/node]"
|
||||
},
|
||||
{
|
||||
"pc": "0x000055daf325b382",
|
||||
"symbol": "v8::Utils::ReportOOMFailure(v8::internal::Isolate*, char const*, bool) [/usr/bin/node]"
|
||||
},
|
||||
{
|
||||
"pc": "0x000055daf325b5e8",
|
||||
"symbol": "v8::internal::V8::FatalProcessOutOfMemory(v8::internal::Isolate*, char const*, bool) [/usr/bin/node]"
|
||||
},
|
||||
{
|
||||
"pc": "0x000055daf33e5906",
|
||||
"symbol": " [/usr/bin/node]"
|
||||
},
|
||||
{
|
||||
"pc": "0x000055daf33e5a49",
|
||||
"symbol": " [/usr/bin/node]"
|
||||
},
|
||||
{
|
||||
"pc": "0x000055daf33f822d",
|
||||
"symbol": "v8::internal::Heap::PerformGarbageCollection(v8::internal::GarbageCollector, v8::GCCallbackFlags) [/usr/bin/node]"
|
||||
},
|
||||
{
|
||||
"pc": "0x000055daf33f8f58",
|
||||
"symbol": "v8::internal::Heap::CollectGarbage(v8::internal::AllocationSpace, v8::internal::GarbageCollectionReason, v8::GCCallbackFlags) [/usr/bin/node]"
|
||||
},
|
||||
{
|
||||
"pc": "0x000055daf33fb48c",
|
||||
"symbol": "v8::internal::Heap::AllocateRawWithLightRetrySlowPath(int, v8::internal::AllocationType, v8::internal::AllocationOrigin, v8::internal::AllocationAlignment) [/usr/bin/node]"
|
||||
},
|
||||
{
|
||||
"pc": "0x000055daf33fb4f4",
|
||||
"symbol": "v8::internal::Heap::AllocateRawWithRetryOrFailSlowPath(int, v8::internal::AllocationType, v8::internal::AllocationOrigin, v8::internal::AllocationAlignment) [/usr/bin/node]"
|
||||
},
|
||||
{
|
||||
"pc": "0x000055daf33c0396",
|
||||
"symbol": "v8::internal::Factory::AllocateRawWithImmortalMap(int, v8::internal::AllocationType, v8::internal::Map, v8::internal::AllocationAlignment) [/usr/bin/node]"
|
||||
},
|
||||
{
|
||||
"pc": "0x000055daf33c8fd0",
|
||||
"symbol": "v8::internal::Factory::NewRawTwoByteString(int, v8::internal::AllocationType) [/usr/bin/node]"
|
||||
},
|
||||
{
|
||||
"pc": "0x000055daf360c29e",
|
||||
"symbol": "v8::internal::String::SlowFlatten(v8::internal::Isolate*, v8::internal::Handle<v8::internal::ConsString>, v8::internal::AllocationType) [/usr/bin/node]"
|
||||
},
|
||||
{
|
||||
"pc": "0x000055daf360d86c",
|
||||
"symbol": "v8::internal::String::SlowEquals(v8::internal::Isolate*, v8::internal::Handle<v8::internal::String>, v8::internal::Handle<v8::internal::String>) [/usr/bin/node]"
|
||||
},
|
||||
{
|
||||
"pc": "0x000055daf37375ab",
|
||||
"symbol": "v8::internal::Runtime_StringEqual(int, unsigned long*, v8::internal::Isolate*) [/usr/bin/node]"
|
||||
},
|
||||
{
|
||||
"pc": "0x000055daf3a4abd9",
|
||||
"symbol": " [/usr/bin/node]"
|
||||
}
|
||||
],
|
||||
"javascriptHeap": {
|
||||
"totalMemory": 2152394752,
|
||||
"totalCommittedMemory": 2150767368,
|
||||
"usedMemory": 2135044960,
|
||||
"availableMemory": 47808640,
|
||||
"memoryLimit": 2197815296,
|
||||
"heapSpaces": {
|
||||
"read_only_space": {
|
||||
"memorySize": 262144,
|
||||
"committedMemory": 33328,
|
||||
"capacity": 33040,
|
||||
"used": 33040,
|
||||
"available": 0
|
||||
},
|
||||
"new_space": {
|
||||
"memorySize": 2097152,
|
||||
"committedMemory": 1114192,
|
||||
"capacity": 1047424,
|
||||
"used": 66000,
|
||||
"available": 981424
|
||||
},
|
||||
"old_space": {
|
||||
"memorySize": 2049843200,
|
||||
"committedMemory": 2049732712,
|
||||
"capacity": 2037853328,
|
||||
"used": 2037494080,
|
||||
"available": 359248
|
||||
},
|
||||
"code_space": {
|
||||
"memorySize": 10129408,
|
||||
"committedMemory": 9828000,
|
||||
"capacity": 8619200,
|
||||
"used": 8619200,
|
||||
"available": 0
|
||||
},
|
||||
"map_space": {
|
||||
"memorySize": 1052672,
|
||||
"committedMemory": 1048960,
|
||||
"capacity": 735040,
|
||||
"used": 735040,
|
||||
"available": 0
|
||||
},
|
||||
"large_object_space": {
|
||||
"memorySize": 88633344,
|
||||
"committedMemory": 88633344,
|
||||
"capacity": 87782784,
|
||||
"used": 87782784,
|
||||
"available": 0
|
||||
},
|
||||
"code_large_object_space": {
|
||||
"memorySize": 376832,
|
||||
"committedMemory": 376832,
|
||||
"capacity": 314816,
|
||||
"used": 314816,
|
||||
"available": 0
|
||||
},
|
||||
"new_large_object_space": {
|
||||
"memorySize": 0,
|
||||
"committedMemory": 0,
|
||||
"capacity": 1047424,
|
||||
"used": 0,
|
||||
"available": 1047424
|
||||
}
|
||||
}
|
||||
},
|
||||
"resourceUsage": {
|
||||
"userCpuSeconds": 2203.37,
|
||||
"kernelCpuSeconds": 38.1817,
|
||||
"cpuConsumptionPercent": 34.1127,
|
||||
"maxRss": 2532282368,
|
||||
"pageFaults": {
|
||||
"IORequired": 22,
|
||||
"IONotRequired": 7984554
|
||||
},
|
||||
"fsActivity": {
|
||||
"reads": 194080,
|
||||
"writes": 24
|
||||
}
|
||||
},
|
||||
"uvthreadResourceUsage": {
|
||||
"userCpuSeconds": 1428.9,
|
||||
"kernelCpuSeconds": 15.9159,
|
||||
"cpuConsumptionPercent": 21.9878,
|
||||
"fsActivity": {
|
||||
"reads": 194080,
|
||||
"writes": 24
|
||||
}
|
||||
},
|
||||
"libuv": [
|
||||
],
|
||||
"environmentVariables": {
|
||||
"COLORTERM": "truecolor",
|
||||
"DBUS_SESSION_BUS_ADDRESS": "unix:path=/run/user/1000/bus",
|
||||
"DESKTOP_SESSION": "awesome",
|
||||
"DISPLAY": ":0.0",
|
||||
"EDITOR": "nano",
|
||||
"FZF_DEFAULT_COMMAND": "ag --hidden --ignore .git -g \"\"",
|
||||
"GDMSESSION": "awesome",
|
||||
"GO111MODULE": "on",
|
||||
"GOBIN": "/home/jordan/go/bin",
|
||||
"GREP_COLOR": "37;45",
|
||||
"GREP_COLORS": "mt=37;45",
|
||||
"GTK_MODULES": "canberra-gtk-module",
|
||||
"HOME": "/home/jordan",
|
||||
"LANG": "C",
|
||||
"LESS": "-F -g -i -M -R -S -w -X -z-4",
|
||||
"LESS_TERMCAP_mb": "\u001b[01;31m",
|
||||
"LESS_TERMCAP_md": "\u001b[01;31m",
|
||||
"LESS_TERMCAP_me": "\u001b[0m",
|
||||
"LESS_TERMCAP_se": "\u001b[0m",
|
||||
"LESS_TERMCAP_so": "\u001b[00;47;30m",
|
||||
"LESS_TERMCAP_ue": "\u001b[0m",
|
||||
"LESS_TERMCAP_us": "\u001b[01;32m",
|
||||
"LOGNAME": "jordan",
|
||||
"LS_COLORS": "rs=0:di=01;34:ln=01;36:mh=00:pi=40;33:so=01;35:do=01;35:bd=40;33;01:cd=40;33;01:or=40;31;01:mi=00:su=37;41:sg=30;43:ca=30;41:tw=30;42:ow=34;42:st=37;44:ex=01;32:*.tar=01;31:*.tgz=01;31:*.arc=01;31:*.arj=01;31:*.taz=01;31:*.lha=01;31:*.lz4=01;31:*.lzh=01;31:*.lzma=01;31:*.tlz=01;31:*.txz=01;31:*.tzo=01;31:*.t7z=01;31:*.zip=01;31:*.z=01;31:*.dz=01;31:*.gz=01;31:*.lrz=01;31:*.lz=01;31:*.lzo=01;31:*.xz=01;31:*.zst=01;31:*.tzst=01;31:*.bz2=01;31:*.bz=01;31:*.tbz=01;31:*.tbz2=01;31:*.tz=01;31:*.deb=01;31:*.rpm=01;31:*.jar=01;31:*.war=01;31:*.ear=01;31:*.sar=01;31:*.rar=01;31:*.alz=01;31:*.ace=01;31:*.zoo=01;31:*.cpio=01;31:*.7z=01;31:*.rz=01;31:*.cab=01;31:*.wim=01;31:*.swm=01;31:*.dwm=01;31:*.esd=01;31:*.jpg=01;35:*.jpeg=01;35:*.mjpg=01;35:*.mjpeg=01;35:*.gif=01;35:*.bmp=01;35:*.pbm=01;35:*.pgm=01;35:*.ppm=01;35:*.tga=01;35:*.xbm=01;35:*.xpm=01;35:*.tif=01;35:*.tiff=01;35:*.png=01;35:*.svg=01;35:*.svgz=01;35:*.mng=01;35:*.pcx=01;35:*.mov=01;35:*.mpg=01;35:*.mpeg=01;35:*.m2v=01;35:*.mkv=01;35:*.webm=01;35:*.ogm=01;35:*.mp4=01;35:*.m4v=01;35:*.mp4v=01;35:*.vob=01;35:*.qt=01;35:*.nuv=01;35:*.wmv=01;35:*.asf=01;35:*.rm=01;35:*.rmvb=01;35:*.flc=01;35:*.avi=01;35:*.fli=01;35:*.flv=01;35:*.gl=01;35:*.dl=01;35:*.xcf=01;35:*.xwd=01;35:*.yuv=01;35:*.cgm=01;35:*.emf=01;35:*.ogv=01;35:*.ogx=01;35:*.aac=00;36:*.au=00;36:*.flac=00;36:*.m4a=00;36:*.mid=00;36:*.midi=00;36:*.mka=00;36:*.mp3=00;36:*.mpc=00;36:*.ogg=00;36:*.ra=00;36:*.wav=00;36:*.oga=00;36:*.opus=00;36:*.spx=00;36:*.xspf=00;36:",
|
||||
"MAIL": "/var/spool/mail/jordan",
|
||||
"OLDPWD": "/home/jordan/Projects/project-citadel/web",
|
||||
"PAGER": "less",
|
||||
"PATH": "/home/jordan/.local/bin:/usr/local/bin:/usr/local/sbin:/home/nightwolf/Programs/cmake/bin:/home/nightwolf/Programs/idea-IU-163.13906.18/bin:/home/nightwolf/Programs/wpcli:/home/nightwolf/neovim/bin:/home/nightwolf/Programs/Postman:/home/nightwolf/Programs/Android_SDK/tools/bin:/home/nightwolf/Development/PhantomJS/bin:/home/nightwolf/Programs/node/bin:/home/nightwolf/pyenv/bin:/home/nightwolf/Programs/vv:/usr/bin:/bin:/usr/lib/jvm/default/bin:/usr/bin/site_perl:/usr/bin/vendor_perl:/usr/bin/core_perl:/usr/local/go/bin:/home/jordan/go/bin:/home/jordan/.garden/bin:~/Programs/node/bin:~/.utilities:/home/jordan/.fzf/bin:/home/jordan/.gem/ruby/2.6.0/bin:/home/jordan/.garden/bin:~/Programs/node/bin:~/.utilities:/home/jordan/.gem/ruby/2.6.0/bin",
|
||||
"PWD": "/home/jordan/Projects/project-citadel/web",
|
||||
"SHELL": "/usr/bin/zsh",
|
||||
"SHLVL": "2",
|
||||
"SSH_AGENT_PID": "2150",
|
||||
"SSH_AUTH_SOCK": "/tmp/ssh-agent.sock.1000",
|
||||
"TERM": "xterm-256color",
|
||||
"TMUX": "/tmp//tmux-1000/default,2216,1",
|
||||
"TMUX_PANE": "%2",
|
||||
"USER": "jordan",
|
||||
"VIRTUALENVWRAPPER_PYTHON": "/usr/bin/python3",
|
||||
"VIRTUAL_ENV_DISABLE_PROMPT": "12",
|
||||
"VISUAL": "nano",
|
||||
"VTE_VERSION": "5602",
|
||||
"WINDOWID": "6291459",
|
||||
"WORKON_HOME": "/home/jordan/.virtualenvs",
|
||||
"XAUTHORITY": "/home/jordan/.Xauthority",
|
||||
"XDG_GREETER_DATA_DIR": "/var/lib/lightdm-data/jordan",
|
||||
"XDG_RUNTIME_DIR": "/run/user/1000",
|
||||
"XDG_SEAT": "seat0",
|
||||
"XDG_SEAT_PATH": "/org/freedesktop/DisplayManager/Seat0",
|
||||
"XDG_SESSION_CLASS": "user",
|
||||
"XDG_SESSION_DESKTOP": "awesome",
|
||||
"XDG_SESSION_ID": "1",
|
||||
"XDG_SESSION_PATH": "/org/freedesktop/DisplayManager/Session0",
|
||||
"XDG_SESSION_TYPE": "x11",
|
||||
"XDG_VTNR": "7",
|
||||
"_": "/usr/bin/nvim",
|
||||
"is_vim": "ps -o state= -o comm= -t '#{pane_tty}' | grep -iqE '^[^TXZ ]+ +(\\S+\\/)?g?(view|n?vim?x?)(diff)?$'",
|
||||
"tmux_version": "$(tmux -V | sed -En \"s/^tmux ([0-9]+(.[0-9]+)?).*/\\1/p\")",
|
||||
"LC_MESSAGES": "",
|
||||
"VIMRUNTIME": "/usr/share/nvim/runtime",
|
||||
"NVIM_LISTEN_ADDRESS": "/tmp/nvimGEyAE0/0",
|
||||
"MYVIMRC": "/home/jordan/.config/nvim/init.vim",
|
||||
"COC_VIMCONFIG": "/home/jordan/.config/nvim",
|
||||
"COC_DATA_HOME": "/home/jordan/.config/coc",
|
||||
"TSS_LOG": "-level verbose -file /tmp/coc-nvim-tsc.log",
|
||||
"NODE_PATH": "/home/jordan/Projects/project-citadel/web/node_modules"
|
||||
},
|
||||
"userLimits": {
|
||||
"core_file_size_blocks": {
|
||||
"soft": "unlimited",
|
||||
"hard": "unlimited"
|
||||
},
|
||||
"data_seg_size_kbytes": {
|
||||
"soft": "unlimited",
|
||||
"hard": "unlimited"
|
||||
},
|
||||
"file_size_blocks": {
|
||||
"soft": "unlimited",
|
||||
"hard": "unlimited"
|
||||
},
|
||||
"max_locked_memory_bytes": {
|
||||
"soft": 65536,
|
||||
"hard": 65536
|
||||
},
|
||||
"max_memory_size_kbytes": {
|
||||
"soft": "unlimited",
|
||||
"hard": "unlimited"
|
||||
},
|
||||
"open_files": {
|
||||
"soft": 524288,
|
||||
"hard": 524288
|
||||
},
|
||||
"stack_size_bytes": {
|
||||
"soft": 8388608,
|
||||
"hard": "unlimited"
|
||||
},
|
||||
"cpu_time_seconds": {
|
||||
"soft": "unlimited",
|
||||
"hard": "unlimited"
|
||||
},
|
||||
"max_user_processes": {
|
||||
"soft": 31138,
|
||||
"hard": 31138
|
||||
},
|
||||
"virtual_memory_kbytes": {
|
||||
"soft": "unlimited",
|
||||
"hard": "unlimited"
|
||||
}
|
||||
},
|
||||
"sharedObjects": [
|
||||
"linux-vdso.so.1",
|
||||
"/usr/lib/libz.so.1",
|
||||
"/usr/lib/libcares.so.2",
|
||||
"/usr/lib/libnghttp2.so.14",
|
||||
"/usr/lib/libcrypto.so.1.1",
|
||||
"/usr/lib/libssl.so.1.1",
|
||||
"/usr/lib/libicui18n.so.65",
|
||||
"/usr/lib/libicuuc.so.65",
|
||||
"/usr/lib/libdl.so.2",
|
||||
"/usr/lib/libstdc++.so.6",
|
||||
"/usr/lib/libm.so.6",
|
||||
"/usr/lib/libgcc_s.so.1",
|
||||
"/usr/lib/libpthread.so.0",
|
||||
"/usr/lib/libc.so.6",
|
||||
"/usr/lib/libicudata.so.65",
|
||||
"/lib64/ld-linux-x86-64.so.2"
|
||||
]
|
||||
}
|
498
web/report.20200703.192901.99868.0.001.json
Normal file
498
web/report.20200703.192901.99868.0.001.json
Normal file
@ -0,0 +1,498 @@
|
||||
|
||||
{
|
||||
"header": {
|
||||
"reportVersion": 1,
|
||||
"event": "Allocation failed - JavaScript heap out of memory",
|
||||
"trigger": "FatalError",
|
||||
"filename": "report.20200703.192901.99868.0.001.json",
|
||||
"dumpEventTime": "2020-07-03T19:29:01Z",
|
||||
"dumpEventTimeStamp": "1593822541435",
|
||||
"processId": 99868,
|
||||
"cwd": "/home/jordan/Projects/project-citadel/web",
|
||||
"commandLine": [
|
||||
"/usr/bin/node",
|
||||
"/home/jordan/.config/coc/extensions/node_modules/coc-tsserver/bin/tsserverForkStart",
|
||||
"/home/jordan/Projects/project-citadel/web/node_modules/typescript/lib/tsserver.js",
|
||||
"--allowLocalPluginLoads",
|
||||
"--useInferredProjectPerProjectRoot",
|
||||
"--cancellationPipeName",
|
||||
"/tmp/coc-nvim-tscancellation-c8c6c50b271560f15471.sock*",
|
||||
"--npmLocation",
|
||||
"\"/usr/bin/npm\"",
|
||||
"--noGetErrOnBackgroundUpdate",
|
||||
"--validateDefaultNpmLocation"
|
||||
],
|
||||
"nodejsVersion": "v13.8.0",
|
||||
"glibcVersionRuntime": "2.30",
|
||||
"glibcVersionCompiler": "2.30",
|
||||
"wordSize": 64,
|
||||
"arch": "x64",
|
||||
"platform": "linux",
|
||||
"componentVersions": {
|
||||
"node": "13.8.0",
|
||||
"v8": "7.9.317.25-node.28",
|
||||
"uv": "1.34.1",
|
||||
"zlib": "1.2.11",
|
||||
"brotli": "1.0.7",
|
||||
"ares": "1.15.0",
|
||||
"modules": "79",
|
||||
"nghttp2": "1.39.2",
|
||||
"napi": "5",
|
||||
"llhttp": "2.0.4",
|
||||
"openssl": "1.1.1d",
|
||||
"cldr": "36.0",
|
||||
"icu": "65.1",
|
||||
"tz": "2019c",
|
||||
"unicode": "12.1"
|
||||
},
|
||||
"release": {
|
||||
"name": "node",
|
||||
"headersUrl": "https://nodejs.org/download/release/v13.8.0/node-v13.8.0-headers.tar.gz",
|
||||
"sourceUrl": "https://nodejs.org/download/release/v13.8.0/node-v13.8.0.tar.gz"
|
||||
},
|
||||
"osName": "Linux",
|
||||
"osRelease": "4.19.101-1-lts",
|
||||
"osVersion": "#1 SMP Sat, 01 Feb 2020 16:35:36 +0000",
|
||||
"osMachine": "x86_64",
|
||||
"cpus": [
|
||||
{
|
||||
"model": "Intel(R) Core(TM) i7-6500U CPU @ 2.50GHz",
|
||||
"speed": 2800,
|
||||
"user": 49033300,
|
||||
"nice": 14200,
|
||||
"sys": 10239800,
|
||||
"idle": 199777400,
|
||||
"irq": 1327100
|
||||
},
|
||||
{
|
||||
"model": "Intel(R) Core(TM) i7-6500U CPU @ 2.50GHz",
|
||||
"speed": 2800,
|
||||
"user": 46034200,
|
||||
"nice": 20700,
|
||||
"sys": 9673500,
|
||||
"idle": 173927400,
|
||||
"irq": 721000
|
||||
},
|
||||
{
|
||||
"model": "Intel(R) Core(TM) i7-6500U CPU @ 2.50GHz",
|
||||
"speed": 2800,
|
||||
"user": 46463200,
|
||||
"nice": 15400,
|
||||
"sys": 9416800,
|
||||
"idle": 174061400,
|
||||
"irq": 597100
|
||||
},
|
||||
{
|
||||
"model": "Intel(R) Core(TM) i7-6500U CPU @ 2.50GHz",
|
||||
"speed": 2800,
|
||||
"user": 46337200,
|
||||
"nice": 14900,
|
||||
"sys": 9474300,
|
||||
"idle": 174305900,
|
||||
"irq": 487800
|
||||
}
|
||||
],
|
||||
"networkInterfaces": [
|
||||
{
|
||||
"name": "lo",
|
||||
"internal": true,
|
||||
"mac": "00:00:00:00:00:00",
|
||||
"address": "127.0.0.1",
|
||||
"netmask": "255.0.0.0",
|
||||
"family": "IPv4"
|
||||
},
|
||||
{
|
||||
"name": "wlp3s0",
|
||||
"internal": false,
|
||||
"mac": "7c:b0:c2:fe:93:86",
|
||||
"address": "192.168.43.5",
|
||||
"netmask": "255.255.255.0",
|
||||
"family": "IPv4"
|
||||
},
|
||||
{
|
||||
"name": "docker0",
|
||||
"internal": false,
|
||||
"mac": "02:42:84:c7:8c:b4",
|
||||
"address": "172.17.0.1",
|
||||
"netmask": "255.255.0.0",
|
||||
"family": "IPv4"
|
||||
},
|
||||
{
|
||||
"name": "br-e929893879ec",
|
||||
"internal": false,
|
||||
"mac": "02:42:c6:97:95:8c",
|
||||
"address": "172.19.0.1",
|
||||
"netmask": "255.255.0.0",
|
||||
"family": "IPv4"
|
||||
},
|
||||
{
|
||||
"name": "lo",
|
||||
"internal": true,
|
||||
"mac": "00:00:00:00:00:00",
|
||||
"address": "::1",
|
||||
"netmask": "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff",
|
||||
"family": "IPv6",
|
||||
"scopeid": 0
|
||||
},
|
||||
{
|
||||
"name": "wlp3s0",
|
||||
"internal": false,
|
||||
"mac": "7c:b0:c2:fe:93:86",
|
||||
"address": "2600:100b:b018:172f:7eb0:c2ff:fefe:9386",
|
||||
"netmask": "ffff:ffff:ffff:ffff::",
|
||||
"family": "IPv6",
|
||||
"scopeid": 0
|
||||
},
|
||||
{
|
||||
"name": "wlp3s0",
|
||||
"internal": false,
|
||||
"mac": "7c:b0:c2:fe:93:86",
|
||||
"address": "2600:100b:b009:7105:7eb0:c2ff:fefe:9386",
|
||||
"netmask": "ffff:ffff:ffff:ffff::",
|
||||
"family": "IPv6",
|
||||
"scopeid": 0
|
||||
},
|
||||
{
|
||||
"name": "wlp3s0",
|
||||
"internal": false,
|
||||
"mac": "7c:b0:c2:fe:93:86",
|
||||
"address": "fe80::7eb0:c2ff:fefe:9386",
|
||||
"netmask": "ffff:ffff:ffff:ffff::",
|
||||
"family": "IPv6",
|
||||
"scopeid": 3
|
||||
},
|
||||
{
|
||||
"name": "docker0",
|
||||
"internal": false,
|
||||
"mac": "02:42:84:c7:8c:b4",
|
||||
"address": "fe80::42:84ff:fec7:8cb4",
|
||||
"netmask": "ffff:ffff:ffff:ffff::",
|
||||
"family": "IPv6",
|
||||
"scopeid": 5
|
||||
},
|
||||
{
|
||||
"name": "br-e929893879ec",
|
||||
"internal": false,
|
||||
"mac": "02:42:c6:97:95:8c",
|
||||
"address": "fe80::42:c6ff:fe97:958c",
|
||||
"netmask": "ffff:ffff:ffff:ffff::",
|
||||
"family": "IPv6",
|
||||
"scopeid": 6
|
||||
},
|
||||
{
|
||||
"name": "veth861c75f",
|
||||
"internal": false,
|
||||
"mac": "de:7f:bb:fc:33:a0",
|
||||
"address": "fe80::dc7f:bbff:fefc:33a0",
|
||||
"netmask": "ffff:ffff:ffff:ffff::",
|
||||
"family": "IPv6",
|
||||
"scopeid": 8
|
||||
},
|
||||
{
|
||||
"name": "veth40b666f",
|
||||
"internal": false,
|
||||
"mac": "5e:46:25:1a:79:73",
|
||||
"address": "fe80::5c46:25ff:fe1a:7973",
|
||||
"netmask": "ffff:ffff:ffff:ffff::",
|
||||
"family": "IPv6",
|
||||
"scopeid": 10
|
||||
},
|
||||
{
|
||||
"name": "vetha03af75",
|
||||
"internal": false,
|
||||
"mac": "7e:23:c2:9d:e8:db",
|
||||
"address": "fe80::7c23:c2ff:fe9d:e8db",
|
||||
"netmask": "ffff:ffff:ffff:ffff::",
|
||||
"family": "IPv6",
|
||||
"scopeid": 12
|
||||
},
|
||||
{
|
||||
"name": "vethb492e80",
|
||||
"internal": false,
|
||||
"mac": "de:af:a3:79:1e:9a",
|
||||
"address": "fe80::dcaf:a3ff:fe79:1e9a",
|
||||
"netmask": "ffff:ffff:ffff:ffff::",
|
||||
"family": "IPv6",
|
||||
"scopeid": 14
|
||||
}
|
||||
],
|
||||
"host": "archlinux"
|
||||
},
|
||||
"javascriptStack": {
|
||||
"message": "No stack.",
|
||||
"stack": [
|
||||
"Unavailable."
|
||||
]
|
||||
},
|
||||
"nativeStack": [
|
||||
{
|
||||
"pc": "0x000055c2d7ceae8a",
|
||||
"symbol": "report::TriggerNodeReport(v8::Isolate*, node::Environment*, char const*, char const*, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, v8::Local<v8::String>) [/usr/bin/node]"
|
||||
},
|
||||
{
|
||||
"pc": "0x000055c2d7babd48",
|
||||
"symbol": "node::OnFatalError(char const*, char const*) [/usr/bin/node]"
|
||||
},
|
||||
{
|
||||
"pc": "0x000055c2d7d1f382",
|
||||
"symbol": "v8::Utils::ReportOOMFailure(v8::internal::Isolate*, char const*, bool) [/usr/bin/node]"
|
||||
},
|
||||
{
|
||||
"pc": "0x000055c2d7d1f5e8",
|
||||
"symbol": "v8::internal::V8::FatalProcessOutOfMemory(v8::internal::Isolate*, char const*, bool) [/usr/bin/node]"
|
||||
},
|
||||
{
|
||||
"pc": "0x000055c2d7ea9906",
|
||||
"symbol": " [/usr/bin/node]"
|
||||
},
|
||||
{
|
||||
"pc": "0x000055c2d7ea9a49",
|
||||
"symbol": " [/usr/bin/node]"
|
||||
},
|
||||
{
|
||||
"pc": "0x000055c2d7ebc22d",
|
||||
"symbol": "v8::internal::Heap::PerformGarbageCollection(v8::internal::GarbageCollector, v8::GCCallbackFlags) [/usr/bin/node]"
|
||||
},
|
||||
{
|
||||
"pc": "0x000055c2d7ebcf58",
|
||||
"symbol": "v8::internal::Heap::CollectGarbage(v8::internal::AllocationSpace, v8::internal::GarbageCollectionReason, v8::GCCallbackFlags) [/usr/bin/node]"
|
||||
},
|
||||
{
|
||||
"pc": "0x000055c2d7ebf48c",
|
||||
"symbol": "v8::internal::Heap::AllocateRawWithLightRetrySlowPath(int, v8::internal::AllocationType, v8::internal::AllocationOrigin, v8::internal::AllocationAlignment) [/usr/bin/node]"
|
||||
},
|
||||
{
|
||||
"pc": "0x000055c2d7ebf4f4",
|
||||
"symbol": "v8::internal::Heap::AllocateRawWithRetryOrFailSlowPath(int, v8::internal::AllocationType, v8::internal::AllocationOrigin, v8::internal::AllocationAlignment) [/usr/bin/node]"
|
||||
},
|
||||
{
|
||||
"pc": "0x000055c2d7e8499b",
|
||||
"symbol": "v8::internal::Factory::NewFillerObject(int, bool, v8::internal::AllocationType, v8::internal::AllocationOrigin) [/usr/bin/node]"
|
||||
},
|
||||
{
|
||||
"pc": "0x000055c2d81b5540",
|
||||
"symbol": "v8::internal::Runtime_AllocateInYoungGeneration(int, unsigned long*, v8::internal::Isolate*) [/usr/bin/node]"
|
||||
},
|
||||
{
|
||||
"pc": "0x000055c2d850ebd9",
|
||||
"symbol": " [/usr/bin/node]"
|
||||
}
|
||||
],
|
||||
"javascriptHeap": {
|
||||
"totalMemory": 2152599552,
|
||||
"totalCommittedMemory": 2151011168,
|
||||
"usedMemory": 2136228312,
|
||||
"availableMemory": 47169120,
|
||||
"memoryLimit": 2197815296,
|
||||
"heapSpaces": {
|
||||
"read_only_space": {
|
||||
"memorySize": 262144,
|
||||
"committedMemory": 33328,
|
||||
"capacity": 33040,
|
||||
"used": 33040,
|
||||
"available": 0
|
||||
},
|
||||
"new_space": {
|
||||
"memorySize": 2097152,
|
||||
"committedMemory": 1353624,
|
||||
"capacity": 1047424,
|
||||
"used": 336544,
|
||||
"available": 710880
|
||||
},
|
||||
"old_space": {
|
||||
"memorySize": 2037784576,
|
||||
"committedMemory": 2037430360,
|
||||
"capacity": 2026077792,
|
||||
"used": 2025882720,
|
||||
"available": 195072
|
||||
},
|
||||
"code_space": {
|
||||
"memorySize": 6721536,
|
||||
"committedMemory": 6463424,
|
||||
"capacity": 5718144,
|
||||
"used": 5718144,
|
||||
"available": 0
|
||||
},
|
||||
"map_space": {
|
||||
"memorySize": 1052672,
|
||||
"committedMemory": 1048960,
|
||||
"capacity": 737680,
|
||||
"used": 737680,
|
||||
"available": 0
|
||||
},
|
||||
"large_object_space": {
|
||||
"memorySize": 104304640,
|
||||
"committedMemory": 104304640,
|
||||
"capacity": 103205528,
|
||||
"used": 103205528,
|
||||
"available": 0
|
||||
},
|
||||
"code_large_object_space": {
|
||||
"memorySize": 376832,
|
||||
"committedMemory": 376832,
|
||||
"capacity": 314656,
|
||||
"used": 314656,
|
||||
"available": 0
|
||||
},
|
||||
"new_large_object_space": {
|
||||
"memorySize": 0,
|
||||
"committedMemory": 0,
|
||||
"capacity": 1047424,
|
||||
"used": 0,
|
||||
"available": 1047424
|
||||
}
|
||||
}
|
||||
},
|
||||
"resourceUsage": {
|
||||
"userCpuSeconds": 2108.75,
|
||||
"kernelCpuSeconds": 34.8424,
|
||||
"cpuConsumptionPercent": 31.044,
|
||||
"maxRss": 2328186880,
|
||||
"pageFaults": {
|
||||
"IORequired": 32,
|
||||
"IONotRequired": 6292470
|
||||
},
|
||||
"fsActivity": {
|
||||
"reads": 250312,
|
||||
"writes": 24
|
||||
}
|
||||
},
|
||||
"uvthreadResourceUsage": {
|
||||
"userCpuSeconds": 1298.13,
|
||||
"kernelCpuSeconds": 16.4946,
|
||||
"cpuConsumptionPercent": 19.0388,
|
||||
"fsActivity": {
|
||||
"reads": 250312,
|
||||
"writes": 24
|
||||
}
|
||||
},
|
||||
"libuv": [
|
||||
],
|
||||
"environmentVariables": {
|
||||
"COLORTERM": "truecolor",
|
||||
"DBUS_SESSION_BUS_ADDRESS": "unix:path=/run/user/1000/bus",
|
||||
"DESKTOP_SESSION": "awesome",
|
||||
"DISPLAY": ":0.0",
|
||||
"EDITOR": "nano",
|
||||
"FZF_DEFAULT_COMMAND": "ag --hidden --ignore .git -g \"\"",
|
||||
"GDMSESSION": "awesome",
|
||||
"GO111MODULE": "on",
|
||||
"GOBIN": "/home/jordan/go/bin",
|
||||
"GREP_COLOR": "37;45",
|
||||
"GREP_COLORS": "mt=37;45",
|
||||
"GTK_MODULES": "canberra-gtk-module",
|
||||
"HOME": "/home/jordan",
|
||||
"LANG": "C",
|
||||
"LESS": "-F -g -i -M -R -S -w -X -z-4",
|
||||
"LESS_TERMCAP_mb": "\u001b[01;31m",
|
||||
"LESS_TERMCAP_md": "\u001b[01;31m",
|
||||
"LESS_TERMCAP_me": "\u001b[0m",
|
||||
"LESS_TERMCAP_se": "\u001b[0m",
|
||||
"LESS_TERMCAP_so": "\u001b[00;47;30m",
|
||||
"LESS_TERMCAP_ue": "\u001b[0m",
|
||||
"LESS_TERMCAP_us": "\u001b[01;32m",
|
||||
"LOGNAME": "jordan",
|
||||
"LS_COLORS": "rs=0:di=01;34:ln=01;36:mh=00:pi=40;33:so=01;35:do=01;35:bd=40;33;01:cd=40;33;01:or=40;31;01:mi=00:su=37;41:sg=30;43:ca=30;41:tw=30;42:ow=34;42:st=37;44:ex=01;32:*.tar=01;31:*.tgz=01;31:*.arc=01;31:*.arj=01;31:*.taz=01;31:*.lha=01;31:*.lz4=01;31:*.lzh=01;31:*.lzma=01;31:*.tlz=01;31:*.txz=01;31:*.tzo=01;31:*.t7z=01;31:*.zip=01;31:*.z=01;31:*.dz=01;31:*.gz=01;31:*.lrz=01;31:*.lz=01;31:*.lzo=01;31:*.xz=01;31:*.zst=01;31:*.tzst=01;31:*.bz2=01;31:*.bz=01;31:*.tbz=01;31:*.tbz2=01;31:*.tz=01;31:*.deb=01;31:*.rpm=01;31:*.jar=01;31:*.war=01;31:*.ear=01;31:*.sar=01;31:*.rar=01;31:*.alz=01;31:*.ace=01;31:*.zoo=01;31:*.cpio=01;31:*.7z=01;31:*.rz=01;31:*.cab=01;31:*.wim=01;31:*.swm=01;31:*.dwm=01;31:*.esd=01;31:*.jpg=01;35:*.jpeg=01;35:*.mjpg=01;35:*.mjpeg=01;35:*.gif=01;35:*.bmp=01;35:*.pbm=01;35:*.pgm=01;35:*.ppm=01;35:*.tga=01;35:*.xbm=01;35:*.xpm=01;35:*.tif=01;35:*.tiff=01;35:*.png=01;35:*.svg=01;35:*.svgz=01;35:*.mng=01;35:*.pcx=01;35:*.mov=01;35:*.mpg=01;35:*.mpeg=01;35:*.m2v=01;35:*.mkv=01;35:*.webm=01;35:*.ogm=01;35:*.mp4=01;35:*.m4v=01;35:*.mp4v=01;35:*.vob=01;35:*.qt=01;35:*.nuv=01;35:*.wmv=01;35:*.asf=01;35:*.rm=01;35:*.rmvb=01;35:*.flc=01;35:*.avi=01;35:*.fli=01;35:*.flv=01;35:*.gl=01;35:*.dl=01;35:*.xcf=01;35:*.xwd=01;35:*.yuv=01;35:*.cgm=01;35:*.emf=01;35:*.ogv=01;35:*.ogx=01;35:*.aac=00;36:*.au=00;36:*.flac=00;36:*.m4a=00;36:*.mid=00;36:*.midi=00;36:*.mka=00;36:*.mp3=00;36:*.mpc=00;36:*.ogg=00;36:*.ra=00;36:*.wav=00;36:*.oga=00;36:*.opus=00;36:*.spx=00;36:*.xspf=00;36:",
|
||||
"MAIL": "/var/spool/mail/jordan",
|
||||
"OLDPWD": "/home/jordan/Projects/project-citadel/web",
|
||||
"PAGER": "less",
|
||||
"PATH": "/home/jordan/.local/bin:/usr/local/bin:/usr/local/sbin:/home/nightwolf/Programs/cmake/bin:/home/nightwolf/Programs/idea-IU-163.13906.18/bin:/home/nightwolf/Programs/wpcli:/home/nightwolf/neovim/bin:/home/nightwolf/Programs/Postman:/home/nightwolf/Programs/Android_SDK/tools/bin:/home/nightwolf/Development/PhantomJS/bin:/home/nightwolf/Programs/node/bin:/home/nightwolf/pyenv/bin:/home/nightwolf/Programs/vv:/usr/bin:/bin:/usr/lib/jvm/default/bin:/usr/bin/site_perl:/usr/bin/vendor_perl:/usr/bin/core_perl:/usr/local/go/bin:/home/jordan/go/bin:/home/jordan/.garden/bin:~/Programs/node/bin:~/.utilities:/home/jordan/.fzf/bin:/home/jordan/.gem/ruby/2.6.0/bin:/home/jordan/.garden/bin:~/Programs/node/bin:~/.utilities:/home/jordan/.gem/ruby/2.6.0/bin",
|
||||
"PWD": "/home/jordan/Projects/project-citadel/web",
|
||||
"SHELL": "/usr/bin/zsh",
|
||||
"SHLVL": "2",
|
||||
"SSH_AGENT_PID": "1475",
|
||||
"SSH_AUTH_SOCK": "/tmp/ssh-agent.sock.1000",
|
||||
"TERM": "xterm-256color",
|
||||
"TMUX": "/tmp//tmux-1000/default,1930,1",
|
||||
"TMUX_PANE": "%3",
|
||||
"USER": "jordan",
|
||||
"VIRTUALENVWRAPPER_PYTHON": "/usr/bin/python3",
|
||||
"VIRTUAL_ENV_DISABLE_PROMPT": "12",
|
||||
"VISUAL": "nano",
|
||||
"VTE_VERSION": "5602",
|
||||
"WINDOWID": "6291459",
|
||||
"WORKON_HOME": "/home/jordan/.virtualenvs",
|
||||
"XAUTHORITY": "/home/jordan/.Xauthority",
|
||||
"XDG_GREETER_DATA_DIR": "/var/lib/lightdm-data/jordan",
|
||||
"XDG_RUNTIME_DIR": "/run/user/1000",
|
||||
"XDG_SEAT": "seat0",
|
||||
"XDG_SEAT_PATH": "/org/freedesktop/DisplayManager/Seat0",
|
||||
"XDG_SESSION_CLASS": "user",
|
||||
"XDG_SESSION_DESKTOP": "awesome",
|
||||
"XDG_SESSION_ID": "1",
|
||||
"XDG_SESSION_PATH": "/org/freedesktop/DisplayManager/Session0",
|
||||
"XDG_SESSION_TYPE": "x11",
|
||||
"XDG_VTNR": "7",
|
||||
"_": "/usr/bin/nvim",
|
||||
"is_vim": "ps -o state= -o comm= -t '#{pane_tty}' | grep -iqE '^[^TXZ ]+ +(\\S+\\/)?g?(view|n?vim?x?)(diff)?$'",
|
||||
"tmux_version": "$(tmux -V | sed -En \"s/^tmux ([0-9]+(.[0-9]+)?).*/\\1/p\")",
|
||||
"LC_MESSAGES": "",
|
||||
"VIMRUNTIME": "/usr/share/nvim/runtime",
|
||||
"NVIM_LISTEN_ADDRESS": "/tmp/nvimerL06q/0",
|
||||
"MYVIMRC": "/home/jordan/.config/nvim/init.vim",
|
||||
"COC_VIMCONFIG": "/home/jordan/.config/nvim",
|
||||
"COC_DATA_HOME": "/home/jordan/.config/coc",
|
||||
"TSS_LOG": "-level verbose -file /tmp/coc-nvim-tsc.log",
|
||||
"NODE_PATH": "/home/jordan/Projects/project-citadel/web/node_modules"
|
||||
},
|
||||
"userLimits": {
|
||||
"core_file_size_blocks": {
|
||||
"soft": "unlimited",
|
||||
"hard": "unlimited"
|
||||
},
|
||||
"data_seg_size_kbytes": {
|
||||
"soft": "unlimited",
|
||||
"hard": "unlimited"
|
||||
},
|
||||
"file_size_blocks": {
|
||||
"soft": "unlimited",
|
||||
"hard": "unlimited"
|
||||
},
|
||||
"max_locked_memory_bytes": {
|
||||
"soft": 65536,
|
||||
"hard": 65536
|
||||
},
|
||||
"max_memory_size_kbytes": {
|
||||
"soft": "unlimited",
|
||||
"hard": "unlimited"
|
||||
},
|
||||
"open_files": {
|
||||
"soft": 524288,
|
||||
"hard": 524288
|
||||
},
|
||||
"stack_size_bytes": {
|
||||
"soft": 8388608,
|
||||
"hard": "unlimited"
|
||||
},
|
||||
"cpu_time_seconds": {
|
||||
"soft": "unlimited",
|
||||
"hard": "unlimited"
|
||||
},
|
||||
"max_user_processes": {
|
||||
"soft": 31137,
|
||||
"hard": 31137
|
||||
},
|
||||
"virtual_memory_kbytes": {
|
||||
"soft": "unlimited",
|
||||
"hard": "unlimited"
|
||||
}
|
||||
},
|
||||
"sharedObjects": [
|
||||
"linux-vdso.so.1",
|
||||
"/usr/lib/libz.so.1",
|
||||
"/usr/lib/libcares.so.2",
|
||||
"/usr/lib/libnghttp2.so.14",
|
||||
"/usr/lib/libcrypto.so.1.1",
|
||||
"/usr/lib/libssl.so.1.1",
|
||||
"/usr/lib/libicui18n.so.65",
|
||||
"/usr/lib/libicuuc.so.65",
|
||||
"/usr/lib/libdl.so.2",
|
||||
"/usr/lib/libstdc++.so.6",
|
||||
"/usr/lib/libm.so.6",
|
||||
"/usr/lib/libgcc_s.so.1",
|
||||
"/usr/lib/libpthread.so.0",
|
||||
"/usr/lib/libc.so.6",
|
||||
"/usr/lib/libicudata.so.65",
|
||||
"/lib64/ld-linux-x86-64.so.2"
|
||||
]
|
||||
}
|
@ -1,20 +1,57 @@
|
||||
import React, { useEffect } from 'react';
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import Admin from 'shared/components/Admin';
|
||||
import Select from 'shared/components/Select';
|
||||
import GlobalTopNavbar from 'App/TopNavbar';
|
||||
import { useUsersQuery, useCreateUserAccountMutation, UsersDocument } from 'shared/generated/graphql';
|
||||
import {
|
||||
useUsersQuery,
|
||||
useDeleteUserAccountMutation,
|
||||
useCreateUserAccountMutation,
|
||||
UsersDocument,
|
||||
UsersQuery,
|
||||
} from 'shared/generated/graphql';
|
||||
import Input from 'shared/components/Input';
|
||||
import styled from 'styled-components';
|
||||
import Button from 'shared/components/Button';
|
||||
import { useForm } from 'react-hook-form';
|
||||
import { usePopup, Popup } from 'shared/components/PopupMenu';
|
||||
import produce from 'immer';
|
||||
import updateApolloCache from 'shared/utils/cache';
|
||||
|
||||
const DeleteUserWrapper = styled.div`
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
`;
|
||||
|
||||
const DeleteUserDescription = styled.p`
|
||||
font-size: 14px;
|
||||
`;
|
||||
|
||||
const DeleteUserButton = styled(Button)`
|
||||
margin-top: 6px;
|
||||
padding: 6px 12px;
|
||||
width: 100%;
|
||||
`;
|
||||
|
||||
type DeleteUserPopupProps = {
|
||||
onDeleteUser: () => void;
|
||||
};
|
||||
const DeleteUserPopup: React.FC<DeleteUserPopupProps> = ({ onDeleteUser }) => {
|
||||
return (
|
||||
<DeleteUserWrapper>
|
||||
<DeleteUserDescription>Deleting this user will remove all user related data.</DeleteUserDescription>
|
||||
<DeleteUserButton onClick={() => onDeleteUser()} color="danger">
|
||||
Delete user
|
||||
</DeleteUserButton>
|
||||
</DeleteUserWrapper>
|
||||
);
|
||||
};
|
||||
type CreateUserData = {
|
||||
email: string;
|
||||
username: string;
|
||||
fullName: string;
|
||||
initials: string;
|
||||
password: string;
|
||||
roleCode: string;
|
||||
};
|
||||
const CreateUserForm = styled.form`
|
||||
display: flex;
|
||||
@ -34,11 +71,16 @@ const InputError = styled.span`
|
||||
color: rgba(${props => props.theme.colors.danger});
|
||||
font-size: 12px;
|
||||
`;
|
||||
|
||||
type AddUserPopupProps = {
|
||||
onAddUser: (user: CreateUserData) => void;
|
||||
};
|
||||
|
||||
const AddUserPopup: React.FC<AddUserPopupProps> = ({ onAddUser }) => {
|
||||
const { register, handleSubmit, errors } = useForm<CreateUserData>();
|
||||
const { register, handleSubmit, errors, setValue } = useForm<CreateUserData>();
|
||||
const [role, setRole] = useState<string | null>(null);
|
||||
register({ name: 'roleCode' }, { required: true });
|
||||
|
||||
const createUser = (data: CreateUserData) => {
|
||||
onAddUser(data);
|
||||
};
|
||||
@ -63,6 +105,18 @@ const AddUserPopup: React.FC<AddUserPopupProps> = ({ onAddUser }) => {
|
||||
variant="alternate"
|
||||
ref={register({ required: 'Email is required' })}
|
||||
/>
|
||||
<Select
|
||||
label="Role"
|
||||
value={role}
|
||||
options={[
|
||||
{ label: 'Admin', value: 'admin' },
|
||||
{ label: 'Member', value: 'member' },
|
||||
]}
|
||||
onChange={newRole => {
|
||||
setRole(newRole);
|
||||
setValue('roleCode', newRole.value);
|
||||
}}
|
||||
/>
|
||||
{errors.email && <InputError>{errors.email.message}</InputError>}
|
||||
<AddUserInput
|
||||
floatingLabel
|
||||
@ -105,6 +159,15 @@ const AdminRoute = () => {
|
||||
}, []);
|
||||
const { loading, data } = useUsersQuery();
|
||||
const { showPopup, hidePopup } = usePopup();
|
||||
const [deleteUser] = useDeleteUserAccountMutation({
|
||||
update: (client, response) => {
|
||||
updateApolloCache<UsersQuery>(client, UsersDocument, cache =>
|
||||
produce(cache, draftCache => {
|
||||
draftCache.users = cache.users.filter(u => u.id !== response.data.deleteUserAccount.userAccount.id);
|
||||
}),
|
||||
);
|
||||
},
|
||||
});
|
||||
const [createUser] = useCreateUserAccountMutation({
|
||||
update: (client, createData) => {
|
||||
const cacheData: any = client.readQuery({
|
||||
@ -133,8 +196,21 @@ const AdminRoute = () => {
|
||||
<GlobalTopNavbar projectID={null} onSaveProjectName={() => {}} name={null} />
|
||||
<Admin
|
||||
initialTab={1}
|
||||
users={data.users.map((user: any) => ({ ...user, role: 'TBD' }))}
|
||||
users={data.users}
|
||||
onInviteUser={() => {}}
|
||||
onDeleteUser={($target, userID) => {
|
||||
showPopup(
|
||||
$target,
|
||||
<Popup tab={0} title="Delete user?" onClose={() => hidePopup()}>
|
||||
<DeleteUserPopup
|
||||
onDeleteUser={() => {
|
||||
deleteUser({ variables: { userID } });
|
||||
hidePopup();
|
||||
}}
|
||||
/>
|
||||
</Popup>,
|
||||
);
|
||||
}}
|
||||
onAddUser={$target => {
|
||||
showPopup(
|
||||
$target,
|
||||
|
@ -1,11 +1,12 @@
|
||||
import React, { useState, useContext, useEffect } from 'react';
|
||||
import TopNavbar from 'shared/components/TopNavbar';
|
||||
import TopNavbar, { MenuItem } from 'shared/components/TopNavbar';
|
||||
import styled from 'styled-components/macro';
|
||||
import DropdownMenu, { ProfileMenu } from 'shared/components/DropdownMenu';
|
||||
import ProjectSettings, { DeleteConfirm, DELETE_INFO } from 'shared/components/ProjectSettings';
|
||||
import { useHistory } from 'react-router';
|
||||
import UserIDContext from 'App/context';
|
||||
import {
|
||||
RoleCode,
|
||||
useMeQuery,
|
||||
useDeleteProjectMutation,
|
||||
useGetProjectsQuery,
|
||||
@ -219,32 +220,38 @@ export const ProjectPopup: React.FC<ProjectPopupProps> = ({ history, name, proje
|
||||
type GlobalTopNavbarProps = {
|
||||
nameOnly?: boolean;
|
||||
projectID: string | null;
|
||||
onChangeProjectOwner?: (userID: string) => void;
|
||||
name: string | null;
|
||||
initialTab?: number;
|
||||
currentTab?: number;
|
||||
popupContent?: JSX.Element;
|
||||
menuType?: Array<string>;
|
||||
menuType?: Array<MenuItem>;
|
||||
onChangeRole?: (userID: string, roleCode: RoleCode) => void;
|
||||
projectMembers?: null | Array<TaskUser>;
|
||||
onSaveProjectName?: (projectName: string) => void;
|
||||
onInviteUser?: ($target: React.RefObject<HTMLElement>) => void;
|
||||
onSetTab?: (tab: number) => void;
|
||||
onRemoveFromBoard?: (userID: string) => void;
|
||||
};
|
||||
|
||||
const GlobalTopNavbar: React.FC<GlobalTopNavbarProps> = ({
|
||||
initialTab,
|
||||
currentTab,
|
||||
onSetTab,
|
||||
menuType,
|
||||
projectID,
|
||||
onChangeProjectOwner,
|
||||
onChangeRole,
|
||||
name,
|
||||
popupContent,
|
||||
projectMembers,
|
||||
onInviteUser,
|
||||
onSaveProjectName,
|
||||
onRemoveFromBoard,
|
||||
nameOnly,
|
||||
}) => {
|
||||
console.log(popupContent);
|
||||
const { loading, data } = useMeQuery();
|
||||
const { showPopup, hidePopup, setTab } = usePopup();
|
||||
const history = useHistory();
|
||||
const [currentTab, setCurrentTab] = useState(initialTab);
|
||||
useEffect(() => {
|
||||
setCurrentTab(initialTab);
|
||||
}, [initialTab]);
|
||||
const { userID, setUserID } = useContext(UserIDContext);
|
||||
const onLogout = () => {
|
||||
fetch('http://localhost:3333/auth/logout', {
|
||||
@ -305,7 +312,12 @@ const GlobalTopNavbar: React.FC<GlobalTopNavbarProps> = ({
|
||||
}}
|
||||
currentTab={currentTab}
|
||||
user={data ? data.me : null}
|
||||
onInviteUser={onInviteUser}
|
||||
onChangeRole={onChangeRole}
|
||||
onChangeProjectOwner={onChangeProjectOwner}
|
||||
onNotificationClick={() => {}}
|
||||
onSetTab={onSetTab}
|
||||
onRemoveFromBoard={onRemoveFromBoard}
|
||||
onDashboardClick={() => {
|
||||
history.push('/');
|
||||
}}
|
||||
|
@ -53,7 +53,7 @@ const Projects = () => {
|
||||
<GlobalTopNavbar projectID={null} onSaveProjectName={() => {}} name={null} />
|
||||
{!loading && data && (
|
||||
<Settings
|
||||
profile={data.me.profileIcon}
|
||||
profile={data.me}
|
||||
onProfileAvatarChange={() => {
|
||||
if ($fileUpload && $fileUpload.current) {
|
||||
$fileUpload.current.click();
|
||||
|
@ -305,14 +305,12 @@ const Details: React.FC<DetailsProps> = ({
|
||||
}}
|
||||
onMemberProfile={($targetRef, memberID) => {
|
||||
const member = data.findTask.assigned.find(m => m.id === memberID);
|
||||
const profileIcon = member ? member.profileIcon : null;
|
||||
if (member) {
|
||||
showPopup(
|
||||
$targetRef,
|
||||
<Popup title={null} onClose={() => {}} tab={0}>
|
||||
<MiniProfile
|
||||
profileIcon={profileIcon}
|
||||
displayName="Jordan Knott"
|
||||
username="@jordanthedev"
|
||||
user={member}
|
||||
bio="None"
|
||||
onRemoveFromTask={() => {
|
||||
unassignTask({ variables: { taskID: data.findTask.id, userID: userID ?? '' } });
|
||||
@ -320,6 +318,7 @@ const Details: React.FC<DetailsProps> = ({
|
||||
/>
|
||||
</Popup>,
|
||||
);
|
||||
}
|
||||
}}
|
||||
onOpenAddMemberPopup={(task, $targetRef) => {
|
||||
showPopup(
|
||||
|
@ -6,8 +6,12 @@ import GlobalTopNavbar, { ProjectPopup } from 'App/TopNavbar';
|
||||
import styled, { css } from 'styled-components/macro';
|
||||
import { Bolt, ToggleOn, Tags, CheckCircle, Sort, Filter } from 'shared/icons';
|
||||
import { usePopup, Popup } from 'shared/components/PopupMenu';
|
||||
import { useParams, Route, useRouteMatch, useHistory, RouteComponentProps } from 'react-router-dom';
|
||||
import { useParams, Route, useRouteMatch, useHistory, RouteComponentProps, useLocation } from 'react-router-dom';
|
||||
import {
|
||||
useSetProjectOwnerMutation,
|
||||
useUpdateProjectMemberRoleMutation,
|
||||
useCreateProjectMemberMutation,
|
||||
useDeleteProjectMemberMutation,
|
||||
useSetTaskCompleteMutation,
|
||||
useToggleTaskLabelMutation,
|
||||
useUpdateProjectNameMutation,
|
||||
@ -30,6 +34,7 @@ import {
|
||||
useUnassignTaskMutation,
|
||||
useUpdateTaskDueDateMutation,
|
||||
FindProjectQuery,
|
||||
useUsersQuery,
|
||||
} from 'shared/generated/graphql';
|
||||
|
||||
import TaskAssignee from 'shared/components/TaskAssignee';
|
||||
@ -48,25 +53,51 @@ import Details from './Details';
|
||||
import { useApolloClient } from '@apollo/react-hooks';
|
||||
import UserIDContext from 'App/context';
|
||||
import DueDateManager from 'shared/components/DueDateManager';
|
||||
import Input from 'shared/components/Input';
|
||||
import Member from 'shared/components/Member';
|
||||
|
||||
const getCacheData = (client: any, projectID: string) => {
|
||||
const cacheData: FindProjectQuery = client.readQuery({
|
||||
query: FindProjectDocument,
|
||||
variables: {
|
||||
projectId: projectID,
|
||||
},
|
||||
});
|
||||
return cacheData;
|
||||
const SearchInput = styled(Input)`
|
||||
margin: 0;
|
||||
`;
|
||||
|
||||
const UserMember = styled(Member)`
|
||||
padding: 4px 0;
|
||||
cursor: pointer;
|
||||
&:hover {
|
||||
background: rgba(${props => props.theme.colors.bg.primary}, 0.4);
|
||||
}
|
||||
border-radius: 6px;
|
||||
`;
|
||||
|
||||
const MemberList = styled.div`
|
||||
margin: 8px 0;
|
||||
`;
|
||||
|
||||
type UserManagementPopupProps = {
|
||||
users: Array<User>;
|
||||
projectMembers: Array<TaskUser>;
|
||||
onAddProjectMember: (userID: string) => void;
|
||||
};
|
||||
|
||||
const writeCacheData = (client: any, projectID: string, cacheData: any, newData: any) => {
|
||||
client.writeQuery({
|
||||
query: FindProjectDocument,
|
||||
variables: {
|
||||
projectId: projectID,
|
||||
},
|
||||
data: { ...cacheData, findProject: newData },
|
||||
});
|
||||
const UserManagementPopup: React.FC<UserManagementPopupProps> = ({ users, projectMembers, onAddProjectMember }) => {
|
||||
return (
|
||||
<Popup tab={0} title="Invite a user">
|
||||
<SearchInput width="100%" variant="alternate" placeholder="Email address or name" name="search" />
|
||||
<MemberList>
|
||||
{users
|
||||
.filter(u => u.id !== projectMembers.find(p => p.id === u.id)?.id)
|
||||
.map(user => (
|
||||
<UserMember
|
||||
key={user.id}
|
||||
onCardMemberClick={() => onAddProjectMember(user.id)}
|
||||
showName
|
||||
member={user}
|
||||
taskID=""
|
||||
/>
|
||||
))}
|
||||
</MemberList>
|
||||
</Popup>
|
||||
);
|
||||
};
|
||||
|
||||
type TaskRouteProps = {
|
||||
@ -300,6 +331,7 @@ const Project = () => {
|
||||
},
|
||||
});
|
||||
const [updateTaskGroupLocation] = useUpdateTaskGroupLocationMutation({});
|
||||
const [updateProjectMemberRole] = useUpdateProjectMemberRoleMutation();
|
||||
|
||||
const [deleteTaskGroup] = useDeleteTaskGroupMutation({
|
||||
onCompleted: deletedTaskGroupData => {},
|
||||
@ -492,9 +524,39 @@ const Project = () => {
|
||||
});
|
||||
|
||||
const [setTaskComplete] = useSetTaskCompleteMutation();
|
||||
const [createProjectMember] = useCreateProjectMemberMutation({
|
||||
update: (client, response) => {
|
||||
updateApolloCache<FindProjectQuery>(
|
||||
client,
|
||||
FindProjectDocument,
|
||||
cache =>
|
||||
produce(cache, draftCache => {
|
||||
draftCache.findProject.members.push({ ...response.data.createProjectMember.member });
|
||||
}),
|
||||
{ projectId: projectID },
|
||||
);
|
||||
},
|
||||
});
|
||||
const [setProjectOwner] = useSetProjectOwnerMutation();
|
||||
const [deleteProjectMember] = useDeleteProjectMemberMutation({
|
||||
update: (client, response) => {
|
||||
updateApolloCache<FindProjectQuery>(
|
||||
client,
|
||||
FindProjectDocument,
|
||||
cache =>
|
||||
produce(cache, draftCache => {
|
||||
draftCache.findProject.members = cache.findProject.members.filter(
|
||||
m => m.id !== response.data.deleteProjectMember.member.id,
|
||||
);
|
||||
}),
|
||||
{ projectId: projectID },
|
||||
);
|
||||
},
|
||||
});
|
||||
|
||||
const client = useApolloClient();
|
||||
const { userID } = useContext(UserIDContext);
|
||||
const location = useLocation();
|
||||
|
||||
const { showPopup, hidePopup } = usePopup();
|
||||
const $labelsRef = useRef<HTMLDivElement>(null);
|
||||
@ -546,12 +608,35 @@ const Project = () => {
|
||||
return (
|
||||
<>
|
||||
<GlobalTopNavbar
|
||||
onChangeRole={(userID, roleCode) => {
|
||||
updateProjectMemberRole({ variables: { userID, roleCode, projectID } });
|
||||
}}
|
||||
onChangeProjectOwner={uid => {
|
||||
setProjectOwner({ variables: { ownerID: uid, projectID } });
|
||||
hidePopup();
|
||||
}}
|
||||
onRemoveFromBoard={userID => {
|
||||
deleteProjectMember({ variables: { userID, projectID } });
|
||||
hidePopup();
|
||||
}}
|
||||
onSaveProjectName={projectName => {
|
||||
updateProjectName({ variables: { projectID, name: projectName } });
|
||||
}}
|
||||
onInviteUser={$target => {
|
||||
showPopup(
|
||||
$target,
|
||||
<UserManagementPopup
|
||||
onAddProjectMember={userID => {
|
||||
createProjectMember({ variables: { userID, projectID } });
|
||||
}}
|
||||
users={data.users}
|
||||
projectMembers={data.findProject.members}
|
||||
/>,
|
||||
);
|
||||
}}
|
||||
popupContent={<ProjectPopup history={history} name={data.findProject.name} projectID={projectID} />}
|
||||
menuType={MENU_TYPES.PROJECT_MENU}
|
||||
initialTab={0}
|
||||
menuType={[{ name: 'Board', link: location.pathname }]}
|
||||
currentTab={0}
|
||||
projectMembers={data.findProject.members}
|
||||
projectID={projectID}
|
||||
name={data.findProject.name}
|
||||
@ -647,27 +732,18 @@ const Project = () => {
|
||||
onCreateTaskGroup={onCreateList}
|
||||
onCardMemberClick={($targetRef, taskID, memberID) => {
|
||||
const member = data.findProject.members.find(m => m.id === memberID);
|
||||
const profileIcon = member ? member.profileIcon : null;
|
||||
if (member) {
|
||||
showPopup(
|
||||
$targetRef,
|
||||
<Popup
|
||||
title={null}
|
||||
onClose={() => {
|
||||
hidePopup();
|
||||
}}
|
||||
tab={0}
|
||||
>
|
||||
<MiniProfile
|
||||
profileIcon={profileIcon}
|
||||
displayName="Jordan Knott"
|
||||
username="@jordanthedev"
|
||||
user={member}
|
||||
bio="None"
|
||||
onRemoveFromTask={() => {
|
||||
/* unassignTask({ variables: { taskID: data.findTask.id, userID: userID ?? '' } }); */
|
||||
}}
|
||||
/>
|
||||
</Popup>,
|
||||
/>,
|
||||
);
|
||||
}
|
||||
}}
|
||||
onChangeTaskGroupName={(taskGroupID, name) => {
|
||||
updateTaskGroupName({ variables: { taskGroupID, name } });
|
||||
@ -715,21 +791,18 @@ const Project = () => {
|
||||
}}
|
||||
onCardMemberClick={($targetRef, taskID, memberID) => {
|
||||
const member = data.findProject.members.find(m => m.id === memberID);
|
||||
const profileIcon = member ? member.profileIcon : null;
|
||||
if (member) {
|
||||
showPopup(
|
||||
$targetRef,
|
||||
<Popup title={null} onClose={() => hidePopup()} tab={0}>
|
||||
<MiniProfile
|
||||
profileIcon={profileIcon}
|
||||
displayName="Jordan Knott"
|
||||
username="@jordanthedev"
|
||||
bio="None"
|
||||
user={member}
|
||||
onRemoveFromTask={() => {
|
||||
/* unassignTask({ variables: { taskID: data.findTask.id, userID: userID ?? '' } }); */
|
||||
}}
|
||||
/>
|
||||
</Popup>,
|
||||
/>,
|
||||
);
|
||||
}
|
||||
}}
|
||||
onOpenLabelsPopup={($targetRef, task) => {
|
||||
taskLabelsRef.current = task.labels;
|
||||
|
@ -1,6 +1,7 @@
|
||||
import React, { useState, useContext, useEffect } from 'react';
|
||||
import styled from 'styled-components/macro';
|
||||
import GlobalTopNavbar from 'App/TopNavbar';
|
||||
import Empty from 'shared/undraw/Empty';
|
||||
import {
|
||||
useCreateTeamMutation,
|
||||
useGetProjectsQuery,
|
||||
@ -20,7 +21,27 @@ import { useForm } from 'react-hook-form';
|
||||
import Input from 'shared/components/Input';
|
||||
import updateApolloCache from 'shared/utils/cache';
|
||||
import produce from 'immer';
|
||||
const EmptyStateContent = styled.div`
|
||||
display: flex;
|
||||
justy-content: center;
|
||||
align-items: center;
|
||||
flex-direction: column;
|
||||
`;
|
||||
|
||||
const EmptyStateTitle = styled.h3`
|
||||
color: #fff;
|
||||
font-size: 18px;
|
||||
`;
|
||||
|
||||
const EmptyStatePrompt = styled.span`
|
||||
color: rgba(${props => props.theme.colors.text.primary});
|
||||
font-size: 16px;
|
||||
margin-top: 8px;
|
||||
`;
|
||||
const EmptyState = styled(Empty)`
|
||||
display: block;
|
||||
margin: 0 auto;
|
||||
`;
|
||||
const CreateTeamButton = styled(Button)`
|
||||
width: 100%;
|
||||
`;
|
||||
@ -193,6 +214,10 @@ const AddTeamButton = styled(Button)`
|
||||
top: 6px;
|
||||
right: 12px;
|
||||
`;
|
||||
|
||||
const CreateFirstTeam = styled(Button)`
|
||||
margin-top: 8px;
|
||||
`;
|
||||
type ShowNewProject = {
|
||||
open: boolean;
|
||||
initialTeamID: null | string;
|
||||
@ -277,6 +302,39 @@ const Projects = () => {
|
||||
>
|
||||
Add Team
|
||||
</AddTeamButton>
|
||||
{projectTeams.length === 0 && (
|
||||
<EmptyStateContent>
|
||||
<EmptyState width={425} height={425} />
|
||||
<EmptyStateTitle>No teams exist</EmptyStateTitle>
|
||||
<EmptyStatePrompt>Create a new team to get started</EmptyStatePrompt>
|
||||
<CreateFirstTeam
|
||||
variant="outline"
|
||||
onClick={$target => {
|
||||
showPopup(
|
||||
$target,
|
||||
<Popup
|
||||
title="Create team"
|
||||
tab={0}
|
||||
onClose={() => {
|
||||
hidePopup();
|
||||
}}
|
||||
>
|
||||
<CreateTeamForm
|
||||
onCreateTeam={teamName => {
|
||||
if (organizationID) {
|
||||
createTeam({ variables: { name: teamName, organizationID } });
|
||||
hidePopup();
|
||||
}
|
||||
}}
|
||||
/>
|
||||
</Popup>,
|
||||
);
|
||||
}}
|
||||
>
|
||||
Create new team
|
||||
</CreateFirstTeam>
|
||||
</EmptyStateContent>
|
||||
)}
|
||||
{projectTeams.map(team => {
|
||||
return (
|
||||
<div key={team.id}>
|
||||
@ -286,10 +344,10 @@ const Projects = () => {
|
||||
<SectionActionLink to={`/teams/${team.id}`}>
|
||||
<SectionAction variant="outline">Projects</SectionAction>
|
||||
</SectionActionLink>
|
||||
<SectionActionLink to="/">
|
||||
<SectionActionLink to={`/teams/${team.id}/members`}>
|
||||
<SectionAction variant="outline">Members</SectionAction>
|
||||
</SectionActionLink>
|
||||
<SectionActionLink to="/">
|
||||
<SectionActionLink to={`/teams/${team.id}/settings`}>
|
||||
<SectionAction variant="outline">Settings</SectionAction>
|
||||
</SectionActionLink>
|
||||
</SectionActions>
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user