This commit is contained in:
@@ -9,5 +9,6 @@ rpdata-*
|
||||
!rpdata-*/
|
||||
.vscode
|
||||
|
||||
/graph2/graphcore/*_gen.go
|
||||
generated.gql
|
||||
generated.go
|
||||
@@ -8,14 +8,17 @@ import (
|
||||
"runtime/debug"
|
||||
"strings"
|
||||
|
||||
"git.aiterp.net/rpdata/api/database"
|
||||
"git.aiterp.net/rpdata/api/graph2"
|
||||
"git.aiterp.net/rpdata/api/internal/auth"
|
||||
"git.aiterp.net/rpdata/api/internal/config"
|
||||
"git.aiterp.net/rpdata/api/internal/instrumentation"
|
||||
"git.aiterp.net/rpdata/api/internal/loader"
|
||||
"git.aiterp.net/rpdata/api/internal/store"
|
||||
"git.aiterp.net/rpdata/api/models"
|
||||
"git.aiterp.net/rpdata/api/models/changes"
|
||||
"git.aiterp.net/rpdata/api/models/logs"
|
||||
"git.aiterp.net/rpdata/api/services"
|
||||
"github.com/99designs/gqlgen/handler"
|
||||
"github.com/prometheus/client_golang/prometheus/promhttp"
|
||||
)
|
||||
@@ -26,10 +29,17 @@ func main() {
|
||||
log.Fatalln("Failed to init store:", err)
|
||||
}
|
||||
|
||||
repos, stopFn, err := database.Init(config.Global().Database)
|
||||
if err != nil {
|
||||
log.Fatalln("Failed to init db:", err)
|
||||
}
|
||||
defer stopFn()
|
||||
services := services.NewBundle(repos)
|
||||
|
||||
instrumentation.Register()
|
||||
|
||||
http.Handle("/", handler.Playground("RPData API", "/graphql"))
|
||||
http.Handle("/graphql", queryHandler())
|
||||
http.Handle("/graphql", queryHandler(services))
|
||||
|
||||
http.Handle("/metrics", promhttp.Handler())
|
||||
|
||||
@@ -77,9 +87,9 @@ func logListedChanges() {
|
||||
log.Println("Change subscription closed.")
|
||||
}
|
||||
|
||||
func queryHandler() http.HandlerFunc {
|
||||
func queryHandler(services *services.Bundle) http.HandlerFunc {
|
||||
handler := handler.GraphQL(
|
||||
graph2.New(),
|
||||
graph2.New(services),
|
||||
handler.RecoverFunc(func(ctx context.Context, err interface{}) error {
|
||||
log.Println(err)
|
||||
log.Println(string(debug.Stack()))
|
||||
@@ -90,7 +100,6 @@ func queryHandler() http.HandlerFunc {
|
||||
handler.RequestMiddleware(instrumentation.RequestMiddleware()),
|
||||
handler.ResolverMiddleware(instrumentation.ResolverMiddleware()),
|
||||
)
|
||||
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
l := loader.New()
|
||||
r = r.WithContext(l.ToContext(r.Context()))
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
package database
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"git.aiterp.net/rpdata/api/database/mongodb"
|
||||
"git.aiterp.net/rpdata/api/internal/config"
|
||||
"git.aiterp.net/rpdata/api/repositories"
|
||||
)
|
||||
|
||||
// ErrDriverUnrecognized is returned if the driver is not recognized
|
||||
var ErrDriverUnrecognized = errors.New("Driver not recognized, check your config or update rpdata")
|
||||
|
||||
// Init sets up the database.
|
||||
func Init(config config.Database) (bundle *repositories.Bundle, closeFn func() error, err error) {
|
||||
switch config.Driver {
|
||||
case "mongo", "mgo", "mongodb":
|
||||
return mongodb.Init(config)
|
||||
default:
|
||||
return nil, nil, ErrDriverUnrecognized
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
package mongodb
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"git.aiterp.net/rpdata/api/internal/config"
|
||||
"git.aiterp.net/rpdata/api/repositories"
|
||||
"github.com/globalsign/mgo"
|
||||
)
|
||||
|
||||
// Init initializes the mongodb database
|
||||
func Init(cfg config.Database) (bundle *repositories.Bundle, closeFn func() error, err error) {
|
||||
port := cfg.Port
|
||||
if port <= 0 {
|
||||
port = 27017
|
||||
}
|
||||
|
||||
session, err := mgo.DialWithInfo(&mgo.DialInfo{
|
||||
Addrs: []string{fmt.Sprintf("%s:%d", cfg.Host, port)},
|
||||
Timeout: 30 * time.Second,
|
||||
Database: cfg.Db,
|
||||
Username: cfg.Username,
|
||||
Password: cfg.Password,
|
||||
Mechanism: cfg.Mechanism,
|
||||
Source: cfg.Db,
|
||||
})
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
db := session.DB(cfg.Db)
|
||||
|
||||
bundle = &repositories.Bundle{
|
||||
Tags: newTagRepository(db),
|
||||
}
|
||||
|
||||
closeFn = func() error {
|
||||
session.Close()
|
||||
return nil
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
package mongodb
|
||||
|
||||
import (
|
||||
"context"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"git.aiterp.net/rpdata/api/models"
|
||||
"git.aiterp.net/rpdata/api/repositories"
|
||||
"github.com/globalsign/mgo"
|
||||
"go.mongodb.org/mongo-driver/bson"
|
||||
)
|
||||
|
||||
type tagRepository struct {
|
||||
stories *mgo.Collection
|
||||
}
|
||||
|
||||
func newTagRepository(db *mgo.Database) repositories.TagRepository {
|
||||
return &tagRepository{
|
||||
stories: db.C("story.stories"),
|
||||
}
|
||||
}
|
||||
|
||||
func (r *tagRepository) Find(ctx context.Context, kind, name string) (*models.Tag, error) {
|
||||
tags := make([]*models.Tag, 0, 1)
|
||||
err := r.stories.Find(bson.M{"listed": true, "tags": bson.M{"kind": kind, "name": name}}).Distinct("tag", &tags)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
} else if len(tags) == 0 {
|
||||
return nil, repositories.ErrNotFound
|
||||
}
|
||||
|
||||
return tags[0], nil
|
||||
}
|
||||
|
||||
func (r *tagRepository) List(ctx context.Context, filter models.TagFilter) ([]*models.Tag, error) {
|
||||
tags := make([]*models.Tag, 0, 64)
|
||||
|
||||
query := bson.M{"listed": true, "tags": bson.M{"$ne": nil}}
|
||||
if filter.Kind != nil {
|
||||
query["tags.kind"] = *filter.Kind
|
||||
}
|
||||
|
||||
err := r.stories.Find(query).Distinct("tags", &tags)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if filter.Kind != nil {
|
||||
// While it's unsorted, delete any incorrect tags with replacement.
|
||||
for i := 0; i < len(tags); i++ {
|
||||
if tags[i].Kind != *filter.Kind {
|
||||
tags[i] = tags[len(tags)-1]
|
||||
tags = tags[:len(tags)-1]
|
||||
i--
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sort.Slice(tags, func(i, j int) bool {
|
||||
if filter.Kind == nil {
|
||||
kindCmp := strings.Compare(string(tags[i].Kind), string(tags[j].Kind))
|
||||
if kindCmp != 0 {
|
||||
return kindCmp < 0
|
||||
}
|
||||
}
|
||||
|
||||
return strings.Compare(tags[i].Name, tags[j].Name) < 0
|
||||
})
|
||||
|
||||
return tags, nil
|
||||
}
|
||||
@@ -13,6 +13,7 @@ require (
|
||||
github.com/go-ini/ini v1.35.0
|
||||
github.com/go-sql-driver/mysql v1.4.0
|
||||
github.com/golang/protobuf v1.3.1 // indirect
|
||||
github.com/google/go-cmp v0.3.0 // indirect
|
||||
github.com/gorilla/websocket v1.4.0
|
||||
github.com/graph-gophers/dataloader v0.0.0-20180104184831-78139374585c
|
||||
github.com/hashicorp/golang-lru v0.5.0
|
||||
@@ -28,8 +29,10 @@ require (
|
||||
github.com/prometheus/procfs v0.0.0-20190517135640-51af30a78b0e // indirect
|
||||
github.com/sirupsen/logrus v1.2.0
|
||||
github.com/stretchr/testify v1.3.0
|
||||
github.com/tidwall/pretty v1.0.0 // indirect
|
||||
github.com/urfave/cli v1.20.0
|
||||
github.com/vektah/gqlparser v1.1.2
|
||||
go.mongodb.org/mongo-driver v1.0.3
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2
|
||||
golang.org/x/net v0.0.0-20190514140710-3ec191127204
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a
|
||||
|
||||
@@ -13,12 +13,14 @@ github.com/agnivade/levenshtein v1.0.1 h1:3oJU7J3FGFmyhn8KHjmVaZCN5hxTr7GxgRue+s
|
||||
github.com/agnivade/levenshtein v1.0.1/go.mod h1:CURSv5d9Uaml+FovSIICkLbAUZ9S4RqaHDIsdSBg7lM=
|
||||
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 h1:bvNMNQO63//z+xNgfBlViaCIJKLlCJ6/fmUseuG0wVQ=
|
||||
github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8=
|
||||
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
|
||||
github.com/beorn7/perks v1.0.0 h1:HWo1m869IqiPhD389kmkxeTalrjNbbJTC8LXupb+sl0=
|
||||
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
|
||||
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
|
||||
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/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=
|
||||
@@ -34,12 +36,15 @@ github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9
|
||||
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
|
||||
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-stack/stack v1.8.0 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk=
|
||||
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
||||
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/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.1 h1:YF8+flBXS5eO826T4nzqPrxfhQThhXl0YzfuUPu4SBg=
|
||||
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/google/go-cmp v0.3.0 h1:crn/baboCvb5fXaQ0IJ1SGTsTVrWpDsCWC8EGETZijY=
|
||||
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||
github.com/gorilla/context v0.0.0-20160226214623-1ea25387ff6f/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg=
|
||||
github.com/gorilla/mux v1.6.1/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
|
||||
github.com/gorilla/websocket v1.2.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
|
||||
@@ -54,8 +59,10 @@ github.com/jmoiron/sqlx v0.0.0-20180614180643-0dae4fefe7c0/go.mod h1:IiEW3SEiiEr
|
||||
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1/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/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
|
||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU=
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
|
||||
@@ -73,6 +80,7 @@ github.com/pkg/errors v0.8.0 h1:WdK/asTD0HN+q6hsWO3/vpuAkAr+tw6aNJNDFFf0+qw=
|
||||
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/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 h1:K47Rk0v/fkEfwfQet2KWhscE0cJzjgCCDBG2KHZoVno=
|
||||
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
|
||||
@@ -91,6 +99,7 @@ github.com/prometheus/procfs v0.0.0-20190517135640-51af30a78b0e h1:zK8d1aZ+gw/Ne
|
||||
github.com/prometheus/procfs v0.0.0-20190517135640-51af30a78b0e/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
|
||||
github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
|
||||
github.com/rs/cors v1.6.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU=
|
||||
github.com/sergi/go-diff v1.0.0 h1:Kpca3qRNrduNnOQeazBd0ysaKrUJiIuISHxogkT9RPQ=
|
||||
github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
|
||||
github.com/shurcooL/httpfs v0.0.0-20171119174359-809beceb2371/go.mod h1:ZY1cvUeJuFPAdZ/B6v7RHavJWZn2YPVFQ1OSXhCGOkg=
|
||||
github.com/shurcooL/vfsgen v0.0.0-20180121065927-ffb13db8def0/go.mod h1:TrYk7fJVaAttu97ZZKrO9UbRa8izdowaMIZcxYMbVaw=
|
||||
@@ -101,7 +110,10 @@ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+
|
||||
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
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 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/tidwall/pretty v1.0.0 h1:HsD+QiTn7sK6flMKIvNmpqz1qrpP3Ps6jOKIKMooyg4=
|
||||
github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk=
|
||||
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/vektah/dataloaden v0.2.0/go.mod h1:vxM6NuRlgiR0M6wbVTJeKp9vQIs81ZMfCYO+4yq/jbE=
|
||||
@@ -112,6 +124,8 @@ github.com/vektah/gqlparser v1.1.0 h1:3668p2gUlO+PiS81x957Rpr3/FPRWG6cxgCXAvTS1h
|
||||
github.com/vektah/gqlparser v1.1.0/go.mod h1:1ycwN7Ij5njmMkPPAOaRFY4rET2Enx7IkVv3vaXspKw=
|
||||
github.com/vektah/gqlparser v1.1.2 h1:ZsyLGn7/7jDNI+y4SEhI4yAxRChlv15pUHMjijT+e68=
|
||||
github.com/vektah/gqlparser v1.1.2/go.mod h1:1ycwN7Ij5njmMkPPAOaRFY4rET2Enx7IkVv3vaXspKw=
|
||||
go.mongodb.org/mongo-driver v1.0.3 h1:GKoji1ld3tw2aC+GX1wbr/J2fX13yNacEYoJ8Nhr0yU=
|
||||
go.mongodb.org/mongo-driver v1.0.3/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM=
|
||||
golang.org/x/crypto v0.0.0-20180411161317-d6449816ce06 h1:EOqG0JqGlLr+punVB69jvWCv/ErZKGlC7PMdyHfv+Bc=
|
||||
golang.org/x/crypto v0.0.0-20180411161317-d6449816ce06/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793 h1:u+LnwYTOOW7Ukr/fppxEb1Nwz0AtPflrblfvUudpo+I=
|
||||
@@ -146,6 +160,7 @@ golang.org/x/tools v0.0.0-20190515012406-7d7faa4812bd/go.mod h1:RgjU9mgBXZiqYHBn
|
||||
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
||||
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 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/yaml.v2 v2.2.1 h1:mUhvW9EsL+naU5Q3cakzfE91YhliOondGd6ZrsDBHQE=
|
||||
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
|
||||
+38
-38
@@ -1,17 +1,17 @@
|
||||
package graph2
|
||||
|
||||
import (
|
||||
input "git.aiterp.net/rpdata/api/graph2/input"
|
||||
changes "git.aiterp.net/rpdata/api/models/changes"
|
||||
channels "git.aiterp.net/rpdata/api/models/channels"
|
||||
characters "git.aiterp.net/rpdata/api/models/characters"
|
||||
files "git.aiterp.net/rpdata/api/models/files"
|
||||
logs "git.aiterp.net/rpdata/api/models/logs"
|
||||
posts "git.aiterp.net/rpdata/api/models/posts"
|
||||
stories "git.aiterp.net/rpdata/api/models/stories"
|
||||
"git.aiterp.net/rpdata/api/graph2/graphcore"
|
||||
"git.aiterp.net/rpdata/api/models/changes"
|
||||
"git.aiterp.net/rpdata/api/models/channels"
|
||||
"git.aiterp.net/rpdata/api/models/characters"
|
||||
"git.aiterp.net/rpdata/api/models/files"
|
||||
"git.aiterp.net/rpdata/api/models/logs"
|
||||
"git.aiterp.net/rpdata/api/models/posts"
|
||||
"git.aiterp.net/rpdata/api/models/stories"
|
||||
)
|
||||
|
||||
func complexity() (cr ComplexityRoot) {
|
||||
func complexity() (cr graphcore.ComplexityRoot) {
|
||||
subListComplexity := 25
|
||||
bigSublistComplexity := 75
|
||||
hugeSublistComplexity := 100
|
||||
@@ -37,7 +37,7 @@ func complexity() (cr ComplexityRoot) {
|
||||
cr.Query.Posts = func(childComplexity int, filter *posts.Filter) int {
|
||||
return childComplexity + listComplexity
|
||||
}
|
||||
cr.Query.UnknownNicks = func(childComplexity int, filter *input.UnknownNicksFilter) int {
|
||||
cr.Query.UnknownNicks = func(childComplexity int, filter *graphcore.UnknownNicksFilter) int {
|
||||
return childComplexity + listComplexity
|
||||
}
|
||||
cr.Query.Log = func(childComplexity int, id string) int {
|
||||
@@ -56,7 +56,7 @@ func complexity() (cr ComplexityRoot) {
|
||||
cr.Query.Comment = func(childComplexity int, id string) int {
|
||||
return childComplexity + findComplexity
|
||||
}
|
||||
cr.Query.Tags = func(childComplexity int) int {
|
||||
cr.Query.Tags = func(childComplexity int, filter *graphcore.TagFilter) int {
|
||||
return childComplexity + listComplexity
|
||||
}
|
||||
cr.Query.Story = func(childComplexity int, id string) int {
|
||||
@@ -78,85 +78,85 @@ func complexity() (cr ComplexityRoot) {
|
||||
return childComplexity + findComplexity
|
||||
}
|
||||
|
||||
cr.Mutation.AddStory = func(childComplexity int, input input.StoryAddInput) int {
|
||||
cr.Mutation.AddStory = func(childComplexity int, input graphcore.StoryAddInput) int {
|
||||
return childComplexity + mutationComplexity
|
||||
}
|
||||
cr.Mutation.AddStoryTag = func(childComplexity int, input input.StoryTagAddInput) int {
|
||||
cr.Mutation.AddStoryTag = func(childComplexity int, input graphcore.StoryTagAddInput) int {
|
||||
return childComplexity + mutationComplexity
|
||||
}
|
||||
cr.Mutation.RemoveStoryTag = func(childComplexity int, input input.StoryTagRemoveInput) int {
|
||||
cr.Mutation.RemoveStoryTag = func(childComplexity int, input graphcore.StoryTagRemoveInput) int {
|
||||
return childComplexity + mutationComplexity
|
||||
}
|
||||
cr.Mutation.EditStory = func(childComplexity int, input input.StoryEditInput) int {
|
||||
cr.Mutation.EditStory = func(childComplexity int, input graphcore.StoryEditInput) int {
|
||||
return childComplexity + mutationComplexity
|
||||
}
|
||||
cr.Mutation.RemoveStory = func(childComplexity int, input input.StoryRemoveInput) int {
|
||||
cr.Mutation.RemoveStory = func(childComplexity int, input graphcore.StoryRemoveInput) int {
|
||||
return childComplexity + mutationComplexity
|
||||
}
|
||||
cr.Mutation.AddChapter = func(childComplexity int, input input.ChapterAddInput) int {
|
||||
cr.Mutation.AddChapter = func(childComplexity int, input graphcore.ChapterAddInput) int {
|
||||
return childComplexity + mutationComplexity
|
||||
}
|
||||
cr.Mutation.EditChapter = func(childComplexity int, input input.ChapterEditInput) int {
|
||||
cr.Mutation.EditChapter = func(childComplexity int, input graphcore.ChapterEditInput) int {
|
||||
return childComplexity + mutationComplexity
|
||||
}
|
||||
cr.Mutation.MoveChapter = func(childComplexity int, input input.ChapterMoveInput) int {
|
||||
cr.Mutation.MoveChapter = func(childComplexity int, input graphcore.ChapterMoveInput) int {
|
||||
return childComplexity + mutationComplexity
|
||||
}
|
||||
cr.Mutation.RemoveChapter = func(childComplexity int, input input.ChapterRemoveInput) int {
|
||||
cr.Mutation.RemoveChapter = func(childComplexity int, input graphcore.ChapterRemoveInput) int {
|
||||
return childComplexity + mutationComplexity
|
||||
}
|
||||
cr.Mutation.AddComment = func(childComplexity int, input input.CommentAddInput) int {
|
||||
cr.Mutation.AddComment = func(childComplexity int, input graphcore.CommentAddInput) int {
|
||||
return childComplexity + mutationComplexity
|
||||
}
|
||||
cr.Mutation.EditComment = func(childComplexity int, input input.CommentEditInput) int {
|
||||
cr.Mutation.EditComment = func(childComplexity int, input graphcore.CommentEditInput) int {
|
||||
return childComplexity + mutationComplexity
|
||||
}
|
||||
cr.Mutation.RemoveComment = func(childComplexity int, input input.CommentRemoveInput) int {
|
||||
cr.Mutation.RemoveComment = func(childComplexity int, input graphcore.CommentRemoveInput) int {
|
||||
return childComplexity + mutationComplexity
|
||||
}
|
||||
cr.Mutation.AddLog = func(childComplexity int, input input.LogAddInput) int {
|
||||
cr.Mutation.AddLog = func(childComplexity int, input graphcore.LogAddInput) int {
|
||||
return childComplexity + mutationComplexity
|
||||
}
|
||||
cr.Mutation.ImportLog = func(childComplexity int, input input.LogImportInput) int {
|
||||
cr.Mutation.ImportLog = func(childComplexity int, input graphcore.LogImportInput) int {
|
||||
return childComplexity + mutationComplexity
|
||||
}
|
||||
cr.Mutation.EditLog = func(childComplexity int, input input.LogEditInput) int {
|
||||
cr.Mutation.EditLog = func(childComplexity int, input graphcore.LogEditInput) int {
|
||||
return childComplexity + mutationComplexity
|
||||
}
|
||||
cr.Mutation.RemoveLog = func(childComplexity int, input input.LogRemoveInput) int {
|
||||
cr.Mutation.RemoveLog = func(childComplexity int, input graphcore.LogRemoveInput) int {
|
||||
return childComplexity + mutationComplexity
|
||||
}
|
||||
cr.Mutation.AddPost = func(childComplexity int, input input.PostAddInput) int {
|
||||
cr.Mutation.AddPost = func(childComplexity int, input graphcore.PostAddInput) int {
|
||||
return childComplexity + mutationComplexity
|
||||
}
|
||||
cr.Mutation.EditPost = func(childComplexity int, input input.PostEditInput) int {
|
||||
cr.Mutation.EditPost = func(childComplexity int, input graphcore.PostEditInput) int {
|
||||
return childComplexity + mutationComplexity
|
||||
}
|
||||
cr.Mutation.MovePost = func(childComplexity int, input input.PostMoveInput) int {
|
||||
cr.Mutation.MovePost = func(childComplexity int, input graphcore.PostMoveInput) int {
|
||||
return childComplexity + mutationComplexity
|
||||
}
|
||||
cr.Mutation.RemovePost = func(childComplexity int, input input.PostRemoveInput) int {
|
||||
cr.Mutation.RemovePost = func(childComplexity int, input graphcore.PostRemoveInput) int {
|
||||
return childComplexity + mutationComplexity
|
||||
}
|
||||
cr.Mutation.AddCharacter = func(childComplexity int, input input.CharacterAddInput) int {
|
||||
cr.Mutation.AddCharacter = func(childComplexity int, input graphcore.CharacterAddInput) int {
|
||||
return childComplexity + mutationComplexity
|
||||
}
|
||||
cr.Mutation.AddCharacterNick = func(childComplexity int, input input.CharacterNickInput) int {
|
||||
cr.Mutation.AddCharacterNick = func(childComplexity int, input graphcore.CharacterNickInput) int {
|
||||
return childComplexity + mutationComplexity
|
||||
}
|
||||
cr.Mutation.RemoveCharacterNick = func(childComplexity int, input input.CharacterNickInput) int {
|
||||
cr.Mutation.RemoveCharacterNick = func(childComplexity int, input graphcore.CharacterNickInput) int {
|
||||
return childComplexity + mutationComplexity
|
||||
}
|
||||
cr.Mutation.EditCharacter = func(childComplexity int, input input.CharacterEditInput) int {
|
||||
cr.Mutation.EditCharacter = func(childComplexity int, input graphcore.CharacterEditInput) int {
|
||||
return childComplexity + mutationComplexity
|
||||
}
|
||||
cr.Mutation.RemoveCharacter = func(childComplexity int, input input.CharacterRemoveInput) int {
|
||||
cr.Mutation.RemoveCharacter = func(childComplexity int, input graphcore.CharacterRemoveInput) int {
|
||||
return childComplexity + mutationComplexity
|
||||
}
|
||||
cr.Mutation.AddChannel = func(childComplexity int, input input.ChannelAddInput) int {
|
||||
cr.Mutation.AddChannel = func(childComplexity int, input graphcore.ChannelAddInput) int {
|
||||
return childComplexity + mutationComplexity
|
||||
}
|
||||
cr.Mutation.EditChannel = func(childComplexity int, input input.ChannelEditInput) int {
|
||||
cr.Mutation.EditChannel = func(childComplexity int, input graphcore.ChannelEditInput) int {
|
||||
return childComplexity + mutationComplexity
|
||||
}
|
||||
|
||||
|
||||
+4
-4
@@ -3,12 +3,12 @@ schema:
|
||||
- schema/types/*.gql
|
||||
|
||||
exec:
|
||||
filename: generated.go
|
||||
package: graph2
|
||||
filename: graphcore/exec_gen.go
|
||||
package: graphcore
|
||||
|
||||
model:
|
||||
filename: input/generated.go
|
||||
package: input
|
||||
filename: graphcore/input_gen.go
|
||||
package: graphcore
|
||||
|
||||
models:
|
||||
Tag:
|
||||
|
||||
+19
-15
@@ -1,55 +1,59 @@
|
||||
package graph2
|
||||
|
||||
import (
|
||||
"git.aiterp.net/rpdata/api/graph2/graphcore"
|
||||
"git.aiterp.net/rpdata/api/graph2/queries"
|
||||
"git.aiterp.net/rpdata/api/graph2/types"
|
||||
"git.aiterp.net/rpdata/api/services"
|
||||
graphql "github.com/99designs/gqlgen/graphql"
|
||||
)
|
||||
|
||||
//go:generate go run github.com/99designs/gqlgen -v
|
||||
|
||||
// New creates a new GraphQL schema.
|
||||
func New() graphql.ExecutableSchema {
|
||||
return NewExecutableSchema(Config{
|
||||
Resolvers: &rootResolver{},
|
||||
func New(s *services.Bundle) graphql.ExecutableSchema {
|
||||
return graphcore.NewExecutableSchema(graphcore.Config{
|
||||
Resolvers: &rootResolver{s},
|
||||
Complexity: complexity(),
|
||||
})
|
||||
}
|
||||
|
||||
type rootResolver struct{}
|
||||
|
||||
func (r *rootResolver) Query() QueryResolver {
|
||||
return &queries.Resolver
|
||||
type rootResolver struct {
|
||||
s *services.Bundle
|
||||
}
|
||||
|
||||
func (r *rootResolver) Mutation() MutationResolver {
|
||||
func (r *rootResolver) Query() graphcore.QueryResolver {
|
||||
return queries.QueryResolver(r.s)
|
||||
}
|
||||
|
||||
func (r *rootResolver) Mutation() graphcore.MutationResolver {
|
||||
return queries.MutationResolver
|
||||
}
|
||||
|
||||
func (r *rootResolver) Subscription() SubscriptionResolver {
|
||||
func (r *rootResolver) Subscription() graphcore.SubscriptionResolver {
|
||||
return queries.SubscriptionResolver
|
||||
}
|
||||
|
||||
func (r *rootResolver) Log() LogResolver {
|
||||
func (r *rootResolver) Log() graphcore.LogResolver {
|
||||
return &types.LogResolver
|
||||
}
|
||||
|
||||
func (r *rootResolver) Comment() CommentResolver {
|
||||
func (r *rootResolver) Comment() graphcore.CommentResolver {
|
||||
return &types.CommentResolver
|
||||
}
|
||||
|
||||
func (r *rootResolver) Chapter() ChapterResolver {
|
||||
func (r *rootResolver) Chapter() graphcore.ChapterResolver {
|
||||
return &types.ChapterResolver
|
||||
}
|
||||
|
||||
func (r *rootResolver) Story() StoryResolver {
|
||||
func (r *rootResolver) Story() graphcore.StoryResolver {
|
||||
return &types.StoryResolver
|
||||
}
|
||||
|
||||
func (r *rootResolver) Change() ChangeResolver {
|
||||
func (r *rootResolver) Change() graphcore.ChangeResolver {
|
||||
return &types.ChangeResolver
|
||||
}
|
||||
|
||||
func (r *rootResolver) Token() TokenResolver {
|
||||
func (r *rootResolver) Token() graphcore.TokenResolver {
|
||||
return &types.TokenResolver
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ import (
|
||||
"context"
|
||||
"errors"
|
||||
|
||||
"git.aiterp.net/rpdata/api/graph2/input"
|
||||
"git.aiterp.net/rpdata/api/graph2/graphcore"
|
||||
"git.aiterp.net/rpdata/api/internal/auth"
|
||||
"git.aiterp.net/rpdata/api/models"
|
||||
"git.aiterp.net/rpdata/api/models/changekeys"
|
||||
@@ -39,7 +39,7 @@ func (r *resolver) Channels(ctx context.Context, filter *channels.Filter) ([]*mo
|
||||
|
||||
// Mutations
|
||||
|
||||
func (r *mutationResolver) AddChannel(ctx context.Context, input input.ChannelAddInput) (*models.Channel, error) {
|
||||
func (r *mutationResolver) AddChannel(ctx context.Context, input graphcore.ChannelAddInput) (*models.Channel, error) {
|
||||
token := auth.TokenFromContext(ctx)
|
||||
if !token.Authenticated() || !token.Permitted("channel.add") {
|
||||
return nil, errors.New("You are not permitted to add channels")
|
||||
@@ -72,7 +72,7 @@ func (r *mutationResolver) AddChannel(ctx context.Context, input input.ChannelAd
|
||||
return &channel, nil
|
||||
}
|
||||
|
||||
func (r *mutationResolver) EditChannel(ctx context.Context, input input.ChannelEditInput) (*models.Channel, error) {
|
||||
func (r *mutationResolver) EditChannel(ctx context.Context, input graphcore.ChannelEditInput) (*models.Channel, error) {
|
||||
token := auth.TokenFromContext(ctx)
|
||||
if !token.Authenticated() || !token.Permitted("channel.edit") {
|
||||
return nil, errors.New("You are not permitted to edit channels")
|
||||
|
||||
@@ -5,7 +5,7 @@ import (
|
||||
"errors"
|
||||
"time"
|
||||
|
||||
"git.aiterp.net/rpdata/api/graph2/input"
|
||||
"git.aiterp.net/rpdata/api/graph2/graphcore"
|
||||
"git.aiterp.net/rpdata/api/internal/auth"
|
||||
"git.aiterp.net/rpdata/api/models"
|
||||
"git.aiterp.net/rpdata/api/models/changekeys"
|
||||
@@ -28,7 +28,7 @@ func (r *resolver) Chapter(ctx context.Context, id string) (*models.Chapter, err
|
||||
|
||||
// Mutations
|
||||
|
||||
func (r *mutationResolver) AddChapter(ctx context.Context, input input.ChapterAddInput) (*models.Chapter, error) {
|
||||
func (r *mutationResolver) AddChapter(ctx context.Context, input graphcore.ChapterAddInput) (*models.Chapter, error) {
|
||||
story, err := stories.FindID(input.StoryID)
|
||||
if err != nil {
|
||||
return nil, errors.New("Story not found")
|
||||
@@ -67,7 +67,7 @@ func (r *mutationResolver) AddChapter(ctx context.Context, input input.ChapterAd
|
||||
return &chapter, nil
|
||||
}
|
||||
|
||||
func (r *mutationResolver) MoveChapter(ctx context.Context, input input.ChapterMoveInput) (*models.Chapter, error) {
|
||||
func (r *mutationResolver) MoveChapter(ctx context.Context, input graphcore.ChapterMoveInput) (*models.Chapter, error) {
|
||||
chapter, err := chapters.FindID(input.ID)
|
||||
if err != nil {
|
||||
return nil, errors.New("Chapter not found")
|
||||
@@ -111,7 +111,7 @@ func (r *mutationResolver) MoveChapter(ctx context.Context, input input.ChapterM
|
||||
return &chapter, nil
|
||||
}
|
||||
|
||||
func (r *mutationResolver) EditChapter(ctx context.Context, input input.ChapterEditInput) (*models.Chapter, error) {
|
||||
func (r *mutationResolver) EditChapter(ctx context.Context, input graphcore.ChapterEditInput) (*models.Chapter, error) {
|
||||
chapter, err := chapters.FindID(input.ID)
|
||||
if err != nil {
|
||||
return nil, errors.New("Chapter not found")
|
||||
@@ -143,7 +143,7 @@ func (r *mutationResolver) EditChapter(ctx context.Context, input input.ChapterE
|
||||
return &chapter, nil
|
||||
}
|
||||
|
||||
func (r *mutationResolver) RemoveChapter(ctx context.Context, input input.ChapterRemoveInput) (*models.Chapter, error) {
|
||||
func (r *mutationResolver) RemoveChapter(ctx context.Context, input graphcore.ChapterRemoveInput) (*models.Chapter, error) {
|
||||
chapter, err := chapters.FindID(input.ID)
|
||||
if err != nil {
|
||||
return nil, errors.New("Chapter not found")
|
||||
|
||||
@@ -5,7 +5,7 @@ import (
|
||||
"errors"
|
||||
"strings"
|
||||
|
||||
"git.aiterp.net/rpdata/api/graph2/input"
|
||||
"git.aiterp.net/rpdata/api/graph2/graphcore"
|
||||
"git.aiterp.net/rpdata/api/internal/auth"
|
||||
"git.aiterp.net/rpdata/api/models"
|
||||
"git.aiterp.net/rpdata/api/models/changekeys"
|
||||
@@ -52,7 +52,7 @@ func (r *resolver) Characters(ctx context.Context, filter *characters.Filter) ([
|
||||
|
||||
// Mutations
|
||||
|
||||
func (r *mutationResolver) AddCharacter(ctx context.Context, input input.CharacterAddInput) (*models.Character, error) {
|
||||
func (r *mutationResolver) AddCharacter(ctx context.Context, input graphcore.CharacterAddInput) (*models.Character, error) {
|
||||
token := auth.TokenFromContext(ctx)
|
||||
if !token.Permitted("member", "character.add") {
|
||||
return nil, errors.New("You are not permitted to add characters")
|
||||
@@ -94,7 +94,7 @@ func (r *mutationResolver) AddCharacter(ctx context.Context, input input.Charact
|
||||
return &character, nil
|
||||
}
|
||||
|
||||
func (r *mutationResolver) AddCharacterNick(ctx context.Context, input input.CharacterNickInput) (*models.Character, error) {
|
||||
func (r *mutationResolver) AddCharacterNick(ctx context.Context, input graphcore.CharacterNickInput) (*models.Character, error) {
|
||||
character, err := characters.FindID(input.ID)
|
||||
if err != nil {
|
||||
return nil, errors.New("Character not found")
|
||||
@@ -122,7 +122,7 @@ func (r *mutationResolver) AddCharacterNick(ctx context.Context, input input.Cha
|
||||
return &character, nil
|
||||
}
|
||||
|
||||
func (r *mutationResolver) RemoveCharacterNick(ctx context.Context, input input.CharacterNickInput) (*models.Character, error) {
|
||||
func (r *mutationResolver) RemoveCharacterNick(ctx context.Context, input graphcore.CharacterNickInput) (*models.Character, error) {
|
||||
character, err := characters.FindID(input.ID)
|
||||
if err != nil {
|
||||
return nil, errors.New("Character not found")
|
||||
@@ -144,7 +144,7 @@ func (r *mutationResolver) RemoveCharacterNick(ctx context.Context, input input.
|
||||
return &character, nil
|
||||
}
|
||||
|
||||
func (r *mutationResolver) EditCharacter(ctx context.Context, input input.CharacterEditInput) (*models.Character, error) {
|
||||
func (r *mutationResolver) EditCharacter(ctx context.Context, input graphcore.CharacterEditInput) (*models.Character, error) {
|
||||
character, err := characters.FindID(input.ID)
|
||||
if err != nil {
|
||||
return nil, errors.New("Character not found")
|
||||
@@ -172,7 +172,7 @@ func (r *mutationResolver) EditCharacter(ctx context.Context, input input.Charac
|
||||
return &character, nil
|
||||
}
|
||||
|
||||
func (r *mutationResolver) RemoveCharacter(ctx context.Context, input input.CharacterRemoveInput) (*models.Character, error) {
|
||||
func (r *mutationResolver) RemoveCharacter(ctx context.Context, input graphcore.CharacterRemoveInput) (*models.Character, error) {
|
||||
character, err := characters.FindID(input.ID)
|
||||
if err != nil {
|
||||
return nil, errors.New("Character not found")
|
||||
|
||||
+10
-15
@@ -6,20 +6,15 @@ import (
|
||||
"log"
|
||||
"time"
|
||||
|
||||
"git.aiterp.net/rpdata/api/models/stories"
|
||||
|
||||
"git.aiterp.net/rpdata/api/models/characters"
|
||||
|
||||
"git.aiterp.net/rpdata/api/models/changekeys"
|
||||
|
||||
"git.aiterp.net/rpdata/api/models/changes"
|
||||
|
||||
"git.aiterp.net/rpdata/api/graph2/input"
|
||||
"git.aiterp.net/rpdata/api/graph2/graphcore"
|
||||
"git.aiterp.net/rpdata/api/internal/auth"
|
||||
"git.aiterp.net/rpdata/api/models/chapters"
|
||||
"git.aiterp.net/rpdata/api/models/comments"
|
||||
|
||||
"git.aiterp.net/rpdata/api/models"
|
||||
"git.aiterp.net/rpdata/api/models/changekeys"
|
||||
"git.aiterp.net/rpdata/api/models/changes"
|
||||
"git.aiterp.net/rpdata/api/models/chapters"
|
||||
"git.aiterp.net/rpdata/api/models/characters"
|
||||
"git.aiterp.net/rpdata/api/models/comments"
|
||||
"git.aiterp.net/rpdata/api/models/stories"
|
||||
)
|
||||
|
||||
// Queries
|
||||
@@ -35,7 +30,7 @@ func (r *resolver) Comment(ctx context.Context, id string) (*models.Comment, err
|
||||
|
||||
// Mutations
|
||||
|
||||
func (r *mutationResolver) AddComment(ctx context.Context, input input.CommentAddInput) (*models.Comment, error) {
|
||||
func (r *mutationResolver) AddComment(ctx context.Context, input graphcore.CommentAddInput) (*models.Comment, error) {
|
||||
chapter, err := chapters.FindID(input.ChapterID)
|
||||
if err != nil {
|
||||
return nil, errors.New("Chapter not found")
|
||||
@@ -90,7 +85,7 @@ func (r *mutationResolver) AddComment(ctx context.Context, input input.CommentAd
|
||||
return &comment, nil
|
||||
}
|
||||
|
||||
func (r *mutationResolver) EditComment(ctx context.Context, input input.CommentEditInput) (*models.Comment, error) {
|
||||
func (r *mutationResolver) EditComment(ctx context.Context, input graphcore.CommentEditInput) (*models.Comment, error) {
|
||||
comment, err := comments.Find(input.CommentID)
|
||||
if err != nil {
|
||||
return nil, errors.New("Comment not found")
|
||||
@@ -141,7 +136,7 @@ func (r *mutationResolver) EditComment(ctx context.Context, input input.CommentE
|
||||
return &comment, nil
|
||||
}
|
||||
|
||||
func (r *mutationResolver) RemoveComment(ctx context.Context, input input.CommentRemoveInput) (*models.Comment, error) {
|
||||
func (r *mutationResolver) RemoveComment(ctx context.Context, input graphcore.CommentRemoveInput) (*models.Comment, error) {
|
||||
comment, err := comments.Find(input.CommentID)
|
||||
if err != nil {
|
||||
return nil, errors.New("Comment not found")
|
||||
|
||||
@@ -6,14 +6,13 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"git.aiterp.net/rpdata/api/models/channels"
|
||||
|
||||
"git.aiterp.net/rpdata/api/graph2/input"
|
||||
"git.aiterp.net/rpdata/api/graph2/graphcore"
|
||||
"git.aiterp.net/rpdata/api/internal/auth"
|
||||
"git.aiterp.net/rpdata/api/internal/loader"
|
||||
"git.aiterp.net/rpdata/api/models"
|
||||
"git.aiterp.net/rpdata/api/models/changekeys"
|
||||
"git.aiterp.net/rpdata/api/models/changes"
|
||||
"git.aiterp.net/rpdata/api/models/channels"
|
||||
"git.aiterp.net/rpdata/api/models/logs"
|
||||
"github.com/99designs/gqlgen/graphql"
|
||||
)
|
||||
@@ -66,7 +65,7 @@ func (r *resolver) Logs(ctx context.Context, filter *logs.Filter) ([]*models.Log
|
||||
|
||||
// Mutations
|
||||
|
||||
func (r *mutationResolver) AddLog(ctx context.Context, input input.LogAddInput) (*models.Log, error) {
|
||||
func (r *mutationResolver) AddLog(ctx context.Context, input graphcore.LogAddInput) (*models.Log, error) {
|
||||
token := auth.TokenFromContext(ctx)
|
||||
if !token.Authenticated() || !token.Permitted("log.add") {
|
||||
return nil, errors.New("You are not permitted to add logs")
|
||||
@@ -107,7 +106,7 @@ func (r *mutationResolver) AddLog(ctx context.Context, input input.LogAddInput)
|
||||
return &log, nil
|
||||
}
|
||||
|
||||
func (r *mutationResolver) ImportLog(ctx context.Context, input input.LogImportInput) ([]*models.Log, error) {
|
||||
func (r *mutationResolver) ImportLog(ctx context.Context, input graphcore.LogImportInput) ([]*models.Log, error) {
|
||||
token := auth.TokenFromContext(ctx)
|
||||
if !token.Authenticated() || !token.Permitted("log.add") {
|
||||
return nil, errors.New("You are not permitted to add logs")
|
||||
@@ -151,7 +150,7 @@ func (r *mutationResolver) ImportLog(ctx context.Context, input input.LogImportI
|
||||
return newLogs, nil
|
||||
}
|
||||
|
||||
func (r *mutationResolver) EditLog(ctx context.Context, input input.LogEditInput) (*models.Log, error) {
|
||||
func (r *mutationResolver) EditLog(ctx context.Context, input graphcore.LogEditInput) (*models.Log, error) {
|
||||
token := auth.TokenFromContext(ctx)
|
||||
if !token.Authenticated() || !token.Permitted("log.edit") {
|
||||
return nil, errors.New("You are not permitted to edit logs")
|
||||
@@ -172,7 +171,7 @@ func (r *mutationResolver) EditLog(ctx context.Context, input input.LogEditInput
|
||||
return &log, nil
|
||||
}
|
||||
|
||||
func (r *mutationResolver) RemoveLog(ctx context.Context, input input.LogRemoveInput) (*models.Log, error) {
|
||||
func (r *mutationResolver) RemoveLog(ctx context.Context, input graphcore.LogRemoveInput) (*models.Log, error) {
|
||||
token := auth.TokenFromContext(ctx)
|
||||
if !token.Authenticated() || !token.Permitted("log.remove") {
|
||||
return nil, errors.New("You are not permitted to remove logs")
|
||||
|
||||
@@ -4,13 +4,12 @@ import (
|
||||
"context"
|
||||
"errors"
|
||||
|
||||
"git.aiterp.net/rpdata/api/graph2/graphcore"
|
||||
"git.aiterp.net/rpdata/api/internal/auth"
|
||||
"git.aiterp.net/rpdata/api/models"
|
||||
"git.aiterp.net/rpdata/api/models/changekeys"
|
||||
"git.aiterp.net/rpdata/api/models/changes"
|
||||
"git.aiterp.net/rpdata/api/models/logs"
|
||||
|
||||
"git.aiterp.net/rpdata/api/graph2/input"
|
||||
"git.aiterp.net/rpdata/api/internal/auth"
|
||||
"git.aiterp.net/rpdata/api/models"
|
||||
"git.aiterp.net/rpdata/api/models/posts"
|
||||
)
|
||||
|
||||
@@ -58,7 +57,7 @@ func (r *resolver) Posts(ctx context.Context, filter *posts.Filter) ([]*models.P
|
||||
|
||||
// Mutation
|
||||
|
||||
func (r *mutationResolver) AddPost(ctx context.Context, input input.PostAddInput) (*models.Post, error) {
|
||||
func (r *mutationResolver) AddPost(ctx context.Context, input graphcore.PostAddInput) (*models.Post, error) {
|
||||
token := auth.TokenFromContext(ctx)
|
||||
if !token.Authenticated() || !token.Permitted("post.add") {
|
||||
return nil, errors.New("You are not permitted to edit logs")
|
||||
@@ -80,7 +79,7 @@ func (r *mutationResolver) AddPost(ctx context.Context, input input.PostAddInput
|
||||
return &post, nil
|
||||
}
|
||||
|
||||
func (r *mutationResolver) EditPost(ctx context.Context, input input.PostEditInput) (*models.Post, error) {
|
||||
func (r *mutationResolver) EditPost(ctx context.Context, input graphcore.PostEditInput) (*models.Post, error) {
|
||||
token := auth.TokenFromContext(ctx)
|
||||
if !token.Authenticated() || !token.Permitted("post.edit") {
|
||||
return nil, errors.New("You are not permitted to edit logs")
|
||||
@@ -119,7 +118,7 @@ func (r *mutationResolver) EditPost(ctx context.Context, input input.PostEditInp
|
||||
return &post, nil
|
||||
}
|
||||
|
||||
func (r *mutationResolver) MovePost(ctx context.Context, input input.PostMoveInput) ([]*models.Post, error) {
|
||||
func (r *mutationResolver) MovePost(ctx context.Context, input graphcore.PostMoveInput) ([]*models.Post, error) {
|
||||
token := auth.TokenFromContext(ctx)
|
||||
if !token.Authenticated() || !token.Permitted("post.move") {
|
||||
return nil, errors.New("You are not permitted to edit logs")
|
||||
@@ -152,7 +151,7 @@ func (r *mutationResolver) MovePost(ctx context.Context, input input.PostMoveInp
|
||||
return posts2, nil
|
||||
}
|
||||
|
||||
func (r *mutationResolver) RemovePost(ctx context.Context, input input.PostRemoveInput) (*models.Post, error) {
|
||||
func (r *mutationResolver) RemovePost(ctx context.Context, input graphcore.PostRemoveInput) (*models.Post, error) {
|
||||
token := auth.TokenFromContext(ctx)
|
||||
if !token.Authenticated() || !token.Permitted("post.remove") {
|
||||
return nil, errors.New("You are not permitted to edit logs")
|
||||
|
||||
@@ -1,11 +1,18 @@
|
||||
package queries
|
||||
|
||||
type resolver struct{}
|
||||
import (
|
||||
"git.aiterp.net/rpdata/api/graph2/graphcore"
|
||||
"git.aiterp.net/rpdata/api/services"
|
||||
)
|
||||
|
||||
type resolver struct{ s *services.Bundle }
|
||||
type mutationResolver struct{}
|
||||
type subscriptionResolver struct{}
|
||||
|
||||
// Resolver has all the queries
|
||||
var Resolver resolver
|
||||
// QueryResolver has all the queries
|
||||
func QueryResolver(s *services.Bundle) graphcore.QueryResolver {
|
||||
return &resolver{s: s}
|
||||
}
|
||||
|
||||
// MutationResolver brings the mutagens.
|
||||
var MutationResolver *mutationResolver
|
||||
|
||||
@@ -5,12 +5,11 @@ import (
|
||||
"errors"
|
||||
"time"
|
||||
|
||||
"git.aiterp.net/rpdata/api/models/changekeys"
|
||||
"git.aiterp.net/rpdata/api/models/changes"
|
||||
|
||||
"git.aiterp.net/rpdata/api/graph2/input"
|
||||
"git.aiterp.net/rpdata/api/graph2/graphcore"
|
||||
"git.aiterp.net/rpdata/api/internal/auth"
|
||||
"git.aiterp.net/rpdata/api/models"
|
||||
"git.aiterp.net/rpdata/api/models/changekeys"
|
||||
"git.aiterp.net/rpdata/api/models/changes"
|
||||
"git.aiterp.net/rpdata/api/models/chapters"
|
||||
"git.aiterp.net/rpdata/api/models/stories"
|
||||
)
|
||||
@@ -53,7 +52,7 @@ func (r *resolver) Stories(ctx context.Context, filter *stories.Filter) ([]*mode
|
||||
|
||||
// Mutations
|
||||
|
||||
func (r *mutationResolver) AddStory(ctx context.Context, input input.StoryAddInput) (*models.Story, error) {
|
||||
func (r *mutationResolver) AddStory(ctx context.Context, input graphcore.StoryAddInput) (*models.Story, error) {
|
||||
token := auth.TokenFromContext(ctx)
|
||||
if token == nil || !token.Permitted("member", "story.add") {
|
||||
return nil, errors.New("Permission denied")
|
||||
@@ -91,7 +90,7 @@ func (r *mutationResolver) AddStory(ctx context.Context, input input.StoryAddInp
|
||||
return &story, nil
|
||||
}
|
||||
|
||||
func (r *mutationResolver) AddStoryTag(ctx context.Context, input input.StoryTagAddInput) (*models.Story, error) {
|
||||
func (r *mutationResolver) AddStoryTag(ctx context.Context, input graphcore.StoryTagAddInput) (*models.Story, error) {
|
||||
token := auth.TokenFromContext(ctx)
|
||||
|
||||
story, err := stories.FindID(input.ID)
|
||||
@@ -119,7 +118,7 @@ func (r *mutationResolver) AddStoryTag(ctx context.Context, input input.StoryTag
|
||||
return &story, nil
|
||||
}
|
||||
|
||||
func (r *mutationResolver) RemoveStoryTag(ctx context.Context, input input.StoryTagRemoveInput) (*models.Story, error) {
|
||||
func (r *mutationResolver) RemoveStoryTag(ctx context.Context, input graphcore.StoryTagRemoveInput) (*models.Story, error) {
|
||||
token := auth.TokenFromContext(ctx)
|
||||
|
||||
story, err := stories.FindID(input.ID)
|
||||
@@ -147,7 +146,7 @@ func (r *mutationResolver) RemoveStoryTag(ctx context.Context, input input.Story
|
||||
return &story, nil
|
||||
}
|
||||
|
||||
func (r *mutationResolver) EditStory(ctx context.Context, input input.StoryEditInput) (*models.Story, error) {
|
||||
func (r *mutationResolver) EditStory(ctx context.Context, input graphcore.StoryEditInput) (*models.Story, error) {
|
||||
token := auth.TokenFromContext(ctx)
|
||||
|
||||
story, err := stories.FindID(input.ID)
|
||||
@@ -173,7 +172,7 @@ func (r *mutationResolver) EditStory(ctx context.Context, input input.StoryEditI
|
||||
return &story, nil
|
||||
}
|
||||
|
||||
func (r *mutationResolver) RemoveStory(ctx context.Context, input input.StoryRemoveInput) (*models.Story, error) {
|
||||
func (r *mutationResolver) RemoveStory(ctx context.Context, input graphcore.StoryRemoveInput) (*models.Story, error) {
|
||||
token := auth.TokenFromContext(ctx)
|
||||
|
||||
story, err := stories.FindID(input.ID)
|
||||
|
||||
+6
-11
@@ -3,20 +3,15 @@ package queries
|
||||
import (
|
||||
"context"
|
||||
|
||||
"git.aiterp.net/rpdata/api/graph2/graphcore"
|
||||
"git.aiterp.net/rpdata/api/models"
|
||||
"git.aiterp.net/rpdata/api/models/tags"
|
||||
)
|
||||
|
||||
func (r *resolver) Tags(ctx context.Context) ([]*models.Tag, error) {
|
||||
tags, err := tags.List()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
func (r *resolver) Tags(ctx context.Context, filter *graphcore.TagFilter) ([]*models.Tag, error) {
|
||||
tagFilter := models.TagFilter{}
|
||||
if filter != nil && filter.Kind != nil {
|
||||
tagFilter.Kind = filter.Kind
|
||||
}
|
||||
|
||||
tags2 := make([]*models.Tag, len(tags))
|
||||
for i := range tags {
|
||||
tags2[i] = &tags[i]
|
||||
}
|
||||
|
||||
return tags2, nil
|
||||
return r.s.Tags.ListTags(ctx, tagFilter)
|
||||
}
|
||||
|
||||
@@ -3,15 +3,14 @@ package queries
|
||||
import (
|
||||
"context"
|
||||
|
||||
"git.aiterp.net/rpdata/api/graph2/graphcore"
|
||||
"git.aiterp.net/rpdata/api/models"
|
||||
"git.aiterp.net/rpdata/api/models/unknownnicks"
|
||||
|
||||
"git.aiterp.net/rpdata/api/graph2/input"
|
||||
)
|
||||
|
||||
/// Queries
|
||||
|
||||
func (r *resolver) UnknownNicks(ctx context.Context, filter *input.UnknownNicksFilter) ([]*models.UnknownNick, error) {
|
||||
func (r *resolver) UnknownNicks(ctx context.Context, filter *graphcore.UnknownNicksFilter) ([]*models.UnknownNick, error) {
|
||||
limit := 100
|
||||
if filter != nil {
|
||||
if filter.Limit > 0 {
|
||||
|
||||
@@ -46,7 +46,7 @@ type Query {
|
||||
|
||||
|
||||
# Find all distinct tags used in stories
|
||||
tags: [Tag!]!
|
||||
tags(filter: TagFilter): [Tag!]!
|
||||
|
||||
|
||||
# Find story by ID
|
||||
|
||||
@@ -16,6 +16,15 @@ input TagInput {
|
||||
name: String!
|
||||
}
|
||||
|
||||
"""
|
||||
A TagFilter is a filter for the tags query.
|
||||
"""
|
||||
input TagFilter {
|
||||
"Filter by kind"
|
||||
kind: TagKind
|
||||
}
|
||||
|
||||
|
||||
# Allowed values for Tag.kind
|
||||
enum TagKind {
|
||||
# An organization is a catch all term for in-universe corporations, teams, groups, cults, forces, etc...
|
||||
|
||||
@@ -4,18 +4,18 @@ import (
|
||||
"context"
|
||||
"log"
|
||||
|
||||
"git.aiterp.net/rpdata/api/graph2/input"
|
||||
"git.aiterp.net/rpdata/api/graph2/graphcore"
|
||||
"git.aiterp.net/rpdata/api/models"
|
||||
)
|
||||
|
||||
type changeResolver struct{}
|
||||
|
||||
func (r *changeResolver) Objects(ctx context.Context, obj *models.Change) ([]input.ChangeObject, error) {
|
||||
func (r *changeResolver) Objects(ctx context.Context, obj *models.Change) ([]graphcore.ChangeObject, error) {
|
||||
objects := obj.Objects()
|
||||
|
||||
results := make([]input.ChangeObject, 0, len(objects))
|
||||
results := make([]graphcore.ChangeObject, 0, len(objects))
|
||||
for _, object := range objects {
|
||||
if changeObject, ok := object.(input.ChangeObject); ok {
|
||||
if changeObject, ok := object.(graphcore.ChangeObject); ok {
|
||||
results = append(results, changeObject)
|
||||
} else {
|
||||
log.Printf("Type %T needs ChangeObject impl", object)
|
||||
|
||||
@@ -11,6 +11,8 @@ func AllPermissions() map[string]string {
|
||||
"channel.add": "Can add channels",
|
||||
"channel.edit": "Can edit channels",
|
||||
"channel.remove": "Can remove channels",
|
||||
"comment.edit": "Can edit non-owned comments",
|
||||
"comment.remove": "Can remove non-owned comments",
|
||||
"log.add": "Can add logs",
|
||||
"log.edit": "Can edit logs",
|
||||
"log.remove": "Can remove logs",
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
package auth
|
||||
|
||||
import (
|
||||
"context"
|
||||
"reflect"
|
||||
|
||||
"git.aiterp.net/rpdata/api/models"
|
||||
)
|
||||
|
||||
// CheckPermission does some magic.
|
||||
func CheckPermission(ctx context.Context, op string, obj interface{}) error {
|
||||
token := TokenFromContext(ctx)
|
||||
if token == nil {
|
||||
return ErrUnauthenticated
|
||||
}
|
||||
|
||||
if reflect.TypeOf(obj).Kind() != reflect.Ptr {
|
||||
return CheckPermission(ctx, op, &obj)
|
||||
}
|
||||
|
||||
var authorized = false
|
||||
|
||||
switch v := obj.(type) {
|
||||
case *models.Channel:
|
||||
authorized = token.Permitted("channel." + op)
|
||||
case *models.Character:
|
||||
authorized = token.PermittedUser(v.Author, "member", "character."+op)
|
||||
case *models.Chapter:
|
||||
authorized = token.PermittedUser(v.Author, "member", "chapter."+op)
|
||||
case *models.Comment:
|
||||
if op == "add" && v.Author != token.UserID {
|
||||
return ErrInvalidOperation
|
||||
}
|
||||
|
||||
authorized = token.PermittedUser(v.Author, "member", "comment."+op)
|
||||
case *models.File:
|
||||
authorized = token.PermittedUser(v.Author, "member", "file."+op)
|
||||
case *models.Log:
|
||||
authorized = token.Permitted("log." + op)
|
||||
case *models.Post:
|
||||
authorized = token.Permitted("post." + op)
|
||||
case *models.Story:
|
||||
authorized = token.PermittedUser(v.Author, "member", "story."+op)
|
||||
case *models.User:
|
||||
authorized = token.Permitted("user." + op)
|
||||
}
|
||||
|
||||
if !authorized {
|
||||
return ErrUnauthorized
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -36,6 +36,15 @@ var ErrWrongPermissions = errors.New("User does not have these permissions")
|
||||
// ErrDeletedUser is returned by CheckToken if the key can represent this user, but the user doesn't exist.
|
||||
var ErrDeletedUser = errors.New("User was not found")
|
||||
|
||||
// ErrUnauthenticated is returned when the user is not authenticated
|
||||
var ErrUnauthenticated = errors.New("You are not authenticated")
|
||||
|
||||
// ErrUnauthorized is returned when the user doesn't have access to this resource
|
||||
var ErrUnauthorized = errors.New("You are not authorized to perform this action")
|
||||
|
||||
// ErrInvalidOperation is returned for operations that should never be allowed
|
||||
var ErrInvalidOperation = errors.New("No permission exists for this operation")
|
||||
|
||||
// TokenFromContext gets the token from context.
|
||||
func TokenFromContext(ctx context.Context) *models.Token {
|
||||
token, ok := ctx.Value(contextKey).(*models.Token)
|
||||
|
||||
+52
-26
@@ -5,56 +5,82 @@ import (
|
||||
"errors"
|
||||
"log"
|
||||
"os"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"gopkg.in/yaml.v2"
|
||||
)
|
||||
|
||||
var globalMutex sync.Mutex
|
||||
var global *Config
|
||||
|
||||
// Config is configuration
|
||||
// Config is configuration data
|
||||
type Config struct {
|
||||
Space struct {
|
||||
Enabled bool `json:"enabled"`
|
||||
Host string `json:"host"`
|
||||
AccessKey string `json:"accessKey"`
|
||||
SecretKey string `json:"secretKey"`
|
||||
Bucket string `json:"bucket"`
|
||||
MaxSize int64 `json:"maxSize"`
|
||||
Root string `json:"root"`
|
||||
} `json:"space"`
|
||||
Space Space `json:"space" yaml:"space"`
|
||||
Database Database `json:"database" yaml:"database"`
|
||||
Wiki Wiki `json:"wiki" yaml:"wiki"`
|
||||
}
|
||||
|
||||
Database struct {
|
||||
Host string `json:"host"`
|
||||
Port int `json:"port"`
|
||||
Db string `json:"db"`
|
||||
Username string `json:"username"`
|
||||
Password string `json:"password"`
|
||||
Mechanism string `json:"mechanism"`
|
||||
} `json:"database"`
|
||||
// Space is configuration for spaces.
|
||||
type Space struct {
|
||||
Enabled bool `json:"enabled" yaml:"enabled"`
|
||||
Host string `json:"host" yaml:"host"`
|
||||
AccessKey string `json:"accessKey" yaml:"accessKey"`
|
||||
SecretKey string `json:"secretKey" yaml:"secretKey"`
|
||||
Bucket string `json:"bucket" yaml:"bucket"`
|
||||
MaxSize int64 `json:"maxSize" yaml:"maxSize"`
|
||||
Root string `json:"root" yaml:"root"`
|
||||
}
|
||||
|
||||
Wiki struct {
|
||||
URL string `json:"url"`
|
||||
} `json:"wiki"`
|
||||
// Database is configuration for spaces.
|
||||
type Database struct {
|
||||
Driver string `json:"driver" yaml:"driver"`
|
||||
Host string `json:"host" yaml:"host"`
|
||||
Port int `json:"port" yaml:"port"`
|
||||
Db string `json:"db" yaml:"db"`
|
||||
Username string `json:"username" yaml:"username"`
|
||||
Password string `json:"password" yaml:"password"`
|
||||
Mechanism string `json:"mechanism" yaml:"mechanism"`
|
||||
}
|
||||
|
||||
// Wiki is the wiki stuff.
|
||||
type Wiki struct {
|
||||
URL string `json:"url" yaml:"url"`
|
||||
}
|
||||
|
||||
// Load loads config stuff
|
||||
func (config *Config) Load(filename string) error {
|
||||
log.Println("Trying to load config from " + filename)
|
||||
|
||||
stat, err := os.Stat(filename)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if stat.Size() < 1 {
|
||||
return errors.New("File is empty")
|
||||
}
|
||||
|
||||
file, err := os.Open(filename)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return json.NewDecoder(file).Decode(config)
|
||||
if strings.HasSuffix(filename, ".json") {
|
||||
return json.NewDecoder(file).Decode(config)
|
||||
}
|
||||
|
||||
return yaml.NewDecoder(file).Decode(config)
|
||||
}
|
||||
|
||||
// LoadAny loads the first of these files it can find
|
||||
func (config *Config) LoadAny(filenames ...string) error {
|
||||
for _, filename := range filenames {
|
||||
if err := config.Load(filename); err == nil {
|
||||
return nil
|
||||
if err := config.Load(filename); err != nil {
|
||||
continue
|
||||
}
|
||||
|
||||
*config = Config{}
|
||||
return nil
|
||||
}
|
||||
|
||||
return errors.New("Failed to load configuration files")
|
||||
@@ -65,7 +91,7 @@ func Global() Config {
|
||||
globalMutex.Lock()
|
||||
if global == nil {
|
||||
global = &Config{}
|
||||
err := global.LoadAny("/etc/aiterp/rpdata.json", "./config.json")
|
||||
err := global.LoadAny("/etc/aiterp/rpdata.yaml", "/etc/aiterp/rpdata.json", "./config.yaml", "./config.json")
|
||||
if err != nil {
|
||||
log.Fatalln(err)
|
||||
}
|
||||
|
||||
@@ -1,47 +0,0 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
)
|
||||
|
||||
// TagKind represents the kind of tags.
|
||||
type TagKind string
|
||||
|
||||
const (
|
||||
// TagKindOrganization is a tag kind, see GraphQL documentation.
|
||||
TagKindOrganization TagKind = "Organization"
|
||||
|
||||
// TagKindCharacter is a tag kind, see GraphQL documentation.
|
||||
TagKindCharacter TagKind = "Character"
|
||||
|
||||
// TagKindLocation is a tag kind, see GraphQL documentation.
|
||||
TagKindLocation TagKind = "Location"
|
||||
|
||||
// TagKindEvent is a tag kind, see GraphQL documentation.
|
||||
TagKindEvent TagKind = "Event"
|
||||
|
||||
// TagKindSeries is a tag kind, see GraphQL documentation.
|
||||
TagKindSeries TagKind = "Series"
|
||||
)
|
||||
|
||||
// UnmarshalGQL unmarshals
|
||||
func (e *TagKind) UnmarshalGQL(v interface{}) error {
|
||||
str, ok := v.(string)
|
||||
if !ok {
|
||||
return fmt.Errorf("enums must be strings")
|
||||
}
|
||||
|
||||
*e = TagKind(str)
|
||||
switch *e {
|
||||
case TagKindOrganization, TagKindCharacter, TagKindLocation, TagKindEvent, TagKindSeries:
|
||||
return nil
|
||||
default:
|
||||
return fmt.Errorf("%s is not a valid TagKind", str)
|
||||
}
|
||||
}
|
||||
|
||||
// MarshalGQL turns it into a JSON string
|
||||
func (e TagKind) MarshalGQL(w io.Writer) {
|
||||
fmt.Fprint(w, "\""+string(e), "\"")
|
||||
}
|
||||
+52
-1
@@ -1,5 +1,10 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
)
|
||||
|
||||
// A Tag associates a story with other content, like other stories, logs and more.
|
||||
type Tag struct {
|
||||
Kind TagKind `bson:"kind"`
|
||||
@@ -15,4 +20,50 @@ func (tag *Tag) Equal(other Tag) bool {
|
||||
// ChangeObject in GQL.
|
||||
func (*Tag) IsChangeObject() {
|
||||
panic("this method is a dummy, and so is its caller")
|
||||
}
|
||||
}
|
||||
|
||||
// TagKind represents the kind of tags.
|
||||
type TagKind string
|
||||
|
||||
const (
|
||||
// TagKindOrganization is a tag kind, see GraphQL documentation.
|
||||
TagKindOrganization TagKind = "Organization"
|
||||
|
||||
// TagKindCharacter is a tag kind, see GraphQL documentation.
|
||||
TagKindCharacter TagKind = "Character"
|
||||
|
||||
// TagKindLocation is a tag kind, see GraphQL documentation.
|
||||
TagKindLocation TagKind = "Location"
|
||||
|
||||
// TagKindEvent is a tag kind, see GraphQL documentation.
|
||||
TagKindEvent TagKind = "Event"
|
||||
|
||||
// TagKindSeries is a tag kind, see GraphQL documentation.
|
||||
TagKindSeries TagKind = "Series"
|
||||
)
|
||||
|
||||
// UnmarshalGQL unmarshals
|
||||
func (e *TagKind) UnmarshalGQL(v interface{}) error {
|
||||
str, ok := v.(string)
|
||||
if !ok {
|
||||
return fmt.Errorf("enums must be strings")
|
||||
}
|
||||
|
||||
*e = TagKind(str)
|
||||
switch *e {
|
||||
case TagKindOrganization, TagKindCharacter, TagKindLocation, TagKindEvent, TagKindSeries:
|
||||
return nil
|
||||
default:
|
||||
return fmt.Errorf("%s is not a valid TagKind", str)
|
||||
}
|
||||
}
|
||||
|
||||
// MarshalGQL turns it into a JSON string
|
||||
func (e TagKind) MarshalGQL(w io.Writer) {
|
||||
fmt.Fprint(w, "\""+string(e), "\"")
|
||||
}
|
||||
|
||||
// TagFilter is a filter of tags.
|
||||
type TagFilter struct {
|
||||
Kind *TagKind `bson:"kind,omitempty"`
|
||||
}
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
package repositories
|
||||
|
||||
import "errors"
|
||||
|
||||
// A Bundle is a set of repositories.
|
||||
type Bundle struct {
|
||||
Tags TagRepository
|
||||
}
|
||||
|
||||
// ErrNotFound should be returned instead of any database-specific not found error.
|
||||
var ErrNotFound = errors.New("Resource not found")
|
||||
@@ -0,0 +1,13 @@
|
||||
package repositories
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"git.aiterp.net/rpdata/api/models"
|
||||
)
|
||||
|
||||
// TagRepository is an interface for a database using logs.
|
||||
type TagRepository interface {
|
||||
Find(ctx context.Context, kind, name string) (*models.Tag, error)
|
||||
List(ctx context.Context, filter models.TagFilter) ([]*models.Tag, error)
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package services
|
||||
|
||||
import "git.aiterp.net/rpdata/api/repositories"
|
||||
|
||||
// A Bundle contains all services, like a bean bag in the more caffeinated language family.
|
||||
type Bundle struct {
|
||||
Tags *TagService
|
||||
}
|
||||
|
||||
// NewBundle creates a new bundle.
|
||||
func NewBundle(repos *repositories.Bundle) *Bundle {
|
||||
bundle := &Bundle{}
|
||||
|
||||
bundle.Tags = &TagService{tags: repos.Tags}
|
||||
|
||||
return bundle
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package services
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"git.aiterp.net/rpdata/api/models"
|
||||
"git.aiterp.net/rpdata/api/repositories"
|
||||
)
|
||||
|
||||
// TagService is a service for tag-related functions.
|
||||
type TagService struct {
|
||||
tags repositories.TagRepository
|
||||
}
|
||||
|
||||
// FindTag finds one tag.
|
||||
func (s *TagService) FindTag(ctx context.Context, source, id string) (*models.Tag, error) {
|
||||
return s.tags.Find(ctx, source, id)
|
||||
}
|
||||
|
||||
// ListTags lists tags.
|
||||
func (s *TagService) ListTags(ctx context.Context, filter models.TagFilter) ([]*models.Tag, error) {
|
||||
return s.tags.List(ctx, filter)
|
||||
}
|
||||
Reference in New Issue
Block a user