the big refactor
This commit is contained in:
245
internal/gql/graphqlTypes.go
Normal file
245
internal/gql/graphqlTypes.go
Normal file
@@ -0,0 +1,245 @@
|
||||
package gql
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"path/filepath"
|
||||
"time"
|
||||
|
||||
"github.com/graph-gophers/dataloader"
|
||||
"github.com/graphql-go/graphql"
|
||||
"github.com/graphql-go/graphql/language/ast"
|
||||
|
||||
helper "git.kapelle.org/niklas/s3browser/internal/helper"
|
||||
types "git.kapelle.org/niklas/s3browser/internal/types"
|
||||
)
|
||||
|
||||
type LoginResult struct {
|
||||
Token string `json:"token"`
|
||||
Successful bool `json:"successful"`
|
||||
}
|
||||
|
||||
var graphqlDirType *graphql.Object
|
||||
var graphqlFileType *graphql.Object
|
||||
var graphqlLoginResultType *graphql.Object
|
||||
|
||||
//GraphqlTypes create all graphql types and stores the in the global variables
|
||||
func GraphqlTypes() {
|
||||
|
||||
var dateTimeType = graphql.NewScalar(graphql.ScalarConfig{
|
||||
Name: "DateTime",
|
||||
Description: "DateTime is a DateTime in ISO 8601 format",
|
||||
Serialize: func(value interface{}) interface{} {
|
||||
switch value := value.(type) {
|
||||
case time.Time:
|
||||
return value.Format(time.RFC3339)
|
||||
}
|
||||
|
||||
return "INVALID"
|
||||
},
|
||||
ParseValue: func(value interface{}) interface{} {
|
||||
switch tvalue := value.(type) {
|
||||
case string:
|
||||
if tval, err := time.Parse(time.RFC3339, tvalue); err != nil {
|
||||
return nil
|
||||
} else {
|
||||
return tval
|
||||
}
|
||||
}
|
||||
return nil
|
||||
},
|
||||
ParseLiteral: func(valueAST ast.Value) interface{} {
|
||||
switch valueAST := valueAST.(type) {
|
||||
case *ast.StringValue:
|
||||
return valueAST.Value
|
||||
}
|
||||
return nil
|
||||
},
|
||||
})
|
||||
|
||||
graphqlDirType = graphql.NewObject(graphql.ObjectConfig{
|
||||
Name: "Directory",
|
||||
Description: "Represents a directory",
|
||||
Fields: graphql.Fields{
|
||||
"id": &graphql.Field{
|
||||
Type: graphql.NewNonNull(graphql.ID),
|
||||
},
|
||||
"name": &graphql.Field{
|
||||
Type: graphql.String,
|
||||
Resolve: func(p graphql.ResolveParams) (interface{}, error) {
|
||||
source, ok := p.Source.(types.Directory)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("Failed to parse source for resolve")
|
||||
}
|
||||
|
||||
return filepath.Base(source.ID), nil
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
graphqlFileType = graphql.NewObject(graphql.ObjectConfig{
|
||||
Name: "File",
|
||||
Description: "Represents a file, not a directory",
|
||||
Fields: graphql.Fields{
|
||||
"id": &graphql.Field{
|
||||
Type: graphql.NewNonNull(graphql.ID),
|
||||
Description: "The uniqe ID of the file. Represents the path and the s3 key.",
|
||||
},
|
||||
"name": &graphql.Field{
|
||||
Type: graphql.String,
|
||||
Resolve: func(p graphql.ResolveParams) (interface{}, error) {
|
||||
source, ok := p.Source.(types.File)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("Failed to parse source for resolve")
|
||||
}
|
||||
|
||||
return filepath.Base(source.ID), nil
|
||||
},
|
||||
},
|
||||
"size": &graphql.Field{
|
||||
Type: graphql.NewNonNull(graphql.Int),
|
||||
Resolve: func(p graphql.ResolveParams) (interface{}, error) {
|
||||
file, err := loadFile(p)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return file.Size, nil
|
||||
},
|
||||
},
|
||||
"contentType": &graphql.Field{
|
||||
Type: graphql.String,
|
||||
Resolve: func(p graphql.ResolveParams) (interface{}, error) {
|
||||
file, err := loadFile(p)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return file.ContentType, nil
|
||||
},
|
||||
},
|
||||
"etag": &graphql.Field{
|
||||
Type: graphql.String,
|
||||
Resolve: func(p graphql.ResolveParams) (interface{}, error) {
|
||||
file, err := loadFile(p)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return file.ETag, nil
|
||||
},
|
||||
},
|
||||
"lastModified": &graphql.Field{
|
||||
Type: dateTimeType,
|
||||
Resolve: func(p graphql.ResolveParams) (interface{}, error) {
|
||||
file, err := loadFile(p)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return file.LastModified, nil
|
||||
},
|
||||
},
|
||||
"parent": &graphql.Field{
|
||||
Type: graphqlDirType,
|
||||
Resolve: func(p graphql.ResolveParams) (interface{}, error) {
|
||||
source, ok := p.Source.(types.File)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("Failed to parse Source for parent resolve")
|
||||
}
|
||||
|
||||
basename := helper.GetPathFromId(source.ID)
|
||||
|
||||
return types.Directory{
|
||||
ID: basename,
|
||||
}, nil
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
graphqlDirType.AddFieldConfig("files", &graphql.Field{
|
||||
Type: graphql.NewList(graphqlFileType),
|
||||
Resolve: func(p graphql.ResolveParams) (interface{}, error) {
|
||||
source, ok := p.Source.(types.Directory)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("Failed to parse Source for files resolve")
|
||||
}
|
||||
|
||||
loader := p.Context.Value("loader").(map[string]*dataloader.Loader)
|
||||
|
||||
thunk := loader["getFiles"].Load(p.Context, dataloader.StringKey(helper.NomalizeID(source.ID)))
|
||||
return thunk()
|
||||
},
|
||||
})
|
||||
|
||||
graphqlDirType.AddFieldConfig("directorys", &graphql.Field{
|
||||
Type: graphql.NewList(graphqlDirType),
|
||||
Resolve: func(p graphql.ResolveParams) (interface{}, error) {
|
||||
source, ok := p.Source.(types.Directory)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("Failed to parse Source for directories resolve")
|
||||
}
|
||||
|
||||
loader := p.Context.Value("loader").(map[string]*dataloader.Loader)
|
||||
thunk := loader["getDirs"].Load(p.Context, dataloader.StringKey(helper.NomalizeID(source.ID)))
|
||||
|
||||
return thunk()
|
||||
},
|
||||
})
|
||||
|
||||
graphqlDirType.AddFieldConfig("parent", &graphql.Field{
|
||||
Type: graphqlDirType,
|
||||
Resolve: func(p graphql.ResolveParams) (interface{}, error) {
|
||||
source, ok := p.Source.(types.Directory)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("Failed to parse Source for directories resolve")
|
||||
}
|
||||
|
||||
return types.Directory{
|
||||
ID: helper.GetParentDir(source.ID),
|
||||
}, nil
|
||||
},
|
||||
})
|
||||
|
||||
graphqlLoginResultType = graphql.NewObject(graphql.ObjectConfig{
|
||||
Name: "LoginResut",
|
||||
Description: "Result of a login",
|
||||
Fields: graphql.Fields{
|
||||
"token": &graphql.Field{
|
||||
Type: graphql.String,
|
||||
Description: "JWT token if login was successful",
|
||||
},
|
||||
"successful": &graphql.Field{
|
||||
Type: graphql.NewNonNull(graphql.Boolean),
|
||||
Description: "If the login was successful",
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
//loadFile helper func for using the dataloader to get a file
|
||||
func loadFile(p graphql.ResolveParams) (*types.File, error) {
|
||||
source, ok := p.Source.(types.File)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("Failed to parse source for resolve")
|
||||
}
|
||||
|
||||
loader := p.Context.Value("loader").(map[string]*dataloader.Loader)
|
||||
|
||||
thunk := loader["getFile"].Load(p.Context, dataloader.StringKey(helper.NomalizeID(source.ID)))
|
||||
result, err := thunk()
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
file, ok := result.(*types.File)
|
||||
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("Failed to load file")
|
||||
}
|
||||
|
||||
return file, err
|
||||
}
|
||||
220
internal/gql/mutations.go
Normal file
220
internal/gql/mutations.go
Normal file
@@ -0,0 +1,220 @@
|
||||
package gql
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/graph-gophers/dataloader"
|
||||
"github.com/minio/minio-go/v7"
|
||||
|
||||
helper "git.kapelle.org/niklas/s3browser/internal/helper"
|
||||
types "git.kapelle.org/niklas/s3browser/internal/types"
|
||||
)
|
||||
|
||||
func deleteMutation(ctx context.Context, id string) error {
|
||||
s3Client, ok := ctx.Value("s3Client").(*minio.Client)
|
||||
|
||||
if !ok {
|
||||
return fmt.Errorf("Failed to get s3Client from context")
|
||||
}
|
||||
|
||||
// TODO: it is posible to remove multiple objects with a single call.
|
||||
// Is it better to batch this?
|
||||
err := s3Client.RemoveObject(ctx, "dev", id, minio.RemoveObjectOptions{})
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Invalidate cache
|
||||
return helper.InvalidateCache(ctx, helper.NomalizeID(id))
|
||||
}
|
||||
|
||||
func copyMutation(ctx context.Context, src, dest string) (*types.File, error) {
|
||||
s3Client, ok := ctx.Value("s3Client").(*minio.Client)
|
||||
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("Failed to get s3Client from context")
|
||||
}
|
||||
|
||||
// Check if dest is a file or a dir
|
||||
if strings.HasSuffix(dest, "/") {
|
||||
// create new dest id
|
||||
// TODO: What if a file with this id already exists?
|
||||
dest += helper.GetFilenameFromID(src)
|
||||
}
|
||||
|
||||
info, err := s3Client.CopyObject(ctx, minio.CopyDestOptions{
|
||||
Bucket: "dev",
|
||||
Object: dest,
|
||||
}, minio.CopySrcOptions{
|
||||
Bucket: "dev",
|
||||
Object: src,
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Invalidate cache
|
||||
// TODO: check error
|
||||
helper.InvalidateCache(ctx, helper.NomalizeID(info.Key))
|
||||
|
||||
return &types.File{
|
||||
ID: info.Key,
|
||||
}, nil
|
||||
|
||||
}
|
||||
|
||||
func moveMutation(ctx context.Context, src, dest string) (*types.File, error) {
|
||||
s3Client, ok := ctx.Value("s3Client").(*minio.Client)
|
||||
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("Failed to get s3Client from context")
|
||||
}
|
||||
|
||||
// Check if dest is a file or a dir
|
||||
if strings.HasSuffix(dest, "/") {
|
||||
// create new dest id
|
||||
// TODO: What if a file with this id already exists?
|
||||
dest += helper.GetFilenameFromID(src)
|
||||
}
|
||||
|
||||
// There is no (spoon) move. Only copy and delete
|
||||
info, err := s3Client.CopyObject(ctx, minio.CopyDestOptions{
|
||||
Bucket: "dev",
|
||||
Object: dest,
|
||||
}, minio.CopySrcOptions{
|
||||
Bucket: "dev",
|
||||
Object: src,
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = deleteMutation(ctx, src)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
helper.InvalidateCache(ctx, helper.NomalizeID(info.Key))
|
||||
|
||||
return &types.File{
|
||||
ID: info.Key,
|
||||
}, nil
|
||||
|
||||
}
|
||||
|
||||
func createDirectory(ctx context.Context, path string) (*types.Directory, error) {
|
||||
s3Client, ok := ctx.Value("s3Client").(*minio.Client)
|
||||
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("Failed to get s3Client from context")
|
||||
}
|
||||
|
||||
if !strings.HasSuffix(path, "/") {
|
||||
path += "/"
|
||||
}
|
||||
|
||||
info, err := s3Client.PutObject(ctx, "dev", path, strings.NewReader(""), 0, minio.PutObjectOptions{
|
||||
ContentType: "application/x-directory",
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Invalidate cache
|
||||
// TODO: check error
|
||||
helper.InvalidateCacheForDir(ctx, helper.NomalizeID(info.Key))
|
||||
|
||||
return &types.Directory{
|
||||
ID: info.Key,
|
||||
}, nil
|
||||
|
||||
}
|
||||
|
||||
func deleteDirectory(ctx context.Context, path string) error {
|
||||
s3Client, ok := ctx.Value("s3Client").(*minio.Client)
|
||||
|
||||
if !ok {
|
||||
return fmt.Errorf("Failed to get s3Client from context")
|
||||
}
|
||||
|
||||
loader, ok := ctx.Value("loader").(map[string]*dataloader.Loader)
|
||||
|
||||
if !ok {
|
||||
return fmt.Errorf("Failed to get dataloader from context")
|
||||
}
|
||||
|
||||
if !strings.HasSuffix(path, "/") {
|
||||
path += "/"
|
||||
}
|
||||
|
||||
// Get all files inside the directory
|
||||
thunk := loader["listObjectsRecursive"].Load(ctx, dataloader.StringKey(helper.NomalizeID(path)))
|
||||
|
||||
result, err := thunk()
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
files, ok := result.([]minio.ObjectInfo)
|
||||
if !ok {
|
||||
return fmt.Errorf("Failed to get parse result from listObjects")
|
||||
}
|
||||
|
||||
// Delete all child files
|
||||
err = helper.DeleteMultiple(ctx, *s3Client, files)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// If the dir had no children it exists as an object (object with "/" at the end).
|
||||
// If it exists as an object and had children it will get delete once the last child has been deleted
|
||||
// If it had no children we have to delete it manualy
|
||||
// This is at least the behavior when working with minio as s3 backend
|
||||
// TODO: check if this is normal behavior when working with s3
|
||||
if len(files) == 0 {
|
||||
err := s3Client.RemoveObject(ctx, "dev", path, minio.RemoveObjectOptions{})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
//Invalidate cache
|
||||
helper.InvalidateCacheForDir(ctx, helper.NomalizeID(path))
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
//login Checks for valid username password combination. Returns singed jwt string
|
||||
func login(ctx context.Context, username, password string) (LoginResult, error) {
|
||||
|
||||
// TODO: replace with propper user management
|
||||
if username != "admin" && password != "hunter2" {
|
||||
return LoginResult{
|
||||
Successful: false,
|
||||
}, nil
|
||||
}
|
||||
|
||||
token := helper.CreateJWT(helper.CreateClaims(username))
|
||||
|
||||
tokenString, err := token.SignedString([]byte("TODO"))
|
||||
|
||||
if err != nil {
|
||||
return LoginResult{
|
||||
Successful: false,
|
||||
}, err
|
||||
}
|
||||
|
||||
return LoginResult{
|
||||
Token: tokenString,
|
||||
Successful: true,
|
||||
}, nil
|
||||
}
|
||||
274
internal/gql/schema.go
Normal file
274
internal/gql/schema.go
Normal file
@@ -0,0 +1,274 @@
|
||||
package gql
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/graph-gophers/dataloader"
|
||||
"github.com/graphql-go/graphql"
|
||||
|
||||
helper "git.kapelle.org/niklas/s3browser/internal/helper"
|
||||
types "git.kapelle.org/niklas/s3browser/internal/types"
|
||||
log "github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
//GraphqlSchema generate the schema with its root query and mutation
|
||||
func GraphqlSchema() (graphql.Schema, error) {
|
||||
|
||||
queryFields := graphql.Fields{
|
||||
"files": &graphql.Field{
|
||||
Type: graphql.NewNonNull(graphql.NewList(graphql.NewNonNull(graphqlFileType))),
|
||||
Args: graphql.FieldConfigArgument{
|
||||
"path": &graphql.ArgumentConfig{
|
||||
Type: graphql.NewNonNull(graphql.String),
|
||||
},
|
||||
},
|
||||
Resolve: func(p graphql.ResolveParams) (interface{}, error) {
|
||||
if is, err := helper.IsAuth(p.Context); !is {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
path, ok := p.Args["path"].(string)
|
||||
|
||||
if !ok {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
log.Debug("querry 'files': ", path)
|
||||
|
||||
loader := p.Context.Value("loader").(map[string]*dataloader.Loader)
|
||||
thunk := loader["getFiles"].Load(p.Context, dataloader.StringKey(path))
|
||||
return thunk()
|
||||
},
|
||||
},
|
||||
"directorys": &graphql.Field{
|
||||
Type: graphql.NewNonNull(graphql.NewList(graphql.NewNonNull(graphqlDirType))),
|
||||
Args: graphql.FieldConfigArgument{
|
||||
"path": &graphql.ArgumentConfig{
|
||||
Type: graphql.NewNonNull(graphql.String),
|
||||
},
|
||||
},
|
||||
Resolve: func(p graphql.ResolveParams) (interface{}, error) {
|
||||
if is, err := helper.IsAuth(p.Context); !is {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
path, ok := p.Args["path"].(string)
|
||||
|
||||
if !ok {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
log.Debug("querry 'directorys': ", path)
|
||||
|
||||
loader := p.Context.Value("loader").(map[string]*dataloader.Loader)
|
||||
thunk := loader["getDirs"].Load(p.Context, dataloader.StringKey(path))
|
||||
return thunk()
|
||||
},
|
||||
},
|
||||
"file": &graphql.Field{
|
||||
Type: graphqlFileType,
|
||||
Args: graphql.FieldConfigArgument{
|
||||
"id": &graphql.ArgumentConfig{
|
||||
Type: graphql.NewNonNull(graphql.ID),
|
||||
},
|
||||
},
|
||||
Resolve: func(p graphql.ResolveParams) (interface{}, error) {
|
||||
if is, err := helper.IsAuth(p.Context); !is {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
id, ok := p.Args["id"].(string)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("Failed to parse args")
|
||||
}
|
||||
|
||||
log.Debug("querry 'file': ", id)
|
||||
|
||||
return types.File{
|
||||
ID: id,
|
||||
}, nil
|
||||
},
|
||||
},
|
||||
"authorized": &graphql.Field{
|
||||
Name: "authorized",
|
||||
Type: graphql.NewNonNull(graphql.Boolean),
|
||||
Description: "True if the user is authorized",
|
||||
Resolve: func(p graphql.ResolveParams) (interface{}, error) {
|
||||
auth, _ := helper.IsAuth(p.Context)
|
||||
|
||||
return auth, nil
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
mutationFields := graphql.Fields{
|
||||
"delete": &graphql.Field{
|
||||
Type: graphql.String,
|
||||
Args: graphql.FieldConfigArgument{
|
||||
"id": &graphql.ArgumentConfig{
|
||||
Type: graphql.NewNonNull(graphql.ID),
|
||||
},
|
||||
},
|
||||
Resolve: func(p graphql.ResolveParams) (interface{}, error) {
|
||||
if is, err := helper.IsAuth(p.Context); !is {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
id, ok := p.Args["id"].(string)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("Failed to parse args")
|
||||
}
|
||||
|
||||
log.Debug("mutation 'delete': ", id)
|
||||
|
||||
return id, deleteMutation(p.Context, id)
|
||||
},
|
||||
},
|
||||
"copy": &graphql.Field{
|
||||
Type: graphqlFileType,
|
||||
Args: graphql.FieldConfigArgument{
|
||||
"src": &graphql.ArgumentConfig{
|
||||
Type: graphql.NewNonNull(graphql.ID),
|
||||
},
|
||||
"dest": &graphql.ArgumentConfig{
|
||||
Type: graphql.NewNonNull(graphql.ID),
|
||||
},
|
||||
},
|
||||
Resolve: func(p graphql.ResolveParams) (interface{}, error) {
|
||||
if is, err := helper.IsAuth(p.Context); !is {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
src, ok := p.Args["src"].(string)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("Failed to parse args")
|
||||
}
|
||||
dest, ok := p.Args["dest"].(string)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("Failed to parse args")
|
||||
}
|
||||
|
||||
log.Debug("mutation 'copy': ", src, "-->", dest)
|
||||
|
||||
return copyMutation(p.Context, src, dest)
|
||||
},
|
||||
},
|
||||
"move": &graphql.Field{
|
||||
Type: graphqlFileType,
|
||||
Args: graphql.FieldConfigArgument{
|
||||
"src": &graphql.ArgumentConfig{
|
||||
Type: graphql.NewNonNull(graphql.ID),
|
||||
},
|
||||
"dest": &graphql.ArgumentConfig{
|
||||
Type: graphql.NewNonNull(graphql.ID),
|
||||
},
|
||||
},
|
||||
Resolve: func(p graphql.ResolveParams) (interface{}, error) {
|
||||
if is, err := helper.IsAuth(p.Context); !is {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
src, ok := p.Args["src"].(string)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("Failed to parse args")
|
||||
}
|
||||
dest, ok := p.Args["dest"].(string)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("Failed to parse args")
|
||||
}
|
||||
|
||||
log.Debug("mutation 'move': ", src, "-->", dest)
|
||||
|
||||
return moveMutation(p.Context, src, dest)
|
||||
},
|
||||
},
|
||||
"createDir": &graphql.Field{
|
||||
Type: graphql.NewNonNull(graphqlDirType),
|
||||
Args: graphql.FieldConfigArgument{
|
||||
"path": &graphql.ArgumentConfig{
|
||||
Type: graphql.NewNonNull(graphql.ID),
|
||||
},
|
||||
},
|
||||
Resolve: func(p graphql.ResolveParams) (interface{}, error) {
|
||||
if is, err := helper.IsAuth(p.Context); !is {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
path, ok := p.Args["path"].(string)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("Failed to parse args")
|
||||
}
|
||||
|
||||
log.Debug("mutation 'createDir': ", path)
|
||||
|
||||
return createDirectory(p.Context, path)
|
||||
},
|
||||
},
|
||||
"deleteDir": &graphql.Field{
|
||||
Type: graphql.NewNonNull(graphql.String),
|
||||
Args: graphql.FieldConfigArgument{
|
||||
"path": &graphql.ArgumentConfig{
|
||||
Type: graphql.NewNonNull(graphql.ID),
|
||||
},
|
||||
},
|
||||
Resolve: func(p graphql.ResolveParams) (interface{}, error) {
|
||||
if is, err := helper.IsAuth(p.Context); !is {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
path, ok := p.Args["path"].(string)
|
||||
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("Failed to parse args")
|
||||
}
|
||||
|
||||
log.Debug("mutation 'deleteDir': ", path)
|
||||
|
||||
return path, deleteDirectory(p.Context, path)
|
||||
},
|
||||
},
|
||||
"login": &graphql.Field{
|
||||
Type: graphql.NewNonNull(graphqlLoginResultType),
|
||||
Args: graphql.FieldConfigArgument{
|
||||
"username": &graphql.ArgumentConfig{
|
||||
Type: graphql.NewNonNull(graphql.String),
|
||||
},
|
||||
"password": &graphql.ArgumentConfig{
|
||||
Type: graphql.NewNonNull(graphql.String),
|
||||
},
|
||||
},
|
||||
Resolve: func(p graphql.ResolveParams) (interface{}, error) {
|
||||
username, ok := p.Args["username"].(string)
|
||||
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("Failed to parse args")
|
||||
}
|
||||
|
||||
password, ok := p.Args["password"].(string)
|
||||
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("Failed to parse args")
|
||||
}
|
||||
|
||||
return login(p.Context, username, password)
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
rootQuery := graphql.ObjectConfig{
|
||||
Name: "RootQuery",
|
||||
Fields: queryFields,
|
||||
}
|
||||
|
||||
rootMutation := graphql.ObjectConfig{
|
||||
Name: "RootMutation",
|
||||
Fields: mutationFields,
|
||||
}
|
||||
|
||||
schemaConfig := graphql.SchemaConfig{
|
||||
Query: graphql.NewObject(rootQuery),
|
||||
Mutation: graphql.NewObject(rootMutation),
|
||||
}
|
||||
|
||||
return graphql.NewSchema(schemaConfig)
|
||||
}
|
||||
Reference in New Issue
Block a user