Skip to content

Latest commit

 

History

History
63 lines (45 loc) · 3.62 KB

ARCHITECTURE.md

File metadata and controls

63 lines (45 loc) · 3.62 KB

Architecture

clear-gql was built in TypeScript, using TypeGraphQL and TypeGraphQL-Prisma.

the final product is the result of 3 key components, visualized here: clear-gql architecture diagram clear-gql architecture diagram

schema.prisma

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

Conventions

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.

CustomResolvers

clear-gql uses CustomResolvers to extend (and even replace) the resolvers automatically generated by TypeGraphQL-Prisma

Conventions

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 metadata CustomResolvers

CustomResolversEnhanceMap and CustomModelsEnhanceMap

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!

Conventions

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.