clear-gql was built in TypeScript, using TypeGraphQL and TypeGraphQL-Prisma.
the final product is the result of 3 key components, visualized here:
schema.prisma
is the one singular source of truth for clear-gql's overall data structure and types.
Its contents are used to determine the database model, as well as utilized by TypeGraphQL-Prisma to generate base CRUD resolvers and types.
When updating this, it is important to generate a databse migration
For more information on schema.prisma
, consult the prisma docs
as a base, every model
should contain the following:
model Example {
// Metadata
id String @id @default(cuid())
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
/// @TypeGraphQL.omit(input: ["update", "where", "orderBy"])
metadata Json?
}
These fields are important to maintain consistency and ease of use when developing on top of clear-gql.
clear-gql uses CustomResolvers
to extend (and even replace) the resolvers automatically generated by TypeGraphQL-Prisma
Every model should have its own CustomResolver
dedicated to reading and writing metadata. This resolver should define:
- A
getMetadata
field resolver - A
set(MODEL_NAME)Metadata
mutation These should function identically to existing metadataCustomResolvers
These two components are how Clear handles permissioning.
By default, the resolvers generated by TypeGraphQL Prisma are entirely unrestricted, and able to be queried without any authentication. These enhance maps allow us to add authentication requirements to specific queries and fields.
For example, consider the Event
model - we want anyone to be able to read what events are there, but not modify them.
To accomplish this, Event
's CustomResolversEnhanceMap defines events: []
and event: []
, meaning that no permissions are required to run events
and event
queries.
To make sure that only the right people can update events, the following is declared: updateEvent: [Authorized(AuthRole.ADMIN, AuthRole.MANAGER)]
.
This means that only Admins and Managers are able to run updateEvent
queries.
CustomModelsEnhanceMap works in a nearly identical way, however it restricts which fields of an object (like id
and name
) can be accessed.
Important Note: Enhance maps do not apply to queries and fields added as a CustomResolver - make sure to add the appropriate Authorized
decorator to CustomResolvers!
Make sure you have sufficiently locked down default permissions. The safest option is for the default permission set to be only admins. Make sure to never have any raw create, update, or delete resolvers available unauthenticated.
Be extra careful when dealing with models that will store student PII, as there are extra legal restrictions we have to follow when storing this information.
If something will not expose student PII or sensitive internal information there's no harm in it being public, it can be kind of fun for someone poking around to discover something new/weird.