Skip to content

Commit

Permalink
refactor: move plugin messages (WebGoat#1968)
Browse files Browse the repository at this point in the history
  • Loading branch information
nbaars authored Dec 3, 2024
1 parent f3c7f45 commit 5fc2e06
Show file tree
Hide file tree
Showing 134 changed files with 757 additions and 693 deletions.
7 changes: 0 additions & 7 deletions src/main/java/org/owasp/webgoat/container/WebGoat.java
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@

import java.io.File;
import org.owasp.webgoat.container.session.LessonSession;
import org.owasp.webgoat.container.users.UserRepository;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.domain.EntityScan;
Expand All @@ -54,12 +53,6 @@
@EntityScan(basePackages = "org.owasp.webgoat.container")
public class WebGoat {

private final UserRepository userRepository;

public WebGoat(UserRepository userRepository) {
this.userRepository = userRepository;
}

@Bean(name = "pluginTargetDirectory")
public File pluginTargetDirectory(@Value("${webgoat.user.directory}") final String webgoatHome) {
return new File(webgoatHome);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,51 +25,4 @@

package org.owasp.webgoat.container.assignments;

import org.owasp.webgoat.container.i18n.PluginMessages;
import org.springframework.beans.factory.annotation.Autowired;

public abstract class AssignmentEndpoint {

// TODO: move this to different bean.
@Autowired private PluginMessages messages;

/**
* Convenience method for create a successful result:
*
* <p>- Assignment is set to solved - Feedback message is set to 'assignment.solved'
*
* <p>Of course you can overwrite these values in a specific lesson
*
* @return a builder for creating a result from a lesson
* @param assignment
*/
protected AttackResult.AttackResultBuilder success(AssignmentEndpoint assignment) {
return AttackResult.builder(messages)
.lessonCompleted(true)
.attemptWasMade()
.feedback("assignment.solved")
.assignment(assignment);
}

/**
* Convenience method for create a failed result:
*
* <p>- Assignment is set to not solved - Feedback message is set to 'assignment.not.solved'
*
* <p>Of course you can overwrite these values in a specific lesson
*
* @return a builder for creating a result from a lesson
* @param assignment
*/
protected AttackResult.AttackResultBuilder failed(AssignmentEndpoint assignment) {
return AttackResult.builder(messages)
.lessonCompleted(false)
.attemptWasMade()
.feedback("assignment.not.solved")
.assignment(assignment);
}

protected AttackResult.AttackResultBuilder informationMessage(AssignmentEndpoint assignment) {
return AttackResult.builder(messages).lessonCompleted(false).assignment(assignment);
}
}
public interface AssignmentEndpoint {}
Original file line number Diff line number Diff line change
Expand Up @@ -30,82 +30,18 @@
import lombok.Getter;
import org.owasp.webgoat.container.i18n.PluginMessages;

@Getter
public class AttackResult {

public static class AttackResultBuilder {
private boolean lessonCompleted;
private String feedback;
private Object[] feedbackArgs;
private String output;
private Object[] outputArgs;
private final String assignment;
private boolean attemptWasMade;

private boolean lessonCompleted;
private PluginMessages messages;
private Object[] feedbackArgs;
private String feedbackResourceBundleKey;
private String output;
private Object[] outputArgs;
private AssignmentEndpoint assignment;
private boolean attemptWasMade = false;

public AttackResultBuilder(PluginMessages messages) {
this.messages = messages;
}

public AttackResultBuilder lessonCompleted(boolean lessonCompleted) {
this.lessonCompleted = lessonCompleted;
this.feedbackResourceBundleKey = "lesson.completed";
return this;
}

public AttackResultBuilder lessonCompleted(boolean lessonCompleted, String resourceBundleKey) {
this.lessonCompleted = lessonCompleted;
this.feedbackResourceBundleKey = resourceBundleKey;
return this;
}

public AttackResultBuilder feedbackArgs(Object... args) {
this.feedbackArgs = args;
return this;
}

public AttackResultBuilder feedback(String resourceBundleKey) {
this.feedbackResourceBundleKey = resourceBundleKey;
return this;
}

public AttackResultBuilder output(String output) {
this.output = output;
return this;
}

public AttackResultBuilder outputArgs(Object... args) {
this.outputArgs = args;
return this;
}

public AttackResultBuilder attemptWasMade() {
this.attemptWasMade = true;
return this;
}

public AttackResult build() {
return new AttackResult(
lessonCompleted,
messages.getMessage(feedbackResourceBundleKey, feedbackArgs),
messages.getMessage(output, output, outputArgs),
assignment.getClass().getSimpleName(),
attemptWasMade);
}

public AttackResultBuilder assignment(AssignmentEndpoint assignment) {
this.assignment = assignment;
return this;
}
}

@Getter private boolean lessonCompleted;
@Getter private String feedback;
@Getter private String output;
@Getter private final String assignment;
@Getter private boolean attemptWasMade;

public AttackResult(
private AttackResult(
boolean lessonCompleted,
String feedback,
String output,
Expand All @@ -118,11 +54,33 @@ public AttackResult(
this.attemptWasMade = attemptWasMade;
}

public static AttackResultBuilder builder(PluginMessages messages) {
return new AttackResultBuilder(messages);
public AttackResult(
boolean lessonCompleted,
String feedback,
Object[] feedbackArgs,
String output,
Object[] outputArgs,
String assignment,
boolean attemptWasMade) {
this.lessonCompleted = lessonCompleted;
this.feedback = feedback;
this.feedbackArgs = feedbackArgs;
this.output = output;
this.outputArgs = outputArgs;
this.assignment = assignment;
this.attemptWasMade = attemptWasMade;
}

public boolean assignmentSolved() {
return lessonCompleted;
}

public AttackResult apply(PluginMessages pluginMessages) {
return new AttackResult(
lessonCompleted,
pluginMessages.getMessage(feedback, feedback, feedbackArgs),
pluginMessages.getMessage(output, output, outputArgs),
assignment,
attemptWasMade);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
package org.owasp.webgoat.container.assignments;

import org.owasp.webgoat.container.i18n.PluginMessages;

public class AttackResultBuilder {

private PluginMessages messages;
private boolean lessonCompleted;
private Object[] feedbackArgs;
private String feedbackResourceBundleKey;
private String output;
private Object[] outputArgs;
private AssignmentEndpoint assignment;
private boolean attemptWasMade = false;
private boolean assignmentCompleted;

public AttackResultBuilder(PluginMessages messages) {
this.messages = messages;
}

public AttackResultBuilder() {}

public AttackResultBuilder lessonCompleted(boolean lessonCompleted) {
this.lessonCompleted = lessonCompleted;
this.feedbackResourceBundleKey = "lesson.completed";
return this;
}

public AttackResultBuilder lessonCompleted(boolean lessonCompleted, String resourceBundleKey) {
this.lessonCompleted = lessonCompleted;
this.feedbackResourceBundleKey = resourceBundleKey;
return this;
}

public AttackResultBuilder assignmentCompleted(boolean assignmentCompleted) {
this.assignmentCompleted = assignmentCompleted;
this.feedbackResourceBundleKey = "assignment.completed";
return this;
}

public AttackResultBuilder assignmentCompleted(
boolean assignmentCompleted, String resourceBundleKey) {
this.assignmentCompleted = assignmentCompleted;
this.feedbackResourceBundleKey = resourceBundleKey;
return this;
}

public AttackResultBuilder feedbackArgs(Object... args) {
this.feedbackArgs = args;
return this;
}

public AttackResultBuilder feedback(String resourceBundleKey) {
this.feedbackResourceBundleKey = resourceBundleKey;
return this;
}

public AttackResultBuilder output(String output) {
this.output = output;
return this;
}

public AttackResultBuilder outputArgs(Object... args) {
this.outputArgs = args;
return this;
}

public AttackResultBuilder attemptWasMade() {
this.attemptWasMade = true;
return this;
}

public AttackResult build() {
return new AttackResult(
lessonCompleted,
feedbackResourceBundleKey,
feedbackArgs,
output,
outputArgs,
assignment.getClass().getSimpleName(),
attemptWasMade);
}

public AttackResultBuilder assignment(AssignmentEndpoint assignment) {
this.assignment = assignment;
return this;
}

/**
* Convenience method for create a successful result:
*
* <p>- Assignment is set to solved - Feedback message is set to 'assignment.solved'
*
* <p>Of course you can overwrite these values in a specific lesson
*
* @return a builder for creating a result from a lesson
* @param assignment
*/
public static AttackResultBuilder success(AssignmentEndpoint assignment) {
return new AttackResultBuilder()
.lessonCompleted(true)
.assignmentCompleted(true)
.attemptWasMade()
.feedback("assignment.solved")
.assignment(assignment);
}

/**
* Convenience method for create a failed result:
*
* <p>- Assignment is set to not solved - Feedback message is set to 'assignment.not.solved'
*
* <p>Of course you can overwrite these values in a specific lesson
*
* @return a builder for creating a result from a lesson
* @param assignment
*/
public static AttackResultBuilder failed(AssignmentEndpoint assignment) {
return new AttackResultBuilder()
.lessonCompleted(false)
.assignmentCompleted(true)
.attemptWasMade()
.feedback("assignment.not.solved")
.assignment(assignment);
}

public static AttackResultBuilder informationMessage(AssignmentEndpoint assignment) {
return new AttackResultBuilder().lessonCompleted(false).assignment(assignment);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package org.owasp.webgoat.container.assignments;

import org.owasp.webgoat.container.i18n.PluginMessages;
import org.springframework.core.MethodParameter;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;

/** This class intercepts the response body and applies the plugin messages to the attack result. */
@RestControllerAdvice
public class AttackResultMessageResponseBodyAdvice implements ResponseBodyAdvice<Object> {

private final PluginMessages pluginMessages;

public AttackResultMessageResponseBodyAdvice(PluginMessages pluginMessages) {
this.pluginMessages = pluginMessages;
}

@Override
public boolean supports(
MethodParameter returnType, Class<? extends HttpMessageConverter<?>> converterType) {
return true;
}

@Override
public Object beforeBodyWrite(
Object body,
MethodParameter returnType,
MediaType selectedContentType,
Class<? extends HttpMessageConverter<?>> selectedConverterType,
ServerHttpRequest request,
ServerHttpResponse response) {
if (body instanceof AttackResult a) {
return a.apply(pluginMessages);
}
return body;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@

package org.owasp.webgoat.lessons.authbypass;

import static org.owasp.webgoat.container.assignments.AttackResultBuilder.failed;
import static org.owasp.webgoat.container.assignments.AttackResultBuilder.success;

import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import java.io.IOException;
Expand All @@ -46,7 +49,7 @@
"auth-bypass.hints.verify.3",
"auth-bypass.hints.verify.4"
})
public class VerifyAccount extends AssignmentEndpoint {
public class VerifyAccount implements AssignmentEndpoint {

private final LessonSession userSessionData;

Expand Down
Loading

0 comments on commit 5fc2e06

Please sign in to comment.