2021-09-24 13:39:23 +00:00
|
|
|
package gql
|
2021-07-26 12:52:36 +00:00
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
|
|
|
"path/filepath"
|
2021-08-06 17:25:07 +00:00
|
|
|
"time"
|
2021-07-26 12:52:36 +00:00
|
|
|
|
|
|
|
"github.com/graph-gophers/dataloader"
|
|
|
|
"github.com/graphql-go/graphql"
|
2021-08-06 17:25:07 +00:00
|
|
|
"github.com/graphql-go/graphql/language/ast"
|
2021-09-24 13:39:23 +00:00
|
|
|
|
|
|
|
helper "git.kapelle.org/niklas/s3browser/internal/helper"
|
|
|
|
types "git.kapelle.org/niklas/s3browser/internal/types"
|
2021-07-26 12:52:36 +00:00
|
|
|
)
|
|
|
|
|
2021-09-14 14:22:32 +00:00
|
|
|
type LoginResult struct {
|
|
|
|
Token string `json:"token"`
|
|
|
|
Successful bool `json:"successful"`
|
|
|
|
}
|
|
|
|
|
2021-07-26 12:52:36 +00:00
|
|
|
var graphqlDirType *graphql.Object
|
|
|
|
var graphqlFileType *graphql.Object
|
2021-09-14 14:22:32 +00:00
|
|
|
var graphqlLoginResultType *graphql.Object
|
2021-07-26 12:52:36 +00:00
|
|
|
|
2021-09-24 13:39:23 +00:00
|
|
|
//GraphqlTypes create all graphql types and stores the in the global variables
|
|
|
|
func GraphqlTypes() {
|
2021-08-06 17:25:07 +00:00
|
|
|
|
|
|
|
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
|
|
|
|
},
|
|
|
|
})
|
|
|
|
|
2021-07-26 12:52:36 +00:00
|
|
|
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) {
|
2021-09-24 13:39:23 +00:00
|
|
|
source, ok := p.Source.(types.Directory)
|
2021-07-26 12:52:36 +00:00
|
|
|
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) {
|
2021-09-24 13:39:23 +00:00
|
|
|
source, ok := p.Source.(types.File)
|
2021-07-26 12:52:36 +00:00
|
|
|
if !ok {
|
|
|
|
return nil, fmt.Errorf("Failed to parse source for resolve")
|
|
|
|
}
|
|
|
|
|
|
|
|
return filepath.Base(source.ID), nil
|
|
|
|
},
|
|
|
|
},
|
|
|
|
"size": &graphql.Field{
|
2021-07-27 19:24:36 +00:00
|
|
|
Type: graphql.NewNonNull(graphql.Int),
|
2021-07-26 12:52:36 +00:00
|
|
|
Resolve: func(p graphql.ResolveParams) (interface{}, error) {
|
|
|
|
file, err := loadFile(p)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
2021-08-06 14:31:07 +00:00
|
|
|
|
2021-07-26 12:52:36 +00:00
|
|
|
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
|
|
|
|
}
|
2021-08-06 14:31:07 +00:00
|
|
|
|
2021-07-26 12:52:36 +00:00
|
|
|
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
|
|
|
|
}
|
2021-08-06 14:31:07 +00:00
|
|
|
|
2021-07-26 12:52:36 +00:00
|
|
|
return file.ETag, nil
|
|
|
|
},
|
|
|
|
},
|
2021-08-06 17:25:07 +00:00
|
|
|
"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
|
|
|
|
},
|
|
|
|
},
|
2021-07-26 12:52:36 +00:00
|
|
|
"parent": &graphql.Field{
|
|
|
|
Type: graphqlDirType,
|
|
|
|
Resolve: func(p graphql.ResolveParams) (interface{}, error) {
|
2021-09-24 13:39:23 +00:00
|
|
|
source, ok := p.Source.(types.File)
|
2021-07-26 12:52:36 +00:00
|
|
|
if !ok {
|
|
|
|
return nil, fmt.Errorf("Failed to parse Source for parent resolve")
|
|
|
|
}
|
|
|
|
|
2021-09-24 13:39:23 +00:00
|
|
|
basename := helper.GetPathFromId(source.ID)
|
2021-07-26 12:52:36 +00:00
|
|
|
|
2021-09-24 13:39:23 +00:00
|
|
|
return types.Directory{
|
2021-07-26 12:52:36 +00:00
|
|
|
ID: basename,
|
|
|
|
}, nil
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
})
|
|
|
|
|
|
|
|
graphqlDirType.AddFieldConfig("files", &graphql.Field{
|
|
|
|
Type: graphql.NewList(graphqlFileType),
|
|
|
|
Resolve: func(p graphql.ResolveParams) (interface{}, error) {
|
2021-09-24 13:39:23 +00:00
|
|
|
source, ok := p.Source.(types.Directory)
|
2021-07-26 12:52:36 +00:00
|
|
|
if !ok {
|
|
|
|
return nil, fmt.Errorf("Failed to parse Source for files resolve")
|
|
|
|
}
|
|
|
|
|
|
|
|
loader := p.Context.Value("loader").(map[string]*dataloader.Loader)
|
|
|
|
|
2021-09-24 13:39:23 +00:00
|
|
|
thunk := loader["getFiles"].Load(p.Context, dataloader.StringKey(helper.NomalizeID(source.ID)))
|
2021-07-26 12:52:36 +00:00
|
|
|
return thunk()
|
|
|
|
},
|
|
|
|
})
|
|
|
|
|
|
|
|
graphqlDirType.AddFieldConfig("directorys", &graphql.Field{
|
|
|
|
Type: graphql.NewList(graphqlDirType),
|
|
|
|
Resolve: func(p graphql.ResolveParams) (interface{}, error) {
|
2021-09-24 13:39:23 +00:00
|
|
|
source, ok := p.Source.(types.Directory)
|
2021-07-26 12:52:36 +00:00
|
|
|
if !ok {
|
2021-08-06 14:31:07 +00:00
|
|
|
return nil, fmt.Errorf("Failed to parse Source for directories resolve")
|
2021-07-26 12:52:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
loader := p.Context.Value("loader").(map[string]*dataloader.Loader)
|
2021-09-24 13:39:23 +00:00
|
|
|
thunk := loader["getDirs"].Load(p.Context, dataloader.StringKey(helper.NomalizeID(source.ID)))
|
2021-07-26 12:52:36 +00:00
|
|
|
|
|
|
|
return thunk()
|
|
|
|
},
|
|
|
|
})
|
|
|
|
|
|
|
|
graphqlDirType.AddFieldConfig("parent", &graphql.Field{
|
|
|
|
Type: graphqlDirType,
|
|
|
|
Resolve: func(p graphql.ResolveParams) (interface{}, error) {
|
2021-09-24 13:39:23 +00:00
|
|
|
source, ok := p.Source.(types.Directory)
|
2021-07-26 12:52:36 +00:00
|
|
|
if !ok {
|
2021-08-06 14:31:07 +00:00
|
|
|
return nil, fmt.Errorf("Failed to parse Source for directories resolve")
|
2021-07-26 12:52:36 +00:00
|
|
|
}
|
|
|
|
|
2021-09-24 13:39:23 +00:00
|
|
|
return types.Directory{
|
|
|
|
ID: helper.GetParentDir(source.ID),
|
2021-07-26 12:52:36 +00:00
|
|
|
}, nil
|
|
|
|
},
|
|
|
|
})
|
2021-09-14 14:22:32 +00:00
|
|
|
|
|
|
|
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",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
})
|
|
|
|
|
2021-07-26 12:52:36 +00:00
|
|
|
}
|
|
|
|
|
2021-09-24 13:39:23 +00:00
|
|
|
//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)
|
2021-07-26 12:52:36 +00:00
|
|
|
if !ok {
|
|
|
|
return nil, fmt.Errorf("Failed to parse source for resolve")
|
|
|
|
}
|
|
|
|
|
|
|
|
loader := p.Context.Value("loader").(map[string]*dataloader.Loader)
|
|
|
|
|
2021-09-24 13:39:23 +00:00
|
|
|
thunk := loader["getFile"].Load(p.Context, dataloader.StringKey(helper.NomalizeID(source.ID)))
|
2021-07-26 12:52:36 +00:00
|
|
|
result, err := thunk()
|
|
|
|
|
2021-08-14 12:13:49 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
2021-09-24 13:39:23 +00:00
|
|
|
file, ok := result.(*types.File)
|
2021-07-26 12:52:36 +00:00
|
|
|
|
|
|
|
if !ok {
|
|
|
|
return nil, fmt.Errorf("Failed to load file")
|
|
|
|
}
|
|
|
|
|
|
|
|
return file, err
|
|
|
|
}
|