snapshot of https://github.com/traggo/server.git (master, 2026-09-16; blobs > 131072B omitted)
Some checks failed
build / build (push) Failing after 3s

This commit is contained in:
upstream-mirror
2026-09-16 05:24:45 +05:00
commit cda7c1a474
272 changed files with 31973 additions and 0 deletions

13
graphql/directive.go Normal file
View 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
View 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
View 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
View 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
View 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)
}