Compare commits

...
19 Commits
Author SHA1 Message Date
gisle 162ccf6bfb The great module madness continus, now with pointers.
the build was successful
2019-05-17 11:51:23 +02:00
gisle 7e3dc49635 Basic stuff, doesn't compile 2019-05-16 15:57:08 +02:00
gisle aff0d99842 graph2: Added exception for open logs query in complexity.
the build was successful
2019-04-27 11:37:01 +02:00
gisle 00150118d2 graph2: Added complexity to prevent queries that can take down the server.
the build was successful
2019-04-25 20:47:20 +02:00
gisle 332a1eb32b Fixed rpdata-as2storyimport not compiling. 2019-03-17 21:32:21 +01:00
gisle db4d46c368 Added story to comment changes.
the build was successful
2019-03-17 20:44:30 +01:00
gisle a8c8610ca2 models: Fixed wrong database mapping for comment source.
the build was successful
2019-01-17 21:19:13 +01:00
gisle d09c17d30d graph2: Changed addComment error message on can-comment check to be consistent with others.
the build was successful
2019-01-16 22:07:00 +01:00
gisle e3e3ea07db graph2: Changed Chapter to not return any comments if mode is disabled, even if there are comments.
the build was successful
2019-01-16 22:05:40 +01:00
gisle 22592439da graph2, models: Added removeComment mutation.
the build was successful
2019-01-16 22:03:28 +01:00
gisle dfa9fb4025 graph2: Changed Comment to return null instead of a zero-date if it's cleared.
the build was successful
2019-01-16 21:50:53 +01:00
gisle 0e2a68a2d4 graph2, models: Added editComment mutation. 2019-01-16 21:45:00 +01:00
gisle 1eefa65527 models: Fixed wrong database mapping for comment id. 2019-01-16 21:41:36 +01:00
gisle f9b6af58c9 graph2: Changed Comment character resolver to use loader.
the build was successful
2019-01-15 21:42:44 +01:00
gisle 56ecf48b57 graph2, models: Added addComment mutation.
the build was successful
2019-01-15 21:34:57 +01:00
gisle 06fbfc90c5 graph2, model: Added Comment type to Change. 2019-01-14 19:58:05 +01:00
gisle 39a4fef506 models, graph2: Added comment removal on chapter removal.
the build was successful
2019-01-14 18:01:43 +01:00
gisle f9fe0bb5f8 models, graph2: Added comment options to chapter mutations.
the build was successful
2019-01-14 17:55:38 +01:00
gisle d22ab387dd models, graph2: Added Comment type and queries, and hooked it up to chapter.
the build was successful
2019-01-14 17:03:16 +01:00
55 changed files with 1301 additions and 512 deletions
+3 -7
View File
@@ -1,16 +1,12 @@
## 1. Build Server
# Use Go 1.10
FROM golang:1.11 AS build-server
# Use Go 1.12
FROM golang:1.12 AS build-server
# Load repository into docker
WORKDIR /go/src/git.aiterp.net/rpdata/api/
WORKDIR /project/
COPY . .
RUN rm -rf ./vendor
# Install build tools and dependencies
RUN go get -u github.com/golang/dep/cmd/dep
RUN go get -u github.com/vektah/gorunpkg
RUN dep ensure
RUN go generate ./...
# Build server and tools (CGO disabled to make them 100% static)
Generated
-250
View File
@@ -1,250 +0,0 @@
# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'.
[[projects]]
name = "github.com/99designs/gqlgen"
packages = [
".",
"cmd",
"codegen",
"codegen/templates",
"complexity",
"graphql",
"graphql/introspection",
"handler",
"internal/gopath"
]
revision = "636435b68700211441303f1a5ed92f3768ba5774"
version = "v0.5.1"
[[projects]]
name = "github.com/agnivade/levenshtein"
packages = ["."]
revision = "3d21ba515fe27b856f230847e856431ae1724adc"
version = "v1.0.0"
[[projects]]
name = "github.com/davecgh/go-spew"
packages = ["spew"]
revision = "8991bc29aa16c548c550c7ff78260e27b9ab7c73"
version = "v1.1.1"
[[projects]]
name = "github.com/dgrijalva/jwt-go"
packages = ["."]
revision = "06ea1031745cb8b3dab3f6a236daf2b0aa468b7e"
version = "v3.2.0"
[[projects]]
branch = "master"
name = "github.com/dustin/go-humanize"
packages = ["."]
revision = "bb3d318650d48840a39aa21a027c6630e198e626"
[[projects]]
branch = "master"
name = "github.com/globalsign/mgo"
packages = [
".",
"bson",
"internal/json",
"internal/sasl",
"internal/scram"
]
revision = "f76e4f9da92ecd56e3be26f5ba92580af1ef97b4"
[[projects]]
name = "github.com/go-ini/ini"
packages = ["."]
revision = "ace140f73450505f33e8b8418216792275ae82a7"
version = "v1.35.0"
[[projects]]
name = "github.com/go-sql-driver/mysql"
packages = ["."]
revision = "d523deb1b23d913de5bdada721a6071e71283618"
version = "v1.4.0"
[[projects]]
name = "github.com/gorilla/websocket"
packages = ["."]
revision = "66b9c49e59c6c48f0ffce28c2d8b8a5678502c6d"
version = "v1.4.0"
[[projects]]
name = "github.com/graph-gophers/dataloader"
packages = ["."]
revision = "78139374585c29dcb97b8f33089ed11959e4be59"
version = "v5"
[[projects]]
name = "github.com/hashicorp/golang-lru"
packages = [
".",
"simplelru"
]
revision = "20f1fb78b0740ba8c3cb143a61e86ba5c8669768"
version = "v0.5.0"
[[projects]]
branch = "master"
name = "github.com/jmoiron/sqlx"
packages = [
".",
"reflectx"
]
revision = "0dae4fefe7c0e190f7b5a78dac28a1c82cc8d849"
[[projects]]
name = "github.com/minio/minio-go"
packages = [
".",
"pkg/credentials",
"pkg/encrypt",
"pkg/s3signer",
"pkg/s3utils",
"pkg/set"
]
revision = "3d2d02921f0510e9d1f66ef77a265b8dddd36992"
version = "6.0.0"
[[projects]]
branch = "master"
name = "github.com/mitchellh/go-homedir"
packages = ["."]
revision = "b8bc1bf767474819792c23f32d8286a45736f1c6"
[[projects]]
name = "github.com/opentracing/opentracing-go"
packages = [
".",
"log"
]
revision = "1949ddbfd147afd4d964a9f00b24eb291e0e7c38"
version = "v1.0.2"
[[projects]]
name = "github.com/pkg/errors"
packages = ["."]
revision = "645ef00459ed84a119197bfb8d8205042c6df63d"
version = "v0.8.0"
[[projects]]
name = "github.com/pmezard/go-difflib"
packages = ["difflib"]
revision = "792786c7400a136282c1664665ae0a8db921c6c2"
version = "v1.0.0"
[[projects]]
name = "github.com/sirupsen/logrus"
packages = ["."]
revision = "c155da19408a8799da419ed3eeb0cb5db0ad5dbc"
version = "v1.0.5"
[[projects]]
name = "github.com/stretchr/testify"
packages = ["assert"]
revision = "f35b8ab0b5a2cef36673838d662e249dd9c94686"
version = "v1.2.2"
[[projects]]
name = "github.com/urfave/cli"
packages = ["."]
revision = "cfb38830724cc34fedffe9a2a29fb54fa9169cd1"
version = "v1.20.0"
[[projects]]
branch = "master"
name = "github.com/vektah/gqlparser"
packages = [
".",
"ast",
"gqlerror",
"lexer",
"parser",
"validator",
"validator/rules"
]
revision = "14e83ae06ec152e6d0afb9766a00e0c0918aa8fc"
[[projects]]
branch = "master"
name = "golang.org/x/crypto"
packages = [
"argon2",
"blake2b",
"ssh/terminal"
]
revision = "d6449816ce06963d9d136eee5a56fca5b0616e7e"
[[projects]]
branch = "master"
name = "golang.org/x/net"
packages = [
"context",
"idna",
"lex/httplex"
]
revision = "a35a21de978d84ffc92f010a153705b170b2f9d1"
[[projects]]
branch = "master"
name = "golang.org/x/sys"
packages = [
"unix",
"windows"
]
revision = "2f57af4873d00d535c5c9028850aa2152e6a5566"
[[projects]]
name = "golang.org/x/text"
packages = [
"collate",
"collate/build",
"internal/colltab",
"internal/gen",
"internal/tag",
"internal/triegen",
"internal/ucd",
"language",
"secure/bidirule",
"transform",
"unicode/bidi",
"unicode/cldr",
"unicode/norm",
"unicode/rangetable"
]
revision = "f21a4dfb5e38f5895301dc265a8def02365cc3d0"
version = "v0.3.0"
[[projects]]
branch = "master"
name = "golang.org/x/tools"
packages = [
"go/ast/astutil",
"go/buildutil",
"go/internal/cgo",
"go/loader",
"imports",
"internal/fastwalk"
]
revision = "677d2ff680c188ddb7dcd2bfa6bc7d3f2f2f75b2"
[[projects]]
name = "google.golang.org/appengine"
packages = ["cloudsql"]
revision = "b1f26356af11148e710935ed1ac8a7f5702c7612"
version = "v1.1.0"
[[projects]]
name = "gopkg.in/yaml.v2"
packages = ["."]
revision = "5420a8b6744d3b0345ab293f6fcba19c978f1183"
version = "v2.2.1"
[solve-meta]
analyzer-name = "dep"
analyzer-version = 1
inputs-digest = "eb8fc099a909f5d8f756b24fbcb6cc2856e132bd3ed16b8fe512f22fabb99596"
solver-name = "gps-cdcl"
solver-version = 1
-43
View File
@@ -1,43 +0,0 @@
# Gopkg.toml example
#
# Refer to https://golang.github.io/dep/docs/Gopkg.toml.html
# for detailed Gopkg.toml documentation.
#
# required = ["github.com/user/thing/cmd/thing"]
# ignored = ["github.com/user/project/pkgX", "bitbucket.org/user/project/pkgA/pkgY"]
#
# [[constraint]]
# name = "github.com/user/project"
# version = "1.0.0"
#
# [[constraint]]
# name = "github.com/user/project2"
# branch = "dev"
# source = "github.com/myfork/project2"
#
# [[override]]
# name = "github.com/x/y"
# version = "2.4.0"
#
# [prune]
# non-go = false
# go-tests = true
# unused-packages = true
required = [ "github.com/99designs/gqlgen" ]
[[constraint]]
branch = "master"
name = "github.com/globalsign/mgo"
[[constraint]]
name = "github.com/minio/minio-go"
version = "6.0.0"
[prune]
go-tests = true
unused-packages = true
[[constraint]]
name = "github.com/stretchr/testify"
version = "1.2.2"
+1 -1
View File
@@ -104,7 +104,7 @@ func main() {
}
}
chapter, err := chapters.Add(story, title, result.Author[5:], result.Source, publishDate, &fictionalDate)
chapter, err := chapters.Add(story, title, result.Author[5:], result.Source, publishDate, &fictionalDate, models.ChapterCommentModeDisabled)
if err != nil {
log.Fatalln(err)
}
+6 -5
View File
@@ -8,15 +8,13 @@ import (
"runtime/debug"
"strings"
"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/graph2"
"git.aiterp.net/rpdata/api/internal/auth"
"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"
"github.com/99designs/gqlgen/handler"
)
@@ -64,6 +62,8 @@ func logListedChanges() {
log.Printf("\tTag: (%s,%s)", object.Kind, object.Name)
case models.Chapter:
log.Printf("\tChapter: %s", object.ID)
case models.Comment:
log.Printf("\tComment: %s", object.ID)
}
}
}
@@ -80,6 +80,7 @@ func queryHandler() http.HandlerFunc {
return fmt.Errorf("The server failed to serve your request due to an internal error, it has been logged")
}),
handler.ComplexityLimit(300),
)
return func(w http.ResponseWriter, r *http.Request) {
+34
View File
@@ -0,0 +1,34 @@
module git.aiterp.net/rpdata/api
go 1.12
require (
github.com/99designs/gqlgen v0.8.0
github.com/agnivade/levenshtein v1.0.1
github.com/davecgh/go-spew v1.1.1
github.com/dgrijalva/jwt-go v3.2.0+incompatible
github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4
github.com/globalsign/mgo v0.0.0-20180403085842-f76e4f9da92e
github.com/go-ini/ini v1.35.0
github.com/go-sql-driver/mysql v1.4.0
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
github.com/jmoiron/sqlx v0.0.0-20180614180643-0dae4fefe7c0
github.com/minio/minio-go v0.0.0-20180409193742-3d2d02921f05
github.com/mitchellh/go-homedir v0.0.0-20161203194507-b8bc1bf76747
github.com/opentracing/opentracing-go v1.0.2
github.com/pkg/errors v0.8.1
github.com/pmezard/go-difflib v1.0.0
github.com/sirupsen/logrus v1.0.5
github.com/stretchr/testify v1.3.0
github.com/urfave/cli v1.20.0
github.com/vektah/gqlparser v1.1.0
golang.org/x/crypto v0.0.0-20180411161317-d6449816ce06
golang.org/x/net v0.0.0-20180416171110-a35a21de978d
golang.org/x/sys v0.0.0-20180416112224-2f57af4873d0
golang.org/x/text v0.3.0
golang.org/x/tools v0.0.0-20190125232054-d66bd3c5d5a6
google.golang.org/appengine v1.1.0
gopkg.in/yaml.v2 v2.2.2
)
+90
View File
@@ -0,0 +1,90 @@
github.com/99designs/gqlgen v0.5.1 h1:cRsbpZgX83PrXb0/hj5EkNdmaVN4l/Eii81Z8LCexgY=
github.com/99designs/gqlgen v0.5.1/go.mod h1:KSQDfLlTTGmzlRgLGm6HeKKKo598l5E2svEM6Nz2Jnw=
github.com/99designs/gqlgen v0.8.0 h1:ZBteuSgeeFwn+mztjDqQZQdVa9pqslmPnDeCovcnc0Y=
github.com/99designs/gqlgen v0.8.0/go.mod h1:st7qHA6ssU3uRZkmv+wzrzgX4srvIqEIdE5iuRW8GhE=
github.com/99designs/gqlgen v0.8.3 h1:I6bMglXNKkn4KlvkSMzqZw53e1N2FF9Gud4NmsOxqiA=
github.com/99designs/gqlgen v0.8.3/go.mod h1:aLyJw9xUgdJxZ8EqNQxo2pGFhXXJ/hq8t7J4yn8TgI4=
github.com/agnivade/levenshtein v1.0.0 h1:q+77q31bLT5jhN3BHKA1276nUEdbz7XjDa0o5dRKcZ0=
github.com/agnivade/levenshtein v1.0.0/go.mod h1:CURSv5d9Uaml+FovSIICkLbAUZ9S4RqaHDIsdSBg7lM=
github.com/agnivade/levenshtein v1.0.1 h1:3oJU7J3FGFmyhn8KHjmVaZCN5hxTr7GxgRue+sxIXdQ=
github.com/agnivade/levenshtein v1.0.1/go.mod h1:CURSv5d9Uaml+FovSIICkLbAUZ9S4RqaHDIsdSBg7lM=
github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
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=
github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
github.com/globalsign/mgo v0.0.0-20180403085842-f76e4f9da92e h1:hmrbHva/wKD6X4M7pgHVbg/KfVV1wwgr1NEkQaVD3rU=
github.com/globalsign/mgo v0.0.0-20180403085842-f76e4f9da92e/go.mod h1:xkRDCp4j0OGD1HRkm4kmhM+pmpv3AKq5SU7GMg4oO/Q=
github.com/go-chi/chi v3.3.2+incompatible/go.mod h1:eB3wogJHnLi3x/kFX2A+IbTBlXxmMeXJVKy9tTv1XzQ=
github.com/go-ini/ini v1.35.0 h1:D/my3+xOfqZMkJpciRcyqU7XMBUgiZa9qXjZIa8uv2k=
github.com/go-ini/ini v1.35.0/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3Ies8=
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/gogo/protobuf v1.0.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
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=
github.com/gorilla/websocket v1.4.0 h1:WDFjx/TMzVgy9VdMMQi2K2Emtwi2QcUQsztZ/zLaH/Q=
github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
github.com/graph-gophers/dataloader v0.0.0-20180104184831-78139374585c h1:94S+uoVVMpQAEOrqGjCDyUdML4dJDkh6aC4MYmXECg4=
github.com/graph-gophers/dataloader v0.0.0-20180104184831-78139374585c/go.mod h1:jk4jk0c5ZISbKaMe8WsVopGB5/15GvGHMdMdPtwlRp4=
github.com/hashicorp/golang-lru v0.5.0 h1:CL2msUPvZTLb5O648aiLNJw3hnBxN2+1Jq8rCOH9wdo=
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/jmoiron/sqlx v0.0.0-20180614180643-0dae4fefe7c0 h1:5B0uxl2lzNRVkJVg+uGHxWtRt4C0Wjc6kJKo5XYx8xE=
github.com/jmoiron/sqlx v0.0.0-20180614180643-0dae4fefe7c0/go.mod h1:IiEW3SEiiErVyFdH8NTuWjSifiEQKUoyK3LNqr2kCHU=
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/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/minio/minio-go v0.0.0-20180409193742-3d2d02921f05 h1:YEyFCqmHcmbcTLqZ7yEAg7VIUat6PuDzGbIctZy888k=
github.com/minio/minio-go v0.0.0-20180409193742-3d2d02921f05/go.mod h1:7guKYtitv8dktvNUGrhzmNlA5wrAABTQXCoesZdFQO8=
github.com/mitchellh/go-homedir v0.0.0-20161203194507-b8bc1bf76747 h1:eQox4Rh4ewJF+mqYPxCkmBAirRnPaHEB26UkNuPyjlk=
github.com/mitchellh/go-homedir v0.0.0-20161203194507-b8bc1bf76747/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
github.com/mitchellh/mapstructure v0.0.0-20180203102830-a4e142e9c047/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
github.com/opentracing/basictracer-go v1.0.0/go.mod h1:QfBfYuafItcjQuMwinw9GhYKwFXS9KnPs5lxoYwgW74=
github.com/opentracing/opentracing-go v1.0.2 h1:3jA2P6O1F9UOrWVpwrIo17pu01KWvNWg4X946/Y5Zwg=
github.com/opentracing/opentracing-go v1.0.2/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=
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/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/rs/cors v1.6.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU=
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=
github.com/sirupsen/logrus v1.0.5/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc=
github.com/stretchr/objx v0.1.0/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/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
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=
github.com/vektah/gqlparser v0.0.0-20180831041411-14e83ae06ec1 h1:FYOXUtr3sYR9shto7Q/aQ1B0Onyk77aws9wGOORiz+I=
github.com/vektah/gqlparser v0.0.0-20180831041411-14e83ae06ec1/go.mod h1:K4QdSSpS2XiHHwzb18kWh3iBljB8rLC8okGXsnQy3Nc=
github.com/vektah/gqlparser v1.1.0 h1:3668p2gUlO+PiS81x957Rpr3/FPRWG6cxgCXAvTS1hw=
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=
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/net v0.0.0-20180404174746-b3c676e531a6/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180416171110-a35a21de978d h1:O2P57H5Cc+d+DJos+iweraI9rmzMYwV+45vkZdDY0Oo=
golang.org/x/net v0.0.0-20180416171110-a35a21de978d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/sys v0.0.0-20180416112224-2f57af4873d0/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/tools v0.0.0-20180911133044-677d2ff680c1 h1:dzEuQYa6+a3gROnSlgly5ERUm4SZKJt+dh+4iSbO+bI=
golang.org/x/tools v0.0.0-20180911133044-677d2ff680c1/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190125232054-d66bd3c5d5a6 h1:iZgcI2DDp6zW5v9Z/5+f0NuqoxNdmzg4hivjk2WLXpY=
golang.org/x/tools v0.0.0-20190125232054-d66bd3c5d5a6/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v2 v2.2.1 h1:mUhvW9EsL+naU5Q3cakzfE91YhliOondGd6ZrsDBHQE=
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
sourcegraph.com/sourcegraph/appdash v0.0.0-20180110180208-2cc67fd64755/go.mod h1:hI742Nqp5OhwiqlzhgfbWU4mW4yO10fP+LoT9WOswdU=
sourcegraph.com/sourcegraph/appdash-data v0.0.0-20151005221446-73f23eafcf67/go.mod h1:L5q+DGLGOQFpo1snNEkLOJT2d1YTW66rWNzatr3He1k=
+182
View File
@@ -0,0 +1,182 @@
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"
)
func complexity() (cr ComplexityRoot) {
subListComplexity := 25
bigSublistComplexity := 75
hugeSublistComplexity := 100
findComplexity := 100
listComplexity := 200
mutationComplexity := 100
cr.Query.Character = func(childComplexity int, id *string, nick *string) int {
return childComplexity + findComplexity
}
cr.Query.Characters = func(childComplexity int, filter *characters.Filter) int {
return childComplexity + listComplexity
}
cr.Query.Channel = func(childComplexity int, name string) int {
return childComplexity + findComplexity
}
cr.Query.Channels = func(childComplexity int, filter *channels.Filter) int {
return childComplexity + listComplexity
}
cr.Query.Post = func(childComplexity int, id string) int {
return childComplexity + findComplexity
}
cr.Query.Posts = func(childComplexity int, filter *posts.Filter) int {
return childComplexity + listComplexity
}
cr.Query.UnknownNicks = func(childComplexity int, filter *input.UnknownNicksFilter) int {
return childComplexity + listComplexity
}
cr.Query.Log = func(childComplexity int, id string) int {
return childComplexity + findComplexity
}
cr.Query.Logs = func(childComplexity int, filter *logs.Filter) int {
if filter != nil && filter.Open != nil && *filter.Open == true {
return childComplexity + findComplexity
}
return childComplexity + listComplexity
}
cr.Query.Chapter = func(childComplexity int, id string) int {
return childComplexity + findComplexity
}
cr.Query.Comment = func(childComplexity int, id string) int {
return childComplexity + findComplexity
}
cr.Query.Tags = func(childComplexity int) int {
return childComplexity + listComplexity
}
cr.Query.Story = func(childComplexity int, id string) int {
return childComplexity + findComplexity
}
cr.Query.Stories = func(childComplexity int, filter *stories.Filter) int {
return childComplexity + listComplexity
}
cr.Query.File = func(childComplexity int, id string) int {
return childComplexity + findComplexity
}
cr.Query.Files = func(childComplexity int, filter *files.Filter) int {
return childComplexity + listComplexity
}
cr.Query.Changes = func(childComplexity int, filter *changes.Filter) int {
return childComplexity + listComplexity
}
cr.Query.Token = func(childComplexity int) int {
return childComplexity + findComplexity
}
cr.Mutation.AddStory = func(childComplexity int, input input.StoryAddInput) int {
return childComplexity + mutationComplexity
}
cr.Mutation.AddStoryTag = func(childComplexity int, input input.StoryTagAddInput) int {
return childComplexity + mutationComplexity
}
cr.Mutation.RemoveStoryTag = func(childComplexity int, input input.StoryTagRemoveInput) int {
return childComplexity + mutationComplexity
}
cr.Mutation.EditStory = func(childComplexity int, input input.StoryEditInput) int {
return childComplexity + mutationComplexity
}
cr.Mutation.RemoveStory = func(childComplexity int, input input.StoryRemoveInput) int {
return childComplexity + mutationComplexity
}
cr.Mutation.AddChapter = func(childComplexity int, input input.ChapterAddInput) int {
return childComplexity + mutationComplexity
}
cr.Mutation.EditChapter = func(childComplexity int, input input.ChapterEditInput) int {
return childComplexity + mutationComplexity
}
cr.Mutation.MoveChapter = func(childComplexity int, input input.ChapterMoveInput) int {
return childComplexity + mutationComplexity
}
cr.Mutation.RemoveChapter = func(childComplexity int, input input.ChapterRemoveInput) int {
return childComplexity + mutationComplexity
}
cr.Mutation.AddComment = func(childComplexity int, input input.CommentAddInput) int {
return childComplexity + mutationComplexity
}
cr.Mutation.EditComment = func(childComplexity int, input input.CommentEditInput) int {
return childComplexity + mutationComplexity
}
cr.Mutation.RemoveComment = func(childComplexity int, input input.CommentRemoveInput) int {
return childComplexity + mutationComplexity
}
cr.Mutation.AddLog = func(childComplexity int, input input.LogAddInput) int {
return childComplexity + mutationComplexity
}
cr.Mutation.ImportLog = func(childComplexity int, input input.LogImportInput) int {
return childComplexity + mutationComplexity
}
cr.Mutation.EditLog = func(childComplexity int, input input.LogEditInput) int {
return childComplexity + mutationComplexity
}
cr.Mutation.RemoveLog = func(childComplexity int, input input.LogRemoveInput) int {
return childComplexity + mutationComplexity
}
cr.Mutation.AddPost = func(childComplexity int, input input.PostAddInput) int {
return childComplexity + mutationComplexity
}
cr.Mutation.EditPost = func(childComplexity int, input input.PostEditInput) int {
return childComplexity + mutationComplexity
}
cr.Mutation.MovePost = func(childComplexity int, input input.PostMoveInput) int {
return childComplexity + mutationComplexity
}
cr.Mutation.RemovePost = func(childComplexity int, input input.PostRemoveInput) int {
return childComplexity + mutationComplexity
}
cr.Mutation.AddCharacter = func(childComplexity int, input input.CharacterAddInput) int {
return childComplexity + mutationComplexity
}
cr.Mutation.AddCharacterNick = func(childComplexity int, input input.CharacterNickInput) int {
return childComplexity + mutationComplexity
}
cr.Mutation.RemoveCharacterNick = func(childComplexity int, input input.CharacterNickInput) int {
return childComplexity + mutationComplexity
}
cr.Mutation.EditCharacter = func(childComplexity int, input input.CharacterEditInput) int {
return childComplexity + mutationComplexity
}
cr.Mutation.RemoveCharacter = func(childComplexity int, input input.CharacterRemoveInput) int {
return childComplexity + mutationComplexity
}
cr.Mutation.AddChannel = func(childComplexity int, input input.ChannelAddInput) int {
return childComplexity + mutationComplexity
}
cr.Mutation.EditChannel = func(childComplexity int, input input.ChannelEditInput) int {
return childComplexity + mutationComplexity
}
cr.Log.Characters = func(childComplexity int) int {
return childComplexity + subListComplexity
}
cr.Log.Posts = func(childComplexity int, kinds []string) int {
return childComplexity + hugeSublistComplexity
}
cr.Story.Chapters = func(childComplexity int) int {
return childComplexity + bigSublistComplexity
}
cr.Story.Tags = func(childComplexity int) int {
return childComplexity + subListComplexity
}
cr.Chapter.Comments = func(childComplexity int, limit *int) int {
return childComplexity + subListComplexity
}
return
}
+7
View File
@@ -35,6 +35,13 @@ models:
model: git.aiterp.net/rpdata/api/models/logs.Filter
LogImporter:
model: git.aiterp.net/rpdata/api/models.LogImporter
Comment:
model: git.aiterp.net/rpdata/api/models.Comment
fields:
fictionalDate:
resolver: true
ChapterCommentMode:
model: git.aiterp.net/rpdata/api/models.ChapterCommentMode
Chapter:
model: git.aiterp.net/rpdata/api/models.Chapter
fields:
+7 -6
View File
@@ -7,12 +7,13 @@ import (
)
//go:generate ./combine.sh
//go:generate gorunpkg github.com/99designs/gqlgen -v
//go:generate go run github.com/99designs/gqlgen -v
// New creates a new GraphQL schema.
func New() graphql.ExecutableSchema {
return NewExecutableSchema(Config{
Resolvers: &rootResolver{},
Resolvers: &rootResolver{},
Complexity: complexity(),
})
}
@@ -34,6 +35,10 @@ func (r *rootResolver) Log() LogResolver {
return &types.LogResolver
}
func (r *rootResolver) Comment() CommentResolver {
return &types.CommentResolver
}
func (r *rootResolver) Chapter() ChapterResolver {
return &types.ChapterResolver
}
@@ -42,10 +47,6 @@ func (r *rootResolver) Story() StoryResolver {
return &types.StoryResolver
}
func (r *rootResolver) File() FileResolver {
return &types.FileResolver
}
func (r *rootResolver) Change() ChangeResolver {
return &types.ChangeResolver
}
+1 -1
View File
@@ -16,7 +16,7 @@ func (r *resolver) Changes(ctx context.Context, filter *changes.Filter) ([]model
/// Subscriptions
func (r *subscriptionResolver) Changes(ctx context.Context, keys []models.ChangeKey) (<-chan models.Change, error) {
func (r *subscriptionResolver) Changes(ctx context.Context, keys []models.ChangeKey) (<-chan *models.Change, error) {
if len(keys) == 0 {
return nil, errors.New("At least one key is required for a subscription")
}
+16 -11
View File
@@ -14,8 +14,13 @@ import (
// Queries
func (r *resolver) Channel(ctx context.Context, name string) (models.Channel, error) {
return channels.FindName(name)
func (r *resolver) Channel(ctx context.Context, name string) (*models.Channel, error) {
channel, err := channels.FindName(name)
if err != nil {
return nil, err
}
return &channel, nil
}
func (r *resolver) Channels(ctx context.Context, filter *channels.Filter) ([]models.Channel, error) {
@@ -24,10 +29,10 @@ func (r *resolver) Channels(ctx context.Context, filter *channels.Filter) ([]mod
// Mutations
func (r *mutationResolver) AddChannel(ctx context.Context, input input.ChannelAddInput) (models.Channel, error) {
func (r *mutationResolver) AddChannel(ctx context.Context, input input.ChannelAddInput) (*models.Channel, error) {
token := auth.TokenFromContext(ctx)
if !token.Authenticated() || !token.Permitted("channel.add") {
return models.Channel{}, errors.New("You are not permitted to add channels")
return nil, errors.New("You are not permitted to add channels")
}
logged := false
@@ -49,31 +54,31 @@ func (r *mutationResolver) AddChannel(ctx context.Context, input input.ChannelAd
channel, err := channels.Add(input.Name, logged, hub, eventName, locationName)
if err != nil {
return models.Channel{}, errors.New("Failed to add channel: " + err.Error())
return nil, errors.New("Failed to add channel: " + err.Error())
}
go changes.Submit("Channel", "add", token.UserID, true, changekeys.Listed(channel), channel)
return channel, nil
return &channel, nil
}
func (r *mutationResolver) EditChannel(ctx context.Context, input input.ChannelEditInput) (models.Channel, error) {
func (r *mutationResolver) EditChannel(ctx context.Context, input input.ChannelEditInput) (*models.Channel, error) {
token := auth.TokenFromContext(ctx)
if !token.Authenticated() || !token.Permitted("channel.edit") {
return models.Channel{}, errors.New("You are not permitted to edit channels")
return nil, errors.New("You are not permitted to edit channels")
}
channel, err := channels.FindName(input.Name)
if err != nil {
return models.Channel{}, errors.New("Channel not found")
return nil, errors.New("Channel not found")
}
channel, err = channels.Edit(channel, input.Logged, input.Hub, input.EventName, input.LocationName)
if err != nil {
return models.Channel{}, errors.New("Failed to edit channel: " + err.Error())
return nil, errors.New("Failed to edit channel: " + err.Error())
}
go changes.Submit("Channel", "edit", token.UserID, true, changekeys.Listed(channel), channel)
return channel, nil
return &channel, nil
}
+48 -34
View File
@@ -5,83 +5,92 @@ import (
"errors"
"time"
"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/changekeys"
"git.aiterp.net/rpdata/api/models/changes"
"git.aiterp.net/rpdata/api/internal/auth"
"git.aiterp.net/rpdata/api/models/stories"
"git.aiterp.net/rpdata/api/graph2/input"
"git.aiterp.net/rpdata/api/models"
"git.aiterp.net/rpdata/api/models/chapters"
"git.aiterp.net/rpdata/api/models/comments"
"git.aiterp.net/rpdata/api/models/stories"
)
// Queries
func (r *resolver) Chapter(ctx context.Context, id string) (models.Chapter, error) {
return chapters.FindID(id)
func (r *resolver) Chapter(ctx context.Context, id string) (*models.Chapter, error) {
chapter, err := chapters.FindID(id)
if err != nil {
return nil, err
}
return &chapter, nil
}
// Mutations
func (r *mutationResolver) AddChapter(ctx context.Context, input input.ChapterAddInput) (models.Chapter, error) {
func (r *mutationResolver) AddChapter(ctx context.Context, input input.ChapterAddInput) (*models.Chapter, error) {
story, err := stories.FindID(input.StoryID)
if err != nil {
return models.Chapter{}, errors.New("Story not found")
return nil, errors.New("Story not found")
}
token := auth.TokenFromContext(ctx)
if !token.Permitted("member", "story.add") {
return models.Chapter{}, errors.New("Unauthorized")
return nil, errors.New("Unauthorized")
}
author := token.UserID
if input.Author != nil && *input.Author != author {
if !token.Permitted("story.add") {
return models.Chapter{}, errors.New("False pretender")
return nil, errors.New("False pretender")
}
author = *input.Author
}
if !story.Open && story.Author != author {
return models.Chapter{}, errors.New("Story is not open")
return nil, errors.New("Story is not open")
}
chapter, err := chapters.Add(story, input.Title, author, input.Source, time.Now(), input.FictionalDate)
commentMode := models.ChapterCommentModeDisabled
if input.CommentMode != nil {
commentMode = *input.CommentMode
}
chapter, err := chapters.Add(story, input.Title, author, input.Source, time.Now(), input.FictionalDate, commentMode)
if err != nil {
return models.Chapter{}, errors.New("Failed to create chapter: " + err.Error())
return nil, errors.New("Failed to create chapter: " + err.Error())
}
go changes.Submit("Chapter", "add", token.UserID, story.Listed, changekeys.Listed(story, chapter), story, chapter)
return chapter, nil
return &chapter, nil
}
func (r *mutationResolver) MoveChapter(ctx context.Context, input input.ChapterMoveInput) (models.Chapter, error) {
func (r *mutationResolver) MoveChapter(ctx context.Context, input input.ChapterMoveInput) (*models.Chapter, error) {
chapter, err := chapters.FindID(input.ID)
if err != nil {
return models.Chapter{}, errors.New("Chapter not found")
return nil, errors.New("Chapter not found")
}
token := auth.TokenFromContext(ctx)
if !token.Authenticated() || !token.PermittedUser(chapter.Author, "member", "chapter.move") {
return models.Chapter{}, errors.New("You are not allowed to move this chapter")
return nil, errors.New("You are not allowed to move this chapter")
}
target, err := stories.FindID(input.StoryID)
if err != nil {
return models.Chapter{}, errors.New("Target story not found")
return nil, errors.New("Target story not found")
}
if !target.Open && !token.PermittedUser(target.Author, "member", "chapter.move") {
return models.Chapter{}, errors.New("You are not permitted to move chapters to this story")
return nil, errors.New("You are not permitted to move chapters to this story")
}
oldStoryID := chapter.StoryID
chapter, err = chapters.Move(chapter, target)
if err != nil {
return models.Chapter{}, errors.New("Failed to move chapter: " + err.Error())
return nil, errors.New("Failed to move chapter: " + err.Error())
}
go func() {
@@ -99,27 +108,27 @@ func (r *mutationResolver) MoveChapter(ctx context.Context, input input.ChapterM
changes.Submit("Chapter", "move-in", token.UserID, story.Listed, changekeys.Listed(story, chapter), story, chapter)
}()
return chapter, nil
return &chapter, nil
}
func (r *mutationResolver) EditChapter(ctx context.Context, input input.ChapterEditInput) (models.Chapter, error) {
func (r *mutationResolver) EditChapter(ctx context.Context, input input.ChapterEditInput) (*models.Chapter, error) {
chapter, err := chapters.FindID(input.ID)
if err != nil {
return models.Chapter{}, errors.New("Chapter not found")
return nil, errors.New("Chapter not found")
}
token := auth.TokenFromContext(ctx)
if !token.Authenticated() || !token.PermittedUser(chapter.Author, "member", "chapter.edit") {
return models.Chapter{}, errors.New("Unauthorized")
return nil, errors.New("Unauthorized")
}
if input.ClearFictionalDate != nil && *input.ClearFictionalDate == true {
input.FictionalDate = &time.Time{}
}
chapter, err = chapters.Edit(chapter, input.Title, input.Source, input.FictionalDate)
chapter, err = chapters.Edit(chapter, input.Title, input.Source, input.FictionalDate, input.CommentMode, input.CommentsLocked)
if err != nil {
return models.Chapter{}, errors.New("Failed to edit chapter: " + err.Error())
return nil, errors.New("Failed to edit chapter: " + err.Error())
}
go func() {
@@ -131,23 +140,28 @@ func (r *mutationResolver) EditChapter(ctx context.Context, input input.ChapterE
changes.Submit("Chapter", "edit", token.UserID, story.Listed, changekeys.Many(story, chapter), chapter)
}()
return chapter, nil
return &chapter, nil
}
func (r *mutationResolver) RemoveChapter(ctx context.Context, input input.ChapterRemoveInput) (models.Chapter, error) {
func (r *mutationResolver) RemoveChapter(ctx context.Context, input input.ChapterRemoveInput) (*models.Chapter, error) {
chapter, err := chapters.FindID(input.ID)
if err != nil {
return models.Chapter{}, errors.New("Chapter not found")
return nil, errors.New("Chapter not found")
}
token := auth.TokenFromContext(ctx)
if !token.Authenticated() || !token.PermittedUser(chapter.Author, "member", "chapter.remove") {
return models.Chapter{}, errors.New("Unauthorized")
return nil, errors.New("Unauthorized")
}
chapter, err = chapters.Remove(chapter)
if err != nil {
return models.Chapter{}, errors.New("Failed to remove chapter: " + err.Error())
return nil, errors.New("Failed to remove chapter: " + err.Error())
}
err = comments.RemoveChapter(chapter)
if err != nil {
return nil, errors.New("Chapter was removed, but comment removal failed: " + err.Error())
}
go func() {
@@ -159,5 +173,5 @@ func (r *mutationResolver) RemoveChapter(ctx context.Context, input input.Chapte
changes.Submit("Chapter", "remove", token.UserID, story.Listed, changekeys.Many(story, chapter), chapter)
}()
return chapter, nil
return &chapter, nil
}
+43 -33
View File
@@ -16,13 +16,23 @@ import (
// Queries
func (r *resolver) Character(ctx context.Context, id *string, nick *string) (models.Character, error) {
func (r *resolver) Character(ctx context.Context, id *string, nick *string) (*models.Character, error) {
if id != nil {
return characters.FindID(*id)
character, err := characters.FindID(*id)
if err != nil {
return nil, err
}
return &character, nil
} else if nick != nil {
return characters.FindNick(*nick)
character, err := characters.FindNick(*nick)
if err != nil {
return nil, err
}
return &character, nil
} else {
return models.Character{}, errors.New("You must specify either an ID or a nick")
return nil, errors.New("You must specify either an ID or a nick")
}
}
@@ -32,13 +42,13 @@ 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 input.CharacterAddInput) (*models.Character, error) {
token := auth.TokenFromContext(ctx)
if !token.Permitted("member", "character.add") {
return models.Character{}, errors.New("You are not permitted to add characters")
return nil, errors.New("You are not permitted to add characters")
}
if len(input.Name) < 2 || len(input.Nick) < 2 {
return models.Character{}, errors.New("You need to provide a name and a nick (min length: 2)")
return nil, errors.New("You need to provide a name and a nick (min length: 2)")
}
shortName := ""
@@ -56,7 +66,7 @@ func (r *mutationResolver) AddCharacter(ctx context.Context, input input.Charact
author := token.UserID
if input.Author != nil && *input.Author != author {
if !token.Permitted("character.add") {
return models.Character{}, errors.New("You are only permitted to add your own characters")
return nil, errors.New("You are only permitted to add your own characters")
}
author = *input.Author
@@ -66,109 +76,109 @@ func (r *mutationResolver) AddCharacter(ctx context.Context, input input.Charact
character, err := characters.Add(input.Nick, input.Name, shortName, author, description)
if err != nil {
return models.Character{}, errors.New("Adding character failed: " + err.Error())
return nil, errors.New("Adding character failed: " + err.Error())
}
go changes.Submit("Character", "add", token.UserID, true, changekeys.Listed(character), character)
return character, nil
return &character, nil
}
func (r *mutationResolver) AddCharacterNick(ctx context.Context, input input.CharacterNickInput) (models.Character, error) {
func (r *mutationResolver) AddCharacterNick(ctx context.Context, input input.CharacterNickInput) (*models.Character, error) {
character, err := characters.FindID(input.ID)
if err != nil {
return models.Character{}, errors.New("Character not found")
return nil, errors.New("Character not found")
}
if len(input.Nick) < 2 {
return models.Character{}, errors.New("You need to provide a valid nick (min length: 2)")
return nil, errors.New("You need to provide a valid nick (min length: 2)")
}
token := auth.TokenFromContext(ctx)
if !token.PermittedUser(character.Author, "member", "character.edit") {
return models.Character{}, errors.New("You are not permitted to edit this character")
return nil, errors.New("You are not permitted to edit this character")
}
logs.ScheduleFullUpdate()
character, err = characters.AddNick(character, input.Nick)
if err != nil {
return models.Character{}, errors.New("Failed to add nick: " + err.Error())
return nil, errors.New("Failed to add nick: " + err.Error())
}
go logs.ScheduleFullUpdate()
go changes.Submit("Character", "edit", token.UserID, true, changekeys.Listed(character), character)
return character, nil
return &character, nil
}
func (r *mutationResolver) RemoveCharacterNick(ctx context.Context, input input.CharacterNickInput) (models.Character, error) {
func (r *mutationResolver) RemoveCharacterNick(ctx context.Context, input input.CharacterNickInput) (*models.Character, error) {
character, err := characters.FindID(input.ID)
if err != nil {
return models.Character{}, errors.New("Character not found")
return nil, errors.New("Character not found")
}
token := auth.TokenFromContext(ctx)
if !token.PermittedUser(character.Author, "member", "character.edit") {
return models.Character{}, errors.New("You are not permitted to edit this character")
return nil, errors.New("You are not permitted to edit this character")
}
character, err = characters.RemoveNick(character, input.Nick)
if err != nil {
return models.Character{}, errors.New("Failed to remove nick: " + err.Error())
return nil, errors.New("Failed to remove nick: " + err.Error())
}
go logs.ScheduleFullUpdate()
go changes.Submit("Character", "edit", token.UserID, true, changekeys.Listed(character), character)
return character, nil
return &character, nil
}
func (r *mutationResolver) EditCharacter(ctx context.Context, input input.CharacterEditInput) (models.Character, error) {
func (r *mutationResolver) EditCharacter(ctx context.Context, input input.CharacterEditInput) (*models.Character, error) {
character, err := characters.FindID(input.ID)
if err != nil {
return models.Character{}, errors.New("Character not found")
return nil, errors.New("Character not found")
}
if input.Name != nil && len(*input.Name) < 2 {
return models.Character{}, errors.New("You need to provide a valid name (min length: 2)")
return nil, errors.New("You need to provide a valid name (min length: 2)")
}
if input.ShortName != nil && len(*input.ShortName) < 2 {
return models.Character{}, errors.New("You need to provide a valid short name (min length: 2)")
return nil, errors.New("You need to provide a valid short name (min length: 2)")
}
token := auth.TokenFromContext(ctx)
if !token.PermittedUser(character.Author, "member", "character.edit") {
return models.Character{}, errors.New("You are not permitted to edit this character")
return nil, errors.New("You are not permitted to edit this character")
}
character, err = characters.Edit(character, input.Name, input.ShortName, input.Description)
if err != nil {
return models.Character{}, errors.New("Failed to edit character: " + err.Error())
return nil, errors.New("Failed to edit character: " + err.Error())
}
go changes.Submit("Character", "edit", token.UserID, true, changekeys.Listed(character), character)
return character, nil
return &character, nil
}
func (r *mutationResolver) RemoveCharacter(ctx context.Context, input input.CharacterRemoveInput) (models.Character, error) {
func (r *mutationResolver) RemoveCharacter(ctx context.Context, input input.CharacterRemoveInput) (*models.Character, error) {
character, err := characters.FindID(input.ID)
if err != nil {
return models.Character{}, errors.New("Character not found")
return nil, errors.New("Character not found")
}
token := auth.TokenFromContext(ctx)
if !token.PermittedUser(character.Author, "member", "character.remove") {
return models.Character{}, errors.New("You are not permitted to remove this character")
return nil, errors.New("You are not permitted to remove this character")
}
character, err = characters.Remove(character)
if err != nil {
return models.Character{}, errors.New("Failed to remove character: " + err.Error())
return nil, errors.New("Failed to remove character: " + err.Error())
}
go changes.Submit("Character", "remove", token.UserID, true, changekeys.Listed(character), character)
return character, nil
return &character, nil
}
+180
View File
@@ -0,0 +1,180 @@
package queries
import (
"context"
"errors"
"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/internal/auth"
"git.aiterp.net/rpdata/api/models/chapters"
"git.aiterp.net/rpdata/api/models/comments"
"git.aiterp.net/rpdata/api/models"
)
// Queries
func (r *resolver) Comment(ctx context.Context, id string) (*models.Comment, error) {
comment, err := comments.Find(id)
if err != nil {
return nil, err
}
return &comment, nil
}
// Mutations
func (r *mutationResolver) AddComment(ctx context.Context, input input.CommentAddInput) (*models.Comment, error) {
chapter, err := chapters.FindID(input.ChapterID)
if err != nil {
return nil, errors.New("Chapter not found")
}
token := auth.TokenFromContext(ctx)
if !token.Permitted("member", "story.edit") {
return nil, errors.New("Unauthorized")
}
if !chapter.CanComment() {
return nil, errors.New("Comments are disabled or locked")
}
var characterPtr *models.Character
if input.CharacterID != nil {
character, err := characters.FindID(*input.CharacterID)
if err != nil {
return nil, errors.New("Character not found")
} else if character.Author != token.UserID {
return nil, errors.New("That is not your character")
}
characterPtr = &character
}
fictionalDate := time.Time{}
if input.FictionalDate != nil {
fictionalDate = *input.FictionalDate
}
subject := ""
if input.Subject != nil {
subject = *input.Subject
}
comment, err := comments.Add(chapter, subject, token.UserID, input.Source, input.CharacterName, characterPtr, time.Now(), fictionalDate)
if err != nil {
return nil, errors.New("Failed to add comment: " + err.Error())
}
go func() {
story, err := stories.FindID(chapter.StoryID)
if err != nil {
log.Println("WARNING: Couldn't log comment change:", err)
return
}
changes.Submit("Comment", "add", token.UserID, true, changekeys.Many(comment, chapter, models.Story{ID: chapter.StoryID}), comment, chapter, story)
}()
return &comment, nil
}
func (r *mutationResolver) EditComment(ctx context.Context, input input.CommentEditInput) (*models.Comment, error) {
comment, err := comments.Find(input.CommentID)
if err != nil {
return nil, errors.New("Comment not found")
}
token := auth.TokenFromContext(ctx)
if !token.PermittedUser(comment.Author, "member", "story.edit") {
return nil, errors.New("You cannot edit this comment")
}
chapter, err := chapters.FindID(comment.ChapterID)
if err != nil {
return nil, errors.New("Comment's chapter not found")
}
if !chapter.CanComment() {
return nil, errors.New("Comments are disabled or locked")
}
if input.ClearFictionalDate != nil && *input.ClearFictionalDate == true {
input.FictionalDate = &time.Time{}
}
if input.CharacterID != nil && *input.CharacterID != "" {
character, err := characters.FindID(*input.CharacterID)
if err != nil {
return nil, errors.New("Character not found")
} else if character.Author != token.UserID {
return nil, errors.New("That is not your character")
}
}
comment, err = comments.Edit(comment, input.Source, input.CharacterName, input.CharacterID, input.Subject, input.FictionalDate)
if err != nil {
return nil, errors.New("Could not post comment: " + err.Error())
}
go func() {
story, err := stories.FindID(chapter.StoryID)
if err != nil {
log.Println("WARNING: Couldn't log comment change:", err)
return
}
changes.Submit("Comment", "edit", token.UserID, true, changekeys.Many(comment, chapter, models.Story{ID: chapter.StoryID}), comment, chapter, story)
}()
return &comment, nil
}
func (r *mutationResolver) RemoveComment(ctx context.Context, input input.CommentRemoveInput) (*models.Comment, error) {
comment, err := comments.Find(input.CommentID)
if err != nil {
return nil, errors.New("Comment not found")
}
token := auth.TokenFromContext(ctx)
if !token.PermittedUser(comment.Author, "member", "story.edit") {
return nil, errors.New("You cannot remove this comment")
}
chapter, err := chapters.FindID(comment.ChapterID)
if err != nil {
return nil, errors.New("Comment's chapter not found")
}
if !chapter.CanComment() {
return nil, errors.New("Comments are disabled or locked")
}
err = comments.Remove(comment)
if err != nil {
return nil, errors.New("Failed to remove comment: " + err.Error())
}
go func() {
story, err := stories.FindID(chapter.StoryID)
if err != nil {
log.Println("WARNING: Couldn't log comment change:", err)
return
}
changes.Submit("Comment", "remove", token.UserID, true, changekeys.Many(comment, chapter, models.Story{ID: chapter.StoryID}), comment, chapter, story)
}()
return &comment, nil
}
+7 -2
View File
@@ -8,8 +8,13 @@ import (
"git.aiterp.net/rpdata/api/models/files"
)
func (r *resolver) File(ctx context.Context, id string) (models.File, error) {
return files.FindID(id)
func (r *resolver) File(ctx context.Context, id string) (*models.File, error) {
file, err := files.FindID(id)
if err != nil {
return nil, err
}
return &file, nil
}
func (r *resolver) Files(ctx context.Context, filter *files.Filter) ([]models.File, error) {
+21 -16
View File
@@ -20,8 +20,13 @@ import (
// Queries
func (r *resolver) Log(ctx context.Context, id string) (models.Log, error) {
return logs.FindID(id)
func (r *resolver) Log(ctx context.Context, id string) (*models.Log, error) {
log, err := logs.FindID(id)
if err != nil {
return nil, err
}
return &log, nil
}
func (r *resolver) Logs(ctx context.Context, filter *logs.Filter) ([]models.Log, error) {
@@ -56,10 +61,10 @@ 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 input.LogAddInput) (*models.Log, error) {
token := auth.TokenFromContext(ctx)
if !token.Authenticated() || !token.Permitted("log.add") {
return models.Log{}, errors.New("You are not permitted to add logs")
return nil, errors.New("You are not permitted to add logs")
}
open := input.Open != nil && *input.Open == true
@@ -80,7 +85,7 @@ func (r *mutationResolver) AddLog(ctx context.Context, input input.LogAddInput)
log, err := logs.Add(input.Date, input.Channel, title, event, description, open)
if !token.Authenticated() || !token.Permitted("log.add") {
return models.Log{}, errors.New("Failed to create log: " + err.Error())
return nil, errors.New("Failed to create log: " + err.Error())
}
go func() {
@@ -94,7 +99,7 @@ func (r *mutationResolver) AddLog(ctx context.Context, input input.LogAddInput)
changes.Submit("Log", "add", token.UserID, true, changekeys.Listed(log), log)
}()
return log, nil
return &log, nil
}
func (r *mutationResolver) ImportLog(ctx context.Context, input input.LogImportInput) ([]models.Log, error) {
@@ -141,44 +146,44 @@ 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 input.LogEditInput) (*models.Log, error) {
token := auth.TokenFromContext(ctx)
if !token.Authenticated() || !token.Permitted("log.edit") {
return models.Log{}, errors.New("You are not permitted to edit logs")
return nil, errors.New("You are not permitted to edit logs")
}
log, err := logs.FindID(input.ID)
if err != nil {
return models.Log{}, errors.New("Log not found")
return nil, errors.New("Log not found")
}
log, err = logs.Edit(log, input.Title, input.Event, input.Description, input.Open)
if err != nil {
return models.Log{}, errors.New("Failed to edit log: " + err.Error())
return nil, errors.New("Failed to edit log: " + err.Error())
}
go changes.Submit("Log", "edit", token.UserID, true, changekeys.Listed(log), log)
return log, nil
return &log, nil
}
func (r *mutationResolver) RemoveLog(ctx context.Context, input input.LogRemoveInput) (models.Log, error) {
func (r *mutationResolver) RemoveLog(ctx context.Context, input input.LogRemoveInput) (*models.Log, error) {
token := auth.TokenFromContext(ctx)
if !token.Authenticated() || !token.Permitted("log.remove") {
return models.Log{}, errors.New("You are not permitted to remove logs")
return nil, errors.New("You are not permitted to remove logs")
}
log, err := logs.FindID(input.ID)
if err != nil {
return models.Log{}, errors.New("Log not found")
return nil, errors.New("Log not found")
}
log, err = logs.Remove(log)
if err != nil {
return models.Log{}, errors.New("Failed to remove log: " + err.Error())
return nil, errors.New("Failed to remove log: " + err.Error())
}
go changes.Submit("Log", "remove", token.UserID, true, changekeys.Listed(log), log)
return log, nil
return &log, nil
}
+22 -17
View File
@@ -16,8 +16,13 @@ import (
// Queries
func (r *resolver) Post(ctx context.Context, id string) (models.Post, error) {
return posts.FindID(id)
func (r *resolver) Post(ctx context.Context, id string) (*models.Post, error) {
post, err := posts.FindID(id)
if err != nil {
return nil, err
}
return &post, nil
}
func (r *resolver) Posts(ctx context.Context, filter *posts.Filter) ([]models.Post, error) {
@@ -43,37 +48,37 @@ func (r *resolver) Posts(ctx context.Context, filter *posts.Filter) ([]models.Po
// Mutation
func (r *mutationResolver) AddPost(ctx context.Context, input input.PostAddInput) (models.Post, error) {
func (r *mutationResolver) AddPost(ctx context.Context, input input.PostAddInput) (*models.Post, error) {
token := auth.TokenFromContext(ctx)
if !token.Authenticated() || !token.Permitted("post.add") {
return models.Post{}, errors.New("You are not permitted to edit logs")
return nil, errors.New("You are not permitted to edit logs")
}
log, err := logs.FindID(input.LogID)
if err != nil {
return models.Post{}, err
return nil, err
}
post, err := posts.Add(log, input.Time, input.Kind, input.Nick, input.Text)
if err != nil {
return models.Post{}, err
return nil, err
}
go logs.UpdateCharacters(log, nil)
go changes.Submit("Post", "add", token.UserID, true, changekeys.Many(log, post), post)
return post, nil
return &post, nil
}
func (r *mutationResolver) EditPost(ctx context.Context, input input.PostEditInput) (models.Post, error) {
func (r *mutationResolver) EditPost(ctx context.Context, input input.PostEditInput) (*models.Post, error) {
token := auth.TokenFromContext(ctx)
if !token.Authenticated() || !token.Permitted("post.edit") {
return models.Post{}, errors.New("You are not permitted to edit logs")
return nil, errors.New("You are not permitted to edit logs")
}
post, err := posts.FindID(input.ID)
if err != nil {
return models.Post{}, errors.New("Post not found")
return nil, errors.New("Post not found")
}
if input.Nick != nil {
@@ -89,7 +94,7 @@ func (r *mutationResolver) EditPost(ctx context.Context, input input.PostEditInp
post, err = posts.Edit(post, input.Time, input.Kind, input.Nick, input.Text)
if err != nil {
return models.Post{}, errors.New("Adding post failed: " + err.Error())
return nil, errors.New("Adding post failed: " + err.Error())
}
go func() {
@@ -101,7 +106,7 @@ func (r *mutationResolver) EditPost(ctx context.Context, input input.PostEditInp
changes.Submit("Post", "edit", token.UserID, true, changekeys.Many(log, post), post)
}()
return post, nil
return &post, nil
}
func (r *mutationResolver) MovePost(ctx context.Context, input input.PostMoveInput) ([]models.Post, error) {
@@ -132,20 +137,20 @@ func (r *mutationResolver) MovePost(ctx context.Context, input input.PostMoveInp
return posts, nil
}
func (r *mutationResolver) RemovePost(ctx context.Context, input input.PostRemoveInput) (models.Post, error) {
func (r *mutationResolver) RemovePost(ctx context.Context, input input.PostRemoveInput) (*models.Post, error) {
token := auth.TokenFromContext(ctx)
if !token.Authenticated() || !token.Permitted("post.remove") {
return models.Post{}, errors.New("You are not permitted to edit logs")
return nil, errors.New("You are not permitted to edit logs")
}
post, err := posts.FindID(input.ID)
if err != nil {
return models.Post{}, errors.New("Post not found (before removing, of course)")
return nil, errors.New("Post not found (before removing, of course)")
}
post, err = posts.Remove(post)
if err != nil {
return models.Post{}, errors.New("Could not remove post: " + err.Error())
return nil, errors.New("Could not remove post: " + err.Error())
}
go func() {
@@ -158,5 +163,5 @@ func (r *mutationResolver) RemovePost(ctx context.Context, input input.PostRemov
changes.Submit("Post", "remove", token.UserID, true, changekeys.Many(log, post), post)
}()
return post, nil
return &post, nil
}
+35 -30
View File
@@ -15,8 +15,13 @@ import (
"git.aiterp.net/rpdata/api/models/stories"
)
func (r *resolver) Story(ctx context.Context, id string) (models.Story, error) {
return stories.FindID(id)
func (r *resolver) Story(ctx context.Context, id string) (*models.Story, error) {
story, err := stories.FindID(id)
if err != nil {
return nil, err
}
return &story, nil
}
func (r *resolver) Stories(ctx context.Context, filter *stories.Filter) ([]models.Story, error) {
@@ -38,16 +43,16 @@ func (r *resolver) Stories(ctx context.Context, filter *stories.Filter) ([]model
// Mutations
func (r *mutationResolver) AddStory(ctx context.Context, input input.StoryAddInput) (models.Story, error) {
func (r *mutationResolver) AddStory(ctx context.Context, input input.StoryAddInput) (*models.Story, error) {
token := auth.TokenFromContext(ctx)
if token == nil || !token.Permitted("member", "story.add") {
return models.Story{}, errors.New("Permission denied")
return nil, errors.New("Permission denied")
}
author := token.UserID
if input.Author != nil && *input.Author != author {
if !token.Permitted("story.add") {
return models.Story{}, errors.New("You are not permitted to add a story in another author's name")
return nil, errors.New("You are not permitted to add a story in another author's name")
}
author = *input.Author
@@ -63,80 +68,80 @@ func (r *mutationResolver) AddStory(ctx context.Context, input input.StoryAddInp
story, err := stories.Add(input.Name, author, input.Category, listed, open, input.Tags, time.Now(), fictionalDate)
if err != nil {
return models.Story{}, errors.New("Failed to add story: " + err.Error())
return nil, errors.New("Failed to add story: " + err.Error())
}
go changes.Submit("Story", "add", token.UserID, story.Listed, changekeys.Listed(story), story)
return story, nil
return &story, nil
}
func (r *mutationResolver) AddStoryTag(ctx context.Context, input input.StoryTagAddInput) (models.Story, error) {
func (r *mutationResolver) AddStoryTag(ctx context.Context, input input.StoryTagAddInput) (*models.Story, error) {
token := auth.TokenFromContext(ctx)
story, err := stories.FindID(input.ID)
if err != nil {
return models.Story{}, errors.New("Story not found")
return nil, errors.New("Story not found")
}
if story.Open {
if !token.Permitted("member") {
return models.Story{}, errors.New("You are not permitted to edit this story")
return nil, errors.New("You are not permitted to edit this story")
}
} else {
if !token.PermittedUser(story.Author, "member", "story.edit") {
return models.Story{}, errors.New("You are not permitted to edit this story")
return nil, errors.New("You are not permitted to edit this story")
}
}
story, err = stories.AddTag(story, input.Tag)
if err != nil {
return models.Story{}, errors.New("Failed to add story: " + err.Error())
return nil, errors.New("Failed to add story: " + err.Error())
}
go changes.Submit("Story", "tag", token.UserID, story.Listed, changekeys.Listed(story), story, input.Tag)
return story, nil
return &story, nil
}
func (r *mutationResolver) RemoveStoryTag(ctx context.Context, input input.StoryTagRemoveInput) (models.Story, error) {
func (r *mutationResolver) RemoveStoryTag(ctx context.Context, input input.StoryTagRemoveInput) (*models.Story, error) {
token := auth.TokenFromContext(ctx)
story, err := stories.FindID(input.ID)
if err != nil {
return models.Story{}, errors.New("Story not found")
return nil, errors.New("Story not found")
}
if story.Open {
if !token.Permitted("member") {
return models.Story{}, errors.New("You are not permitted to edit this story")
return nil, errors.New("You are not permitted to edit this story")
}
} else {
if !token.PermittedUser(story.Author, "member", "story.edit") {
return models.Story{}, errors.New("You are not permitted to edit this story")
return nil, errors.New("You are not permitted to edit this story")
}
}
story, err = stories.RemoveTag(story, input.Tag)
if err != nil {
return models.Story{}, errors.New("Failed to add story: " + err.Error())
return nil, errors.New("Failed to add story: " + err.Error())
}
go changes.Submit("Story", "untag", token.UserID, story.Listed, changekeys.Listed(story), story, input.Tag)
return story, nil
return &story, nil
}
func (r *mutationResolver) EditStory(ctx context.Context, input input.StoryEditInput) (models.Story, error) {
func (r *mutationResolver) EditStory(ctx context.Context, input input.StoryEditInput) (*models.Story, error) {
token := auth.TokenFromContext(ctx)
story, err := stories.FindID(input.ID)
if err != nil {
return models.Story{}, errors.New("Story not found")
return nil, errors.New("Story not found")
}
if !token.PermittedUser(story.Author, "member", "story.edit") {
return models.Story{}, errors.New("You are not permitted to remove this story")
return nil, errors.New("You are not permitted to remove this story")
}
if input.ClearFictionalDate != nil && *input.ClearFictionalDate {
@@ -145,37 +150,37 @@ func (r *mutationResolver) EditStory(ctx context.Context, input input.StoryEditI
story, err = stories.Edit(story, input.Name, input.Category, input.Listed, input.Open, input.FictionalDate)
if err != nil {
return models.Story{}, errors.New("Failed to add story: " + err.Error())
return nil, errors.New("Failed to add story: " + err.Error())
}
go changes.Submit("Story", "edit", token.UserID, story.Listed, changekeys.Listed(story), story)
return story, nil
return &story, nil
}
func (r *mutationResolver) RemoveStory(ctx context.Context, input input.StoryRemoveInput) (models.Story, error) {
func (r *mutationResolver) RemoveStory(ctx context.Context, input input.StoryRemoveInput) (*models.Story, error) {
token := auth.TokenFromContext(ctx)
story, err := stories.FindID(input.ID)
if err != nil {
return models.Story{}, errors.New("Story not found")
return nil, errors.New("Story not found")
}
if !token.PermittedUser(story.Author, "member", "story.remove") {
return models.Story{}, errors.New("You are not permitted to remove this story")
return nil, errors.New("You are not permitted to remove this story")
}
story, err = stories.Remove(story)
if err != nil {
return models.Story{}, err
return nil, err
}
err = chapters.RemoveStory(story)
if err != nil {
return models.Story{}, errors.New("Failed to remove chapters, but story is removed: " + err.Error())
return nil, errors.New("Failed to remove chapters, but story is removed: " + err.Error())
}
go changes.Submit("Story", "remove", token.UserID, story.Listed, changekeys.Listed(story), story)
return story, nil
return &story, nil
}
+3 -3
View File
@@ -8,11 +8,11 @@ import (
"git.aiterp.net/rpdata/api/models"
)
func (r *resolver) Token(ctx context.Context) (models.Token, error) {
func (r *resolver) Token(ctx context.Context) (*models.Token, error) {
token := auth.TokenFromContext(ctx)
if !token.Authenticated() {
return models.Token{}, errors.New("No (valid) token")
return nil, errors.New("No (valid) token")
}
return *token, nil
return token, nil
}
+14
View File
@@ -41,6 +41,10 @@ type Query {
chapter(id: String!): Chapter!
# Find comment by ID
comment(id: String!): Comment!
# Find all distinct tags used in stories
tags: [Tag!]!
@@ -97,6 +101,16 @@ type Mutation {
removeChapter(input: ChapterRemoveInput!): Chapter!
"Add a comment to a chapter."
addComment(input: CommentAddInput!): Comment!
"Edit a comment in a chapter."
editComment(input: CommentEditInput!): Comment!
"Remove a comemnt in a chapter."
removeComment(input: CommentRemoveInput!): Comment!
# Add a new log
addLog(input: LogAddInput!): Log!
+1 -1
View File
@@ -27,7 +27,7 @@ type Change {
objects: [ChangeObject!]!
}
union ChangeObject = Character | Channel | Log | Post | Story | Tag | Chapter
union ChangeObject = Character | Channel | Log | Post | Story | Tag | Chapter | Comment
"""
A change key is a key associated with a change, used for filtering
+38
View File
@@ -20,6 +20,35 @@ type Chapter {
# The date of edit.
editedDate: Date!
"The comment mode."
commentMode: ChapterCommentMode!
"Whether the author has locket comments."
commentsLocked: Boolean!
"A shorthand for checking whether a logged-in user can comment on this chapter."
canComment: Boolean!
"Get all chapter comments."
comments(limit: Int): [Comment!]!
}
"""
The possibles modes of comments for a chapter.
"""
enum ChapterCommentMode {
"Comments are disabled and hidden."
Disabled
"Comments should be shown as typical news article comments."
Article
"Comments should be shown in a compact form suitable for many small messages."
Chat
"Comments are going to be shown as omni-tool messages."
Message
}
# Input for addChapter mutation
@@ -41,6 +70,9 @@ input ChapterAddInput {
# Optionally, assign a fictional date for the chapter
fictionalDate: Date
"The comment mode for the chapter."
commentMode: ChapterCommentMode
}
# Input for editChapter mutation
@@ -59,6 +91,12 @@ input ChapterEditInput {
# Remove the fictional date for a chapter
clearFictionalDate: Boolean
"Set the comment mode for the chapter"
commentMode: ChapterCommentMode
"Set whether the chapter comments are locked"
commentsLocked: Boolean
}
# Input for moveChapter mutation
+91
View File
@@ -0,0 +1,91 @@
"""
A Comment represents a comment to a story chapter.
"""
type Comment {
"A unique ID of the change."
id: String!
"subject"
subject: String!
"The chapter ID the comment belongs to."
chapterId: String!
"The comment's author."
author: String!
"The displayed name of the character. This may be the same as character.name, but it does not need to be."
characterName: String!
"The character associated with the comment."
character: Character
"The fictional (IC) date of the comment."
fictionalDate: Date
"The date of creation."
createdDate: Date!
"The date of the last edit."
editedDate: Date!
"The markdown source of the comment."
source: String!
}
"""
Input for the addComment mutation
"""
input CommentAddInput {
"What chapter to comment on."
chapterId: String!
"The markdown source of the comment."
source: String!
"The name of the character associated with this comment."
characterName: String!
"Optioanlly, a character ID."
characterId: String
"Optional in-universe date of the comment."
fictionalDate: Date
"Optional subject to add to the comment, only shown in some modes."
subject: String
}
"""
Input for the editComment mutation
"""
input CommentEditInput {
"What comment to edit."
commentId: String!
"Change the markdown source."
source: String
"Change the name of the character associated with this comment."
characterName: String
"Change the character assocaited with this comment."
characterId: String
"Change the optional in-universe date of the comment."
fictionalDate: Date
"Set to clear the fictional date."
clearFictionalDate: Boolean
"Change the optional subject for the comment, only shown in some modes."
subject: String
}
"""
Input for the removeComment mutation
"""
input CommentRemoveInput {
"What comment to edit."
commentId: String!
}
+5 -3
View File
@@ -12,9 +12,11 @@ type changeResolver struct{}
func (r *changeResolver) Objects(ctx context.Context, obj *models.Change) ([]input.ChangeObject, error) {
objects := obj.Objects()
results := make([]input.ChangeObject, len(objects))
for i := range objects {
results[i] = objects[i]
results := make([]input.ChangeObject, 0, len(objects))
for _, object := range objects {
if changeObject, ok := object.(input.ChangeObject); ok {
results = append(results, changeObject)
}
}
return results, nil
+19
View File
@@ -2,9 +2,11 @@ package types
import (
"context"
"errors"
"time"
"git.aiterp.net/rpdata/api/models"
"git.aiterp.net/rpdata/api/models/comments"
)
type chapterResolver struct{}
@@ -17,5 +19,22 @@ func (r *chapterResolver) FictionalDate(ctx context.Context, chapter *models.Cha
return &chapter.FictionalDate, nil
}
func (r *chapterResolver) Comments(ctx context.Context, chapter *models.Chapter, limit *int) ([]models.Comment, error) {
limitValue := 0
if limit != nil {
if *limit < 0 {
return nil, errors.New("Limit cannot be negative")
}
limitValue = *limit
}
if !chapter.CommentMode.IsEnabled() {
return nil, nil
}
return comments.ListChapterID(chapter.ID, limitValue)
}
// ChapterResolver is a resolver
var ChapterResolver chapterResolver
+41
View File
@@ -0,0 +1,41 @@
package types
import (
"context"
"errors"
"time"
"git.aiterp.net/rpdata/api/internal/loader"
"git.aiterp.net/rpdata/api/models"
)
type commentResolver struct{}
func (r *commentResolver) Character(ctx context.Context, obj *models.Comment) (*models.Character, error) {
if obj.CharacterID == "" {
return nil, nil
}
loader := loader.FromContext(ctx)
if loader == nil {
return nil, errors.New("no loader")
}
character, err := loader.Character("id", obj.CharacterID)
if err != nil {
return nil, err
}
return &character, nil
}
func (r *commentResolver) FictionalDate(ctx context.Context, obj *models.Comment) (*time.Time, error) {
if obj.FictionalDate.IsZero() {
return nil, nil
}
return &obj.FictionalDate, nil
}
// CommentResolver is a resolver
var CommentResolver commentResolver
-16
View File
@@ -1,16 +0,0 @@
package types
import (
"context"
"git.aiterp.net/rpdata/api/models"
)
type fileResolver struct{}
func (r *fileResolver) Size(ctx context.Context, file *models.File) (int, error) {
return int(file.Size), nil
}
// FileResolver is a resolver
var FileResolver fileResolver
+2 -2
View File
@@ -11,10 +11,10 @@ import (
type logResolver struct{}
func (r *logResolver) Channel(ctx context.Context, log *models.Log) (models.Channel, error) {
func (r *logResolver) Channel(ctx context.Context, log *models.Log) (*models.Channel, error) {
loader := loader.FromContext(ctx)
if loader == nil {
return models.Channel{}, errors.New("no loader")
return nil, errors.New("no loader")
}
return loader.Channel("name", log.ChannelName)
+7 -2
View File
@@ -9,8 +9,13 @@ import (
type tokenResolver struct{}
func (r *tokenResolver) User(ctx context.Context, token *models.Token) (models.User, error) {
return users.Find(token.UserID)
func (r *tokenResolver) User(ctx context.Context, token *models.Token) (*models.User, error) {
user, err := users.Find(token.UserID)
if err != nil {
return nil, err
}
return &user, nil
}
// TokenResolver is a resolver
+5 -5
View File
@@ -11,13 +11,13 @@ import (
)
// Channel gets a character by key
func (loader *Loader) Channel(key, value string) (models.Channel, error) {
func (loader *Loader) Channel(key, value string) (*models.Channel, error) {
if !strings.HasPrefix(key, "Channel.") {
key = "Channel." + key
}
if loader.loaders[key] == nil {
return models.Channel{}, errors.New("unsupported key")
return nil, errors.New("unsupported key")
}
loader.loadPrimed(key)
@@ -25,15 +25,15 @@ func (loader *Loader) Channel(key, value string) (models.Channel, error) {
thunk := loader.loaders[key].Load(loader.ctx, dataloader.StringKey(value))
res, err := thunk()
if err != nil {
return models.Channel{}, err
return nil, err
}
channel, ok := res.(models.Channel)
if !ok {
return channel, errors.New("incorrect type")
return nil, errors.New("incorrect type")
}
return channel, nil
return &channel, nil
}
// PrimeChannels primes channels for loading along with the first one.
+3 -1
View File
@@ -24,12 +24,14 @@ const (
ChangeModelTag ChangeModel = "Tag"
// ChangeModelChapter is a value of ChangeModel
ChangeModelChapter ChangeModel = "Chapter"
// ChangeModelComment is a value of ChangeModel
ChangeModelComment ChangeModel = "Comment"
)
// IsValid returns true if the underlying string is one of the correct values.
func (e ChangeModel) IsValid() bool {
switch e {
case ChangeModelCharacter, ChangeModelChannel, ChangeModelLog, ChangeModelPost, ChangeModelStory, ChangeModelTag, ChangeModelChapter:
case ChangeModelCharacter, ChangeModelChannel, ChangeModelLog, ChangeModelPost, ChangeModelStory, ChangeModelTag, ChangeModelChapter, ChangeModelComment:
return true
}
return false
+5 -1
View File
@@ -19,6 +19,7 @@ type Change struct {
Stories []Story `bson:"stories"`
Tags []Tag `bson:"tags"`
Chapters []Chapter `bson:"chapters"`
Comments []Comment `bson:"comments"`
}
// ChangeKey is a key for a change that can be used when subscribing to them.
@@ -29,7 +30,7 @@ type ChangeKey struct {
// Objects makes a combined, mixed array of all the models stored in this change.
func (change *Change) Objects() []interface{} {
data := make([]interface{}, 0, len(change.Logs)+len(change.Characters)+len(change.Channels)+len(change.Posts)+len(change.Stories)+len(change.Tags)+len(change.Chapters))
data := make([]interface{}, 0, len(change.Logs)+len(change.Characters)+len(change.Channels)+len(change.Posts)+len(change.Stories)+len(change.Tags)+len(change.Chapters)+len(change.Comments))
for _, log := range change.Logs {
data = append(data, log)
@@ -52,6 +53,9 @@ func (change *Change) Objects() []interface{} {
for _, chapter := range change.Chapters {
data = append(data, chapter)
}
for _, comment := range change.Comments {
data = append(data, comment)
}
return data
}
+2
View File
@@ -22,6 +22,7 @@ func TestMany(t *testing.T) {
},
},
models.Post{ID: "P5"},
models.Comment{ID: "SCC1234"},
}
expectations := []models.ChangeKey{
@@ -33,6 +34,7 @@ func TestMany(t *testing.T) {
{Model: "Character", ID: "C17"},
{Model: "Channel", ID: "#Stuff"},
{Model: "Post", ID: "P5"},
{Model: "Comment", ID: "SCC1234"},
}
results := changekeys.Many(data...)
+5
View File
@@ -28,6 +28,11 @@ func TestOne(t *testing.T) {
models.Log{ID: "2018-10-23_210303325_RedrockAgency", ShortID: "L807"},
models.ChangeKey{Model: "Log", ID: "2018-10-23_210303325_RedrockAgency"},
},
{
"Comment_SCC1234",
models.Comment{ID: "SCC1234"},
models.ChangeKey{Model: "Comment", ID: "SCC1234"},
},
}
for _, row := range table {
+4
View File
@@ -81,6 +81,10 @@ func Submit(model, op, author string, listed bool, keys []models.ChangeKey, obje
change.Chapters = append(change.Chapters, object)
case []models.Chapter:
change.Chapters = append(change.Chapters, object...)
case models.Comment:
change.Comments = append(change.Comments, object)
case []models.Comment:
change.Comments = append(change.Comments, object...)
default:
log.Printf("Warning: unrecognized object in change: %#+v", object)
}
+7 -5
View File
@@ -12,13 +12,13 @@ var subList []*subscription
type subscription struct {
Keys map[string]bool
Channel chan<- models.Change
Channel chan<- *models.Change
WildCard bool
}
// Subscribe subscribes to all changes.
func Subscribe(ctx context.Context, keys []models.ChangeKey, wildcard bool) <-chan models.Change {
channel := make(chan models.Change, 64)
func Subscribe(ctx context.Context, keys []models.ChangeKey, wildcard bool) <-chan *models.Change {
channel := make(chan *models.Change, 64)
sub := &subscription{
Keys: make(map[string]bool, len(keys)),
Channel: channel,
@@ -58,16 +58,18 @@ func pushToSubscribers(change models.Change) {
subMutex.Lock()
SubLoop:
for _, sub := range subList {
changeCopy := change
if sub.WildCard && change.Listed {
select {
case sub.Channel <- change:
case sub.Channel <- &changeCopy:
default:
}
} else {
for _, key := range keys {
if sub.Keys[key] {
select {
case sub.Channel <- change:
case sub.Channel <- &changeCopy:
default:
}
+6
View File
@@ -8,3 +8,9 @@ type Channel struct {
EventName string `bson:"eventName,omitempty"`
LocationName string `bson:"locationName,omitempty"`
}
// IsChangeObject is an interface implementation to identify it as a valid
// ChangeObject in GQL.
func (*Channel) IsChangeObject() {
panic("this method is a dummy, and so is its caller")
}
+57
View File
@@ -0,0 +1,57 @@
package models
import (
"fmt"
"io"
)
// ChapterCommentMode represents the kind of tags.
type ChapterCommentMode string
const (
// ChapterCommentModeDisabled is a chapter comment mode, see GraphQL documentation.
ChapterCommentModeDisabled ChapterCommentMode = "Disabled"
// ChapterCommentModeArticle is a chapter comment mode, see GraphQL documentation.
ChapterCommentModeArticle ChapterCommentMode = "Article"
// ChapterCommentModeChat is a chapter comment mode, see GraphQL documentation.
ChapterCommentModeChat ChapterCommentMode = "Chat"
// ChapterCommentModeMessage is a chapter comment mode, see GraphQL documentation.
ChapterCommentModeMessage ChapterCommentMode = "Message"
)
// UnmarshalGQL unmarshals
func (e *ChapterCommentMode) UnmarshalGQL(v interface{}) error {
str, ok := v.(string)
if !ok {
return fmt.Errorf("enums must be strings")
}
*e = ChapterCommentMode(str)
switch *e {
case ChapterCommentModeDisabled, ChapterCommentModeArticle, ChapterCommentModeChat, ChapterCommentModeMessage:
return nil
default:
return fmt.Errorf("%s is not a valid ChapterCommentMode", str)
}
}
// IsEnabled returns true if comments are enabled.
func (e ChapterCommentMode) IsEnabled() bool {
return e != ChapterCommentModeDisabled && len(e) != 0
}
// MarshalGQL turns it into a JSON string
func (e ChapterCommentMode) MarshalGQL(w io.Writer) {
// Backwards compatibility: Empty value means disabled.
if len(e) == 0 {
w.Write(disabledChapterCommentModeBytes)
return
}
fmt.Fprint(w, "\""+string(e)+"\"")
}
var disabledChapterCommentModeBytes = []byte(`"Disabled"`)
+21 -8
View File
@@ -4,12 +4,25 @@ import "time"
// A Chapter is a part of a story.
type Chapter struct {
ID string `bson:"_id"`
StoryID string `bson:"storyId"`
Title string `bson:"title"`
Author string `bson:"author"`
Source string `bson:"source"`
CreatedDate time.Time `bson:"createdDate"`
FictionalDate time.Time `bson:"fictionalDate,omitempty"`
EditedDate time.Time `bson:"editedDate"`
ID string `bson:"_id"`
StoryID string `bson:"storyId"`
Title string `bson:"title"`
Author string `bson:"author"`
Source string `bson:"source"`
CreatedDate time.Time `bson:"createdDate"`
FictionalDate time.Time `bson:"fictionalDate,omitempty"`
EditedDate time.Time `bson:"editedDate"`
CommentMode ChapterCommentMode `bson:"commentMode"`
CommentsLocked bool `bson:"commentsLocked"`
}
// CanComment returns true if the chapter can be commented to.
func (chapter *Chapter) CanComment() bool {
return !chapter.CommentsLocked && chapter.CommentMode.IsEnabled()
}
// IsChangeObject is an interface implementation to identify it as a valid
// ChangeObject in GQL.
func (*Chapter) IsChangeObject() {
panic("this method is a dummy, and so is its caller")
}
+10 -8
View File
@@ -8,15 +8,17 @@ import (
)
// Add adds a new chapter.
func Add(story models.Story, title, author, source string, createdDate time.Time, finctionalDate *time.Time) (models.Chapter, error) {
func Add(story models.Story, title, author, source string, createdDate time.Time, finctionalDate *time.Time, commentMode models.ChapterCommentMode) (models.Chapter, error) {
chapter := models.Chapter{
ID: makeChapterID(),
StoryID: story.ID,
Title: title,
Author: author,
Source: source,
CreatedDate: createdDate,
EditedDate: createdDate,
ID: makeChapterID(),
StoryID: story.ID,
Title: title,
Author: author,
Source: source,
CreatedDate: createdDate,
EditedDate: createdDate,
CommentMode: commentMode,
CommentsLocked: false,
}
if finctionalDate != nil {
+9 -1
View File
@@ -9,7 +9,7 @@ import (
// Edit edits a chapter, and updates EditedDate. While many Edit functions cheat if there's nothing to
// change, this functill will due to EditedDate.
func Edit(chapter models.Chapter, title, source *string, fictionalDate *time.Time) (models.Chapter, error) {
func Edit(chapter models.Chapter, title, source *string, fictionalDate *time.Time, commentMode *models.ChapterCommentMode, commentsLocked *bool) (models.Chapter, error) {
now := time.Now()
changes := bson.M{"editedDate": now}
@@ -28,6 +28,14 @@ func Edit(chapter models.Chapter, title, source *string, fictionalDate *time.Tim
changes["fictionalDate"] = *fictionalDate
edited.FictionalDate = *fictionalDate
}
if commentMode != nil && *commentMode != chapter.CommentMode {
changes["commentMode"] = *commentMode
edited.CommentMode = *commentMode
}
if commentsLocked != nil && *commentsLocked != chapter.CommentsLocked {
changes["commentsLocked"] = *commentsLocked
edited.CommentsLocked = *commentsLocked
}
err := collection.UpdateId(chapter.ID, bson.M{"$set": changes})
if err != nil {
+6
View File
@@ -29,3 +29,9 @@ func (character *Character) HasNick(nick string) bool {
return false
}
// IsChangeObject is an interface implementation to identify it as a valid
// ChangeObject in GQL.
func (*Character) IsChangeObject() {
panic("this method is a dummy, and so is its caller")
}
+23
View File
@@ -0,0 +1,23 @@
package models
import "time"
// A Comment is a comment on a chapter.
type Comment struct {
ID string `bson:"_id"`
ChapterID string `bson:"chapterId"`
Subject string `bson:"subject"`
Author string `bson:"author"`
CharacterName string `bson:"characterName"`
CharacterID string `bson:"characterId"`
FictionalDate time.Time `bson:"fictionalDate"`
CreatedDate time.Time `bson:"createdDate"`
EditedDate time.Time `bson:"editeddDate"`
Source string `bson:"source"`
}
// IsChangeObject is an interface implementation to identify it as a valid
// ChangeObject in GQL.
func (*Comment) IsChangeObject() {
panic("this method is a dummy, and so is its caller")
}
+35
View File
@@ -0,0 +1,35 @@
package comments
import (
"time"
"git.aiterp.net/rpdata/api/models"
)
// Add adds a comment.
func Add(chapter models.Chapter, subject, author, source, characterName string, character *models.Character, createdDate time.Time, fictionalDate time.Time) (models.Comment, error) {
characterID := ""
if character != nil {
characterID = character.ID
}
comment := models.Comment{
ID: makeCommentID(),
ChapterID: chapter.ID,
Subject: subject,
Author: author,
CharacterName: characterName,
CharacterID: characterID,
FictionalDate: fictionalDate,
CreatedDate: createdDate,
EditedDate: createdDate,
Source: source,
}
err := collection.Insert(comment)
if err != nil {
return models.Comment{}, err
}
return comment, nil
}
+66
View File
@@ -0,0 +1,66 @@
package comments
import (
"crypto/rand"
"encoding/binary"
"strconv"
"git.aiterp.net/rpdata/api/internal/store"
"git.aiterp.net/rpdata/api/models"
"github.com/globalsign/mgo"
)
var collection *mgo.Collection
func find(query interface{}) (models.Comment, error) {
comment := models.Comment{}
err := collection.Find(query).One(&comment)
return comment, err
}
func list(query interface{}, limit int) ([]models.Comment, error) {
allocSize := 32
if limit >= 0 {
allocSize = limit
} else {
limit = 0
}
comments := make([]models.Comment, 0, allocSize)
err := collection.Find(query).Sort("createdDate").Limit(limit).All(&comments)
if err != nil {
return nil, err
}
return comments, nil
}
func makeCommentID() string {
result := "SCC"
offset := 0
data := make([]byte, 48)
rand.Read(data)
for len(result) < 32 {
result += strconv.FormatUint(binary.LittleEndian.Uint64(data[offset:]), 36)
offset += 8
if offset >= 48 {
rand.Read(data)
offset = 0
}
}
return result[:32]
}
func init() {
store.HandleInit(func(db *mgo.Database) {
collection = db.C("story.comments")
collection.EnsureIndexKey("chapterId")
collection.EnsureIndexKey("author")
collection.EnsureIndexKey("createdDate")
})
}
+44
View File
@@ -0,0 +1,44 @@
package comments
import (
"time"
"git.aiterp.net/rpdata/api/models"
"github.com/globalsign/mgo/bson"
)
// Edit edits a comment.
func Edit(comment models.Comment, source, characterName, characterID, subject *string, fictionalDate *time.Time) (models.Comment, error) {
changes := make(bson.M, 6)
comment.EditedDate = time.Now()
changes["editedDate"] = comment.EditedDate
if source != nil {
comment.Source = *source
changes["source"] = *source
}
if characterName != nil {
comment.CharacterName = *characterName
changes["characterName"] = *characterName
}
if characterID != nil {
comment.CharacterID = *characterID
changes["characterId"] = *characterID
}
if subject != nil {
comment.Subject = *subject
changes["subject"] = *subject
}
if fictionalDate != nil {
comment.FictionalDate = *fictionalDate
changes["fictionalDate"] = *fictionalDate
}
err := collection.UpdateId(comment.ID, bson.M{"$set": changes})
if err != nil {
return models.Comment{}, err
}
return comment, nil
}
+11
View File
@@ -0,0 +1,11 @@
package comments
import (
"git.aiterp.net/rpdata/api/models"
"github.com/globalsign/mgo/bson"
)
// Find finds a comment by ID.
func Find(id string) (models.Comment, error) {
return find(bson.M{"_id": id})
}
+11
View File
@@ -0,0 +1,11 @@
package comments
import (
"git.aiterp.net/rpdata/api/models"
"github.com/globalsign/mgo/bson"
)
// ListChapterID lists all comments by chapter-ID
func ListChapterID(chapterID string, limit int) ([]models.Comment, error) {
return list(bson.M{"chapterId": chapterID}, limit)
}
+17
View File
@@ -0,0 +1,17 @@
package comments
import (
"git.aiterp.net/rpdata/api/models"
"github.com/globalsign/mgo/bson"
)
// Remove removes one comment.
func Remove(comment models.Comment) error {
return collection.RemoveId(comment.ID)
}
// RemoveChapter removes all comments for the given chapter.
func RemoveChapter(chapter models.Chapter) error {
_, err := collection.RemoveAll(bson.M{"chapterId": chapter.ID})
return err
}
+6
View File
@@ -14,3 +14,9 @@ type File struct {
Author string `bson:"author" json:"author"`
URL string `bson:"url,omitempty" json:"url,omitempty"`
}
// IsChangeObject is an interface implementation to identify it as a valid
// ChangeObject in GQL.
func (*File) IsChangeObject() {
panic("this method is a dummy, and so is its caller")
}
+6
View File
@@ -14,3 +14,9 @@ type Log struct {
Open bool `bson:"open"`
CharacterIDs []string `bson:"characterIds"`
}
// IsChangeObject is an interface implementation to identify it as a valid
// ChangeObject in GQL.
func (*Log) IsChangeObject() {
panic("this method is a dummy, and so is its caller")
}
+6
View File
@@ -12,3 +12,9 @@ type Post struct {
Text string `bson:"text"`
Position int `bson:"position"`
}
// IsChangeObject is an interface implementation to identify it as a valid
// ChangeObject in GQL.
func (*Post) IsChangeObject() {
panic("this method is a dummy, and so is its caller")
}
+6
View File
@@ -16,3 +16,9 @@ type Story struct {
FictionalDate time.Time `bson:"fictionalDate,omitempty"`
UpdatedDate time.Time `bson:"updatedDate"`
}
// IsChangeObject is an interface implementation to identify it as a valid
// ChangeObject in GQL.
func (*Story) IsChangeObject() {
panic("this method is a dummy, and so is its caller")
}
+6
View File
@@ -10,3 +10,9 @@ type Tag struct {
func (tag *Tag) Equal(other Tag) bool {
return tag.Kind == other.Kind && tag.Name == other.Name
}
// IsChangeObject is an interface implementation to identify it as a valid
// ChangeObject in GQL.
func (*Tag) IsChangeObject() {
panic("this method is a dummy, and so is its caller")
}