snapshot of https://github.com/traggo/server.git (master, 2026-09-16; blobs > 131072B omitted)
Some checks failed
build / build (push) Failing after 3s
Some checks failed
build / build (push) Failing after 3s
This commit is contained in:
13
graphql/directive.go
Normal file
13
graphql/directive.go
Normal file
@@ -0,0 +1,13 @@
|
||||
package graphql
|
||||
|
||||
import (
|
||||
"github.com/traggo/server/auth"
|
||||
"github.com/traggo/server/generated/gqlschema"
|
||||
)
|
||||
|
||||
// NewDirective creates a new directive.
|
||||
func NewDirective() gqlschema.DirectiveRoot {
|
||||
return gqlschema.DirectiveRoot{
|
||||
HasRole: auth.HasRole(),
|
||||
}
|
||||
}
|
||||
32
graphql/handler.go
Normal file
32
graphql/handler.go
Normal file
@@ -0,0 +1,32 @@
|
||||
package graphql
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"github.com/99designs/gqlgen/handler"
|
||||
"github.com/traggo/server/generated/gqlschema"
|
||||
"github.com/traggo/server/logger"
|
||||
)
|
||||
|
||||
// Handler combines graphql handler and playground handler.
|
||||
func Handler(endpoint string, resolvers gqlschema.ResolverRoot, directives gqlschema.DirectiveRoot) http.HandlerFunc {
|
||||
gqlHandler := handler.GraphQL(gqlschema.NewExecutableSchema(gqlschema.Config{
|
||||
Resolvers: resolvers,
|
||||
Directives: directives,
|
||||
}), handler.RequestMiddleware(logger.GQLLog()))
|
||||
playground := handler.Playground("Traggo Playground", endpoint)
|
||||
|
||||
return func(writer http.ResponseWriter, request *http.Request) {
|
||||
if acceptHTMLAndNotJSON(request) {
|
||||
playground.ServeHTTP(writer, request)
|
||||
} else {
|
||||
gqlHandler.ServeHTTP(writer, request)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func acceptHTMLAndNotJSON(request *http.Request) bool {
|
||||
val := request.Header.Get("Accept")
|
||||
return strings.Contains(val, "text/html") && !strings.Contains(val, "application/json")
|
||||
}
|
||||
42
graphql/handler_test.go
Normal file
42
graphql/handler_test.go
Normal file
@@ -0,0 +1,42 @@
|
||||
package graphql
|
||||
|
||||
import (
|
||||
"net/http/httptest"
|
||||
"net/url"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
"github.com/traggo/server/model"
|
||||
"github.com/traggo/server/test"
|
||||
)
|
||||
|
||||
func TestHandler_jsonOverHtml(t *testing.T) {
|
||||
db := test.InMemoryDB(t)
|
||||
defer db.Close()
|
||||
resolver := NewResolver(db.DB, 4, model.Version{})
|
||||
handler := Handler("/gql", resolver, NewDirective())
|
||||
req := httptest.NewRequest("GET", "/gql?query="+url.QueryEscape("query {currentUser {name}}"), strings.NewReader(""))
|
||||
req.Header.Set("Accept", "text/html;application/json")
|
||||
recorder := httptest.NewRecorder()
|
||||
handler.ServeHTTP(recorder, req)
|
||||
require.Equal(t, "application/graphql-response+json", recorder.Header().Get("Content-Type"))
|
||||
require.JSONEq(t, `
|
||||
{
|
||||
"data": { "currentUser": null }
|
||||
}
|
||||
`, recorder.Body.String())
|
||||
}
|
||||
|
||||
func TestHandler_htmlIfNotJson(t *testing.T) {
|
||||
db := test.InMemoryDB(t)
|
||||
defer db.Close()
|
||||
resolver := NewResolver(db.DB, 4, model.Version{})
|
||||
handler := Handler("/gql", resolver, NewDirective())
|
||||
req := httptest.NewRequest("get", "/gql", strings.NewReader(""))
|
||||
req.Header.Set("Accept", "text/html;application/xml")
|
||||
recorder := httptest.NewRecorder()
|
||||
handler.ServeHTTP(recorder, req)
|
||||
|
||||
require.Contains(t, recorder.Body.String(), "Traggo Playground")
|
||||
}
|
||||
71
graphql/resolver.go
Normal file
71
graphql/resolver.go
Normal file
@@ -0,0 +1,71 @@
|
||||
package graphql
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/traggo/server/dashboard"
|
||||
"github.com/traggo/server/setting"
|
||||
|
||||
"github.com/jinzhu/copier"
|
||||
"github.com/jinzhu/gorm"
|
||||
"github.com/traggo/server/device"
|
||||
"github.com/traggo/server/generated/gqlmodel"
|
||||
"github.com/traggo/server/generated/gqlschema"
|
||||
"github.com/traggo/server/model"
|
||||
"github.com/traggo/server/statistics"
|
||||
"github.com/traggo/server/tag"
|
||||
"github.com/traggo/server/timespan"
|
||||
"github.com/traggo/server/user"
|
||||
)
|
||||
|
||||
// NewResolver combines all resolvers to a resolver root.
|
||||
func NewResolver(db *gorm.DB, passStrength int, version model.Version) gqlschema.ResolverRoot {
|
||||
return &resolver{
|
||||
ResolverForUser: user.ResolverForUser{
|
||||
DB: db,
|
||||
PassStrength: passStrength,
|
||||
},
|
||||
ResolverForTag: tag.ResolverForTag{
|
||||
DB: db,
|
||||
},
|
||||
ResolverForDevice: device.ResolverForDevice{
|
||||
DB: db,
|
||||
},
|
||||
ResolverForTimeSpan: timespan.ResolverForTimeSpan{
|
||||
DB: db,
|
||||
},
|
||||
ResolverForStatistics: statistics.ResolverForStatistics{
|
||||
DB: db,
|
||||
},
|
||||
ResolverForSettings: setting.ResolverForSettings{
|
||||
DB: db,
|
||||
},
|
||||
ResolverForDashboard: dashboard.NewResolverForDashboard(db),
|
||||
version: version,
|
||||
}
|
||||
}
|
||||
|
||||
type resolver struct {
|
||||
user.ResolverForUser
|
||||
tag.ResolverForTag
|
||||
device.ResolverForDevice
|
||||
timespan.ResolverForTimeSpan
|
||||
statistics.ResolverForStatistics
|
||||
version model.Version
|
||||
setting.ResolverForSettings
|
||||
dashboard.ResolverForDashboard
|
||||
}
|
||||
|
||||
func (r *resolver) RootMutation() gqlschema.RootMutationResolver {
|
||||
return r
|
||||
}
|
||||
|
||||
func (r *resolver) RootQuery() gqlschema.RootQueryResolver {
|
||||
return r
|
||||
}
|
||||
|
||||
func (r *resolver) Version(ctx context.Context) (*gqlmodel.Version, error) {
|
||||
gql := &gqlmodel.Version{}
|
||||
copier.Copy(gql, r.version)
|
||||
return gql, nil
|
||||
}
|
||||
22
graphql/resolver_test.go
Normal file
22
graphql/resolver_test.go
Normal file
@@ -0,0 +1,22 @@
|
||||
package graphql
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/traggo/server/generated/gqlmodel"
|
||||
"github.com/traggo/server/model"
|
||||
"github.com/traggo/server/test"
|
||||
)
|
||||
|
||||
func TestNewResolver_doesNotThrow(t *testing.T) {
|
||||
db := test.InMemoryDB(t)
|
||||
defer db.Close()
|
||||
resolver := NewResolver(db.DB, 4, model.Version{Name: "oops", BuildDate: "date", Commit: "aeu"})
|
||||
resolver.RootMutation()
|
||||
resolver.RootQuery()
|
||||
version, e := resolver.RootQuery().Version(context.Background())
|
||||
assert.NoError(t, e)
|
||||
assert.Equal(t, &gqlmodel.Version{Name: "oops", BuildDate: "date", Commit: "aeu"}, version)
|
||||
}
|
||||
Reference in New Issue
Block a user