api/graph: Enable GraphQL federation

This commit is contained in:
Adnan Maolood 2022-06-29 09:55:29 -04:00 committed by Drew DeVault
parent 90704ff1ee
commit ae02f6feca
6 changed files with 57 additions and 40 deletions

1
.gitignore vendored
View File

@ -15,4 +15,5 @@ overrides/
.pgp
api/api
api/graph/api/generated.go
api/graph/api/federation.go
*_gen.go

View File

@ -8,9 +8,9 @@ exec:
package: api
# Uncomment to enable federation
# federation:
# filename: graph/generated/federation.go
# package: generated
federation:
filename: graph/api/federation.go
package: api
# Where should any generated models go?
model:

View File

@ -0,0 +1,25 @@
package graph
// This file will be automatically regenerated based on the schema, any resolver implementations
// will be copied through when generating and any unknown code will be moved to the end.
import (
"context"
"git.sr.ht/~sircmpwn/meta.sr.ht/api/graph/api"
"git.sr.ht/~sircmpwn/meta.sr.ht/api/graph/model"
"git.sr.ht/~sircmpwn/meta.sr.ht/api/loaders"
)
func (r *entityResolver) FindOAuthClientByUUID(ctx context.Context, uuid string) (*model.OAuthClient, error) {
return loaders.ForContext(ctx).OAuthClientsByUUID.Load(uuid)
}
func (r *entityResolver) FindUserByID(ctx context.Context, id int) (*model.User, error) {
return loaders.ForContext(ctx).UsersByID.Load(id)
}
// Entity returns api.EntityResolver implementation.
func (r *Resolver) Entity() api.EntityResolver { return &entityResolver{r} }
type entityResolver struct{ *Resolver }

View File

@ -23,6 +23,8 @@ type OAuthClient struct {
fields *database.ModelFields
}
func (OAuthClient) IsEntity() {}
func (oc *OAuthClient) As(alias string) *OAuthClient {
oc.alias = alias
return oc

View File

@ -11,36 +11,36 @@ access token, and are not available to clients using OAuth 2.0 access tokens.
directive @private on FIELD_DEFINITION
"""
This used to decorate fields which are for internal use, and are not
This is used to decorate fields which are for internal use, and are not
available to normal API users.
"""
directive @internal on FIELD_DEFINITION
directive @anoninternal on FIELD_DEFINITION
"""
Used to provide a human-friendly description of an access scope.
"""
directive @scopehelp(details: String!) on ENUM_VALUE
enum AccessScope {
AUDIT_LOG @scopehelp(details: "audit log")
BILLING @scopehelp(details: "billing history")
PGP_KEYS @scopehelp(details: "PGP keys")
SSH_KEYS @scopehelp(details: "SSH keys")
PROFILE @scopehelp(details: "profile information")
"Audit log"
AUDIT_LOG
"Billing history"
BILLING
"PGP keys"
PGP_KEYS
"SSH keys"
SSH_KEYS
"Profile information"
PROFILE
}
enum AccessKind {
RO @scopehelp(details: "read")
RW @scopehelp(details: "read and write")
"Read-only"
RO
"Read and write"
RW
}
"""
Decorates fields for which access requires a particular OAuth 2.0 scope with
read or write access. For the meta.sr.ht API, you have access to all public
information without any special permissions - user profile information,
public keys, and so on.
read or write access.
"""
directive @access(scope: AccessScope!, kind: AccessKind!) on FIELD_DEFINITION | ENUM_VALUE
@ -57,17 +57,6 @@ type Version {
deprecationDate: Time
}
interface Entity {
id: Int!
created: Time!
updated: Time!
"""
The canonical name of this entity. For users, this is their username
prefixed with '~'. Additional entity types will be supported in the future.
"""
canonicalName: String!
}
enum UserType {
UNCONFIRMED
ACTIVE_NON_PAYING
@ -78,7 +67,7 @@ enum UserType {
SUSPENDED
}
type User implements Entity {
type User @key(fields: "id") {
id: Int!
created: Time!
updated: Time!
@ -144,7 +133,7 @@ type OAuthGrantRegistration {
secret: String!
}
type OAuthClient {
type OAuthClient @key(fields: "uuid") {
id: Int!
uuid: String!
redirectUrl: String!
@ -153,7 +142,7 @@ type OAuthClient {
description: String
url: String
owner: Entity! @access(scope: PROFILE, kind: RO)
owner: User! @access(scope: PROFILE, kind: RO)
}
type OAuthClientRegistration {
@ -331,7 +320,7 @@ type WebhookSubscriptionCursor {
cursor: Cursor
}
type Query {
extend type Query {
"Returns API version information."
version: Version!
@ -428,7 +417,7 @@ input ProfileWebhookInput {
query: String!
}
type Mutation {
extend type Mutation {
updateUser(input: UserInput): User! @access(scope: PROFILE, kind: RW)
createPGPKey(key: String!): PGPKey! @access(scope: PGP_KEYS, kind: RW)
@ -453,7 +442,7 @@ type Mutation {
may be used to access details of the event which trigged the webhook. The
query may not make any mutations.
"""
createWebhook(config: ProfileWebhookInput!): WebhookSubscription!
createProfileWebhook(config: ProfileWebhookInput!): WebhookSubscription!
"""
Deletes a user profile webhook. Any events already queued may still be
@ -463,7 +452,7 @@ type Mutation {
Manually deleting a webhook configured by a third-party client may cause
unexpected behavior with the third-party integration.
"""
deleteWebhook(id: Int!): WebhookSubscription
deleteProfileWebhook(id: Int!): WebhookSubscription
### ###
### The following resolvers are for internal use. ###

View File

@ -486,7 +486,7 @@ func (r *mutationResolver) UpdateSSHKey(ctx context.Context, id int) (*model.SSH
return &key, nil
}
func (r *mutationResolver) CreateWebhook(ctx context.Context, config model.ProfileWebhookInput) (model.WebhookSubscription, error) {
func (r *mutationResolver) CreateProfileWebhook(ctx context.Context, config model.ProfileWebhookInput) (model.WebhookSubscription, error) {
schema := server.ForContext(ctx).Schema
if err := corewebhooks.Validate(schema, config.Query); err != nil {
return nil, err
@ -563,7 +563,7 @@ func (r *mutationResolver) CreateWebhook(ctx context.Context, config model.Profi
return &sub, nil
}
func (r *mutationResolver) DeleteWebhook(ctx context.Context, id int) (model.WebhookSubscription, error) {
func (r *mutationResolver) DeleteProfileWebhook(ctx context.Context, id int) (model.WebhookSubscription, error) {
var sub model.ProfileWebhookSubscription
filter, err := corewebhooks.FilterWebhooks(ctx)
@ -1167,7 +1167,7 @@ func (r *mutationResolver) SendEmailNotification(ctx context.Context, subject st
return err == nil, err
}
func (r *oAuthClientResolver) Owner(ctx context.Context, obj *model.OAuthClient) (model.Entity, error) {
func (r *oAuthClientResolver) Owner(ctx context.Context, obj *model.OAuthClient) (*model.User, error) {
return loaders.ForContext(ctx).UsersByID.Load(obj.OwnerID)
}