Browse Source

Started work on new layered setup, making a huge mess.

thegreatrefactor
Gisle Aune 5 years ago
parent
commit
cdf4e6f667
  1. 1
      .gitignore
  2. 17
      cmd/rpdata-server/main.go
  3. 22
      database/database.go
  4. 44
      database/mongodb/db.go
  5. 72
      database/mongodb/tags.go
  6. 3
      go.mod
  7. 15
      go.sum
  8. 76
      graph2/complexity.go
  9. 8
      graph2/gqlgen.yml
  10. 32
      graph2/graph.go
  11. 6
      graph2/queries/channel.go
  12. 10
      graph2/queries/chapter.go
  13. 12
      graph2/queries/character.go
  14. 21
      graph2/queries/comment.go
  15. 13
      graph2/queries/log.go
  16. 15
      graph2/queries/post.go
  17. 13
      graph2/queries/resolver.go
  18. 17
      graph2/queries/story.go
  19. 17
      graph2/queries/tags.go
  20. 5
      graph2/queries/unknownnicks.go
  21. 2
      graph2/schema/root.gql
  22. 9
      graph2/schema/types/Tag.gql
  23. 8
      graph2/types/change.go
  24. 2
      internal/auth/permissions.go
  25. 53
      internal/auth/permitted.go
  26. 9
      internal/auth/token.go
  27. 82
      internal/config/config.go
  28. 47
      models/tag-kind.go
  29. 53
      models/tag.go
  30. 11
      repositories/repository.go
  31. 13
      repositories/tag.go
  32. 17
      services/services.go
  33. 23
      services/tags.go

1
.gitignore

@ -9,5 +9,6 @@ rpdata-*
!rpdata-*/
.vscode
/graph2/graphcore/*_gen.go
generated.gql
generated.go

17
cmd/rpdata-server/main.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()))

22
database/database.go

@ -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
}
}

44
database/mongodb/db.go

@ -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
}

72
database/mongodb/tags.go

@ -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
}

3
go.mod

@ -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

15
go.sum

@ -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=

76
graph2/complexity.go

@ -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
}

8
graph2/gqlgen.yml

@ -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:

32
graph2/graph.go

@ -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{}
type rootResolver struct {
s *services.Bundle
}
func (r *rootResolver) Query() QueryResolver {
return &queries.Resolver
func (r *rootResolver) Query() graphcore.QueryResolver {
return queries.QueryResolver(r.s)
}
func (r *rootResolver) Mutation() MutationResolver {
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
}

6
graph2/queries/channel.go

@ -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")

10
graph2/queries/chapter.go

@ -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")

12
graph2/queries/character.go

@ -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")

21
graph2/queries/comment.go

@ -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/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/graph2/input"
"git.aiterp.net/rpdata/api/internal/auth"
"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"
"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")

13
graph2/queries/log.go

@ -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")

15
graph2/queries/post.go

@ -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")

13
graph2/queries/resolver.go

@ -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

17
graph2/queries/story.go

@ -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)

17
graph2/queries/tags.go

@ -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)
}

5
graph2/queries/unknownnicks.go

@ -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 {

2
graph2/schema/root.gql

@ -46,7 +46,7 @@ type Query {
# Find all distinct tags used in stories
tags: [Tag!]!
tags(filter: TagFilter): [Tag!]!
# Find story by ID

9
graph2/schema/types/Tag.gql

@ -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...

8
graph2/types/change.go

@ -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)

2
internal/auth/permissions.go

@ -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",

53
internal/auth/permitted.go

@ -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
}

9
internal/auth/token.go

@ -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)

82
internal/config/config.go

@ -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"`
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"`
Wiki struct {
URL string `json:"url"`
} `json:"wiki"`
Space Space `json:"space" yaml:"space"`
Database Database `json:"database" yaml:"database"`
Wiki Wiki `json:"wiki" yaml:"wiki"`
}
// 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"`
}
// 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)
}

47
models/tag-kind.go

@ -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), "\"")
}

53
models/tag.go

@ -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"`
}

11
repositories/repository.go

@ -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")

13
repositories/tag.go

@ -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)
}

17
services/services.go

@ -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
}

23
services/tags.go

@ -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)
}
Loading…
Cancel
Save