Implementing a New GraphQL Query or Mutation
When tasked with implementing a new GraphQL query or mutation:
-
Define in GraphQL Schema:
- Add the query/mutation in
queries.graphqlsormutations.graphqls. - Define new types in appropriate
.graphqlsfiles (e.g.,users.graphqlsfor User-related). - Add inputs if needed (e.g.,
UserInput).
- Add the query/mutation in
-
Create/Update DTOs:
- In
web/dto/, createEntityDto.javamatching the GraphQL type. - Create
EntityInput.javaextendingEntityDtofor mutations. - Ensure fields match GraphQL schema.
- In
-
Implement Mapper:
- In
web/, createEntityMapper.javaextendingBaseMapper<Entity, EntityDto, EntityInput>. - Use MapStruct annotations.
- Implement
@AfterMappingto set bidirectional references (e.g., set entity on child objects).
- In
-
Update Controller:
- In
web/EntityController.java, add@QueryMappingor@MutationMappingmethod. - Inject service, mapper, CurrentUserContext.
- Resolve
currentUserId = currentUserContext.getCurrentUserId()in the controller and pass it to the service where needed. - For queries: Call service to get entity, map to DTO.
- For mutations: Map input to entity, call service update/create, map result to DTO.
- Add
@PreAuthorizefor permissions using evaluators.
- In
-
Update Service:
- In
EntityService.java, add methods for business logic. - Accept
currentUserIdas a method parameter — do NOT injectCurrentUserContextinto services. - Use repositories for DB access.
- Handle dependencies on other services (e.g., KeycloakService, SlugService).
- In
-
Update Repository:
- In
domain/EntityRepository.java, extendBaseRepository<Entity>. - Add custom query methods if needed (e.g.,
@Queryfor complex joins). - For permissions, see
MemberRepositoryfor examples of role-based queries. - For workspace subclass fields, always query the subclass:
SELECT w FROM OrgWorkspace w WHERE ....
- In
-
Handle Permissions:
- Use
@PreAuthorize("@axveroRolePermissionEvaluator.hasUserAnyOrgRole(#id, 'OWNER')")for org-level. - For team/workspace, use
hasUserAnyTeamRole,hasUserAnyRoleForTeam(cascading), etc. - Roles: OWNER, ADMIN, MEMBER, etc. (see MemberRole enum).
- Automatic creator membership: Ensure creators are added as OWNER when implementing create methods.
- Role-based result scoping: If a query must return different data depending on whether the caller is a client or staff (e.g.,
applications), checkClientService.findClientIdByUserIdAndWorkspaceId(currentUserId, workspaceId)in the service and filter accordingly. Clients always see only their own data; staff see all.
- Use
-
Update Tests:
- Add integration tests in
test/integration/using HTTP client files. - Ensure Testcontainers for DB/Keycloak.
- Add integration tests in
-
DB Migrations:
- No DB migrations needed currently; using JPA create-update. Once the project is complete, migrate to Liquibase.
-
Validate:
- Run
./mvnw compilefirst - No need to run tests as part of development, but ensure code compiles and passes basic checks.
- Tests are currently not fully implemented, so focus on production code correctness and structure.
- Update schemas if needed.
- Run