Skip to content

Commit 36f8076

Browse files
authored
Merge pull request #149 from devcordde/events
Implement #9 and some refactoring
2 parents 9e3192e + b882a21 commit 36f8076

30 files changed

+590
-208
lines changed

backend/src/main/java/club/devcord/devmarkt/DevelopmentStartup.java

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,14 +16,11 @@
1616

1717
package club.devcord.devmarkt;
1818

19-
import club.devcord.devmarkt.repositories.TemplateRepo;
20-
import io.micronaut.context.BeanContext;
2119
import io.micronaut.context.annotation.Requires;
2220
import io.micronaut.context.event.ApplicationEventListener;
2321
import io.micronaut.context.event.StartupEvent;
2422
import io.micronaut.json.JsonMapper;
2523
import io.micronaut.security.token.jwt.generator.JwtTokenGenerator;
26-
import jakarta.inject.Inject;
2724
import jakarta.inject.Singleton;
2825
import java.util.Map;
2926
import org.slf4j.Logger;

backend/src/main/java/club/devcord/devmarkt/auth/InvocationDataCustomizer.java

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
package club.devcord.devmarkt.auth;
1818

19+
import club.devcord.devmarkt.ws.SessionMetaData;
1920
import graphql.ExecutionInput;
2021
import io.micronaut.configuration.graphql.GraphQLExecutionInputCustomizer;
2122
import io.micronaut.http.HttpRequest;
@@ -28,17 +29,26 @@
2829
public class InvocationDataCustomizer implements GraphQLExecutionInputCustomizer {
2930

3031
private final UserProvider provider;
32+
private final SessionMetaData sessionMetaData;
3133

32-
public InvocationDataCustomizer(UserProvider provider) {
34+
public InvocationDataCustomizer(UserProvider provider, SessionMetaData sessionMetaData) {
3335
this.provider = provider;
36+
this.sessionMetaData = sessionMetaData;
3437
}
3538

3639
@Override
3740
public Publisher<ExecutionInput> customize(ExecutionInput executionInput, HttpRequest httpRequest,
3841
MutableHttpResponse<String> httpResponse) {
3942
httpRequest.getHeaders().getAuthorization()
4043
.flatMap(provider::validate)
41-
.ifPresent(user -> executionInput.getGraphQLContext().put("user", user));
44+
.ifPresent(user -> {
45+
executionInput.getGraphQLContext().put("user", user);
46+
var session = sessionMetaData.getHttpRequestWebSocketSessionMap().get(httpRequest);
47+
if (session != null) {
48+
sessionMetaData.getUserSessions().put(user.id(), session);
49+
}
50+
});
51+
sessionMetaData.getHttpRequestWebSocketSessionMap().remove(httpRequest);
4252
return Mono.just(executionInput);
4353
}
4454
}

backend/src/main/java/club/devcord/devmarkt/auth/OwnApplicationDirective.java

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818

1919
import club.devcord.devmarkt.auth.error.UnauthorizedError;
2020
import club.devcord.devmarkt.entities.auth.User;
21-
import club.devcord.devmarkt.responses.Failure;
21+
import club.devcord.devmarkt.responses.FailureException;
2222
import club.devcord.devmarkt.responses.failure.application.ErrorCode;
2323
import club.devcord.devmarkt.services.ApplicationService;
2424
import graphql.execution.DataFetcherResult;
@@ -69,11 +69,10 @@ public GraphQLFieldDefinition onField(
6969
}
7070
LOGGER.info("Rejecting request because user {} doesn't own application id: {}",
7171
user.id(), value);
72-
return fieldBooleanReturn
73-
? false
74-
: DataFetcherResult.newResult()
75-
.data(new Failure<>(ErrorCode.NOT_FOUND))
76-
.build();
72+
if (fieldBooleanReturn) {
73+
return false;
74+
}
75+
throw new FailureException(ErrorCode.NOT_FOUND);
7776
};
7877

7978
environment.setFieldDataFetcher(authDataFetcher);

backend/src/main/java/club/devcord/devmarkt/auth/RoleDirective.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ public GraphQLFieldDefinition onField(
5353
}
5454

5555
if (user.role() == expectedRole || user.role() == Role.ADMIN) {
56-
return originalDataFetcher.get(env);
56+
return originalDataFetcher.get(env);
5757
}
5858
LOGGER.info("Rejecting forbidden request for user {}", user.id());
5959
return DataFetcherResult.newResult()

backend/src/main/java/club/devcord/devmarkt/responses/Response.java renamed to backend/src/main/java/club/devcord/devmarkt/entities/application/ApplicationProcessEvent.java

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -14,14 +14,16 @@
1414
* limitations under the License.
1515
*/
1616

17-
package club.devcord.devmarkt.responses;
17+
package club.devcord.devmarkt.entities.application;
1818

19-
public sealed interface Response<T> permits Failure, Success {
19+
import club.devcord.devmarkt.graphql.GraphQLType;
20+
import io.micronaut.core.annotation.Introspected;
2021

21-
default Object graphQlUnion() {
22-
return this instanceof Success<T> success
23-
? success.value()
24-
: this;
25-
}
22+
@Introspected
23+
@GraphQLType("ApplicationProcessEvent")
24+
public record ApplicationProcessEvent(
25+
Integer id,
26+
ApplicationStatus status
27+
) {
2628

2729
}

backend/src/main/java/club/devcord/devmarkt/responses/Success.java renamed to backend/src/main/java/club/devcord/devmarkt/graphql/CustomInstrumentation.java

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -14,14 +14,19 @@
1414
* limitations under the License.
1515
*/
1616

17-
package club.devcord.devmarkt.responses;
17+
package club.devcord.devmarkt.graphql;
1818

19-
public record Success<T>(
20-
T value
21-
) implements Response<T> {
19+
import graphql.execution.instrumentation.SimpleInstrumentation;
20+
import graphql.execution.instrumentation.parameters.InstrumentationFieldFetchParameters;
21+
import graphql.schema.DataFetcher;
22+
import jakarta.inject.Singleton;
2223

23-
public static <T> Response<T> response(T value) {
24-
return new Success<>(value);
25-
}
24+
@Singleton
25+
public class CustomInstrumentation extends SimpleInstrumentation {
2626

27+
@Override
28+
public DataFetcher<?> instrumentDataFetcher(DataFetcher<?> dataFetcher,
29+
InstrumentationFieldFetchParameters parameters) {
30+
return new ProxyDataFetcher<>(dataFetcher);
31+
}
2732
}

backend/src/main/java/club/devcord/devmarkt/graphql/GraphQLFactory.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,8 @@ public GraphQL graphQL(
5454
ResourceResolver resourceResolver,
5555
BeanContext context,
5656
RoleDirective roleDirective,
57-
OwnApplicationDirective ownApplicationDirective) {
57+
OwnApplicationDirective ownApplicationDirective,
58+
CustomInstrumentation customInstrumentation) {
5859
var builder = new SchemaParserBuilder()
5960
.scalars(JavaPrimitives.GraphQLLong, TemplateNameScalar.TEMPLATE_NAME,
6061
ExtendedScalars.NonNegativeInt, ExtendedScalars.PositiveInt, ExtendedScalars.DateTime,
@@ -72,6 +73,7 @@ public GraphQL graphQL(
7273
.makeExecutableSchema();
7374

7475
return GraphQL.newGraphQL(schema)
76+
.instrumentation(customInstrumentation)
7577
.build();
7678
}
7779

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
/*
2+
* Copyright 2022 Contributors to the Devmarkt-Backend project
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package club.devcord.devmarkt.graphql;
18+
19+
import club.devcord.devmarkt.logging.LogMsgGenerator;
20+
import club.devcord.devmarkt.responses.Failure;
21+
import club.devcord.devmarkt.responses.FailureException;
22+
import graphql.execution.DataFetcherResult;
23+
import graphql.schema.DataFetcher;
24+
import graphql.schema.DataFetchingEnvironment;
25+
import graphql.schema.GraphQLObjectType;
26+
import org.slf4j.Logger;
27+
import org.slf4j.LoggerFactory;
28+
29+
public class ProxyDataFetcher<T> implements DataFetcher<Object> {
30+
31+
private static final Logger LOGGER = LoggerFactory.getLogger(ProxyDataFetcher.class);
32+
33+
private final DataFetcher<T> originalDataFetcher;
34+
public ProxyDataFetcher(DataFetcher<T> originalDataFetcher) {
35+
this.originalDataFetcher = originalDataFetcher;
36+
}
37+
38+
@Override
39+
public Object get(DataFetchingEnvironment environment) throws Exception {
40+
var schema = environment.getGraphQLSchema();
41+
Object result;
42+
try {
43+
result = originalDataFetcher.get(environment);
44+
} catch (FailureException exception) {
45+
result = DataFetcherResult.newResult()
46+
.data(new Failure(exception.errors()))
47+
.build();
48+
}
49+
if (environment.getParentType() instanceof GraphQLObjectType type
50+
&& (type == schema.getSubscriptionType()
51+
|| (type == schema.getMutationType())
52+
|| (type == schema.getQueryType()))) {
53+
LOGGER.info(LogMsgGenerator.generateMsg(environment, result));
54+
}
55+
return result;
56+
}
57+
}

backend/src/main/java/club/devcord/devmarkt/graphql/application/ApplicationMutation.java

Lines changed: 7 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,9 @@
1717
package club.devcord.devmarkt.graphql.application;
1818

1919
import club.devcord.devmarkt.entities.application.Answer;
20+
import club.devcord.devmarkt.entities.application.Application;
2021
import club.devcord.devmarkt.entities.application.ApplicationStatus;
2122
import club.devcord.devmarkt.entities.auth.User;
22-
import club.devcord.devmarkt.logging.LoggingUtil;
2323
import club.devcord.devmarkt.services.ApplicationService;
2424
import graphql.kickstart.tools.GraphQLMutationResolver;
2525
import graphql.schema.DataFetchingEnvironment;
@@ -39,33 +39,22 @@ public ApplicationMutation(ApplicationService service) {
3939
this.service = service;
4040
}
4141

42-
public Object createApplication(String templateName, ArrayList<Answer> answers,
42+
public Application createApplication(String templateName, ArrayList<Answer> answers,
4343
DataFetchingEnvironment environment) {
4444
var user = (User) environment.getGraphQlContext().get("user");
45-
var response = service.createApplication(templateName, answers, user);
46-
LOGGER.info("Application creation: User: {}, TemplateName: {}, Successful: {}",
47-
user.id(), templateName, LoggingUtil.responseStatus(response));
48-
return response.graphQlUnion();
45+
return service.createApplication(templateName, answers, user);
4946
}
5047

5148
public boolean deleteApplication(int id) {
52-
var response = service.deleteApplication(id);
53-
LOGGER.info("Application deletion. ID: {}, Successful: {}", id, response);
54-
return response;
49+
return service.deleteApplication(id);
5550
}
5651

57-
public Object updateApplication(int id, ArrayList<Answer> updatedAnswers) {
58-
var response = service.updateApplication(id, updatedAnswers);
59-
LOGGER.info("Application update. ID: {}, AnswerNumbers: {}, Response: {}", id,
60-
updatedAnswers.stream().map(Answer::number).toArray(),
61-
LoggingUtil.responseStatus(response));
62-
return response.graphQlUnion();
52+
public Application updateApplication(int id, ArrayList<Answer> updatedAnswers) {
53+
return service.updateApplication(id, updatedAnswers);
6354
}
6455

6556
public boolean processApplication(int id, ApplicationStatus status) {
66-
var response = service.processApplication(id, status);
67-
LOGGER.info("Application process. ID: {}, Successful: {}, Status: {}", id, response, status);
68-
return response;
57+
return service.processApplication(id, status);
6958
}
7059

7160
}

backend/src/main/java/club/devcord/devmarkt/graphql/application/ApplicationQuery.java

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616

1717
package club.devcord.devmarkt.graphql.application;
1818

19-
import club.devcord.devmarkt.logging.LoggingUtil;
19+
import club.devcord.devmarkt.entities.application.Application;
2020
import club.devcord.devmarkt.services.ApplicationService;
2121
import graphql.kickstart.tools.GraphQLQueryResolver;
2222
import jakarta.inject.Singleton;
@@ -34,10 +34,7 @@ public ApplicationQuery(ApplicationService service) {
3434
this.service = service;
3535
}
3636

37-
public Object application(int id) {
38-
var response = service.application(id);
39-
LOGGER.info("Application fetched with id: {} Successful: {}", id,
40-
LoggingUtil.responseStatus(response));
41-
return response.graphQlUnion();
37+
public Application application(int id) {
38+
return service.application(id);
4239
}
4340
}

0 commit comments

Comments
 (0)