getHints();
diff --git a/webgoat-container/src/main/java/org/owasp/webgoat/lessons/Assignment.java b/webgoat-container/src/main/java/org/owasp/webgoat/lessons/Assignment.java
new file mode 100644
index 000000000..0ee355f67
--- /dev/null
+++ b/webgoat-container/src/main/java/org/owasp/webgoat/lessons/Assignment.java
@@ -0,0 +1,59 @@
+/**
+ * ************************************************************************************************
+ * This file is part of WebGoat, an Open Web Application Security Project utility. For details,
+ * please see http://www.owasp.org/
+ *
+ * Copyright (c) 2002 - 20014 Bruce Mayhew
+ *
+ * This program is free software; you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
+ * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program; if
+ * not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ *
+ * Getting Source ==============
+ *
+ * Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software
+ * projects.
+ *
+ */
+package org.owasp.webgoat.lessons;
+
+import org.owasp.webgoat.lessons.model.AttackResult;
+import org.owasp.webgoat.session.UserTracker;
+import org.owasp.webgoat.session.WebSession;
+import org.springframework.beans.factory.annotation.Autowired;
+
+/**
+ * Each lesson can define an endpoint which can support the lesson. So for example if you create a lesson which uses JavaScript and
+ * needs to call out to the server to fetch data you can define an endpoint in that lesson. WebGoat will pick up this endpoint and
+ * Spring will publish it.
+ *
+ * Extend this class and implement the met
+ *
+ * Note: each subclass should declare this annotation otherwise the WebGoat framework cannot find your endpoint.
+ */
+public abstract class Assignment extends Endpoint {
+
+ @Autowired
+ private UserTracker userTracker;
+ @Autowired
+ private WebSession webSession;
+
+ //// TODO: 11/13/2016 events better fit?
+ protected AttackResult trackProgress(AttackResult attackResult) {
+ if (attackResult.assignmentSolved()) {
+ userTracker.assignmentSolved(webSession.getCurrentLesson(), this);
+ } else {
+ userTracker.assignmentFailed(webSession.getCurrentLesson());
+ }
+ return attackResult;
+ }
+
+}
diff --git a/webgoat-container/src/main/java/org/owasp/webgoat/lessons/AssignmentEndpoint.java b/webgoat-container/src/main/java/org/owasp/webgoat/lessons/Endpoint.java
similarity index 60%
rename from webgoat-container/src/main/java/org/owasp/webgoat/lessons/AssignmentEndpoint.java
rename to webgoat-container/src/main/java/org/owasp/webgoat/lessons/Endpoint.java
index 1a7e3aee2..18e33f4ef 100644
--- a/webgoat-container/src/main/java/org/owasp/webgoat/lessons/AssignmentEndpoint.java
+++ b/webgoat-container/src/main/java/org/owasp/webgoat/lessons/Endpoint.java
@@ -1,3 +1,11 @@
+package org.owasp.webgoat.lessons;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.boot.actuate.endpoint.mvc.MvcEndpoint;
+
+import java.io.File;
+
/**
* ************************************************************************************************
* This file is part of WebGoat, an Open Web Application Security Project utility. For details,
@@ -22,36 +30,16 @@
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software
* projects.
*
+ *
+ * @author nbaars
+ * @version $Id: $Id
+ * @since November 13, 2016
*/
-package org.owasp.webgoat.lessons;
-
-import org.owasp.webgoat.lessons.model.AttackResult;
-import org.owasp.webgoat.session.LessonTracker;
-import org.owasp.webgoat.session.UserTracker;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.beans.factory.annotation.Qualifier;
-import org.springframework.boot.actuate.endpoint.Endpoint;
-import org.springframework.boot.actuate.endpoint.mvc.MvcEndpoint;
-
-import java.io.File;
-
-/**
- * Each lesson can define an endpoint which can support the lesson. So for example if you create a lesson which uses JavaScript and
- * needs to call out to the server to fetch data you can define an endpoint in that lesson. WebGoat will pick up this endpoint and
- * Spring will publish it.
- *
- * Extend this class and implement the met
- *
- * Note: each subclass should declare this annotation otherwise the WebGoat framework cannot find your endpoint.
- */
-@LessonEndpointMapping
-public abstract class AssignmentEndpoint implements MvcEndpoint {
+public abstract class Endpoint implements MvcEndpoint {
@Autowired
@Qualifier("pluginTargetDirectory")
private File pluginDirectory;
- @Autowired
- private UserTracker userTracker;
/**
* The directory of the plugin directory in which the lessons resides, so if you want to access the lesson 'ClientSideFiltering' you will
@@ -69,23 +57,6 @@ public abstract class AssignmentEndpoint implements MvcEndpoint {
return new File(this.pluginDirectory, "plugin");
}
- /**
- * Get the lesson tracker which is based on the current user and do the
- * @return
- */
- protected LessonTracker getLessonTracker() {
- LessonTracker lessonTracker = userTracker.getCurrentLessonTracker();
- return lessonTracker;
- }
-
- protected AttackResult trackProgress(AttackResult attackResult) {
- //// TODO: 11/5/2016 improve
- if (attackResult.isLessonCompleted()) {
- getLessonTracker().incrementNumVisits();
- }
- getLessonTracker().setCompleted(attackResult.isLessonCompleted());
- return attackResult;
- }
@Override
public final boolean isSensitive() {
@@ -93,8 +64,7 @@ public abstract class AssignmentEndpoint implements MvcEndpoint {
}
@Override
- public final Class extends Endpoint> getEndpointType() {
+ public final Class extends org.springframework.boot.actuate.endpoint.Endpoint> getEndpointType() {
return null;
}
-
}
diff --git a/webgoat-container/src/main/java/org/owasp/webgoat/lessons/LessonAdapter.java b/webgoat-container/src/main/java/org/owasp/webgoat/lessons/LessonAdapter.java
index 2825ef6e7..70d0fdf52 100644
--- a/webgoat-container/src/main/java/org/owasp/webgoat/lessons/LessonAdapter.java
+++ b/webgoat-container/src/main/java/org/owasp/webgoat/lessons/LessonAdapter.java
@@ -30,6 +30,7 @@
*/
package org.owasp.webgoat.lessons;
+//// TODO: 11/8/2016 remove
public abstract class LessonAdapter extends AbstractLesson {
diff --git a/webgoat-container/src/main/java/org/owasp/webgoat/lessons/LessonEndpointMapping.java b/webgoat-container/src/main/java/org/owasp/webgoat/lessons/LessonEndpointMapping.java
deleted file mode 100644
index 94bc84c2c..000000000
--- a/webgoat-container/src/main/java/org/owasp/webgoat/lessons/LessonEndpointMapping.java
+++ /dev/null
@@ -1,49 +0,0 @@
-
-/**
- *************************************************************************************************
- * This file is part of WebGoat, an Open Web Application Security Project utility. For details,
- * please see http://www.owasp.org/
- *
- * Copyright (c) 2002 - 20014 Bruce Mayhew
- *
- * This program is free software; you can redistribute it and/or modify it under the terms of the
- * GNU General Public License as published by the Free Software Foundation; either version 2 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
- * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with this program; if
- * not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
- * 02111-1307, USA.
- *
- * Getting Source ==============
- *
- * Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software
- * projects.
- *
- *
- * @author WebGoat
- * @since December 12, 2015
- * @version $Id: $Id
- */
-package org.owasp.webgoat.lessons;
-
-import org.springframework.stereotype.Component;
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-/**
- * Annotation as a marker annotation. During the startup we scan the plugins for classes which use this annotation.
- * @see AssignmentEndpoint for more information.
- */
-@Component
-@Target(ElementType.TYPE)
-@Retention(RetentionPolicy.RUNTIME)
-public @interface LessonEndpointMapping { }
-
-
diff --git a/webgoat-container/src/main/java/org/owasp/webgoat/lessons/NewLesson.java b/webgoat-container/src/main/java/org/owasp/webgoat/lessons/NewLesson.java
index 074391ba6..c0a10e9d4 100644
--- a/webgoat-container/src/main/java/org/owasp/webgoat/lessons/NewLesson.java
+++ b/webgoat-container/src/main/java/org/owasp/webgoat/lessons/NewLesson.java
@@ -1,9 +1,5 @@
package org.owasp.webgoat.lessons;
-import lombok.Getter;
-import lombok.Setter;
-import org.owasp.webgoat.session.WebSession;
-
import java.util.List;
/**
@@ -37,9 +33,7 @@ import java.util.List;
*/
public abstract class NewLesson extends LessonAdapter {
- @Setter
- @Getter
- private int totalNumberOfAssignments = 0;
+
@Override
public abstract Category getDefaultCategory();
@@ -55,10 +49,4 @@ public abstract class NewLesson extends LessonAdapter {
@Override
public abstract String getId();
- public final List getHints(WebSession w) {
- throw new IllegalStateException("Do not use");
- }
-
-
-
}
diff --git a/webgoat-container/src/main/java/org/owasp/webgoat/lessons/model/AttackResult.java b/webgoat-container/src/main/java/org/owasp/webgoat/lessons/model/AttackResult.java
index 95af8dacf..d90bf8258 100644
--- a/webgoat-container/src/main/java/org/owasp/webgoat/lessons/model/AttackResult.java
+++ b/webgoat-container/src/main/java/org/owasp/webgoat/lessons/model/AttackResult.java
@@ -1,5 +1,7 @@
package org.owasp.webgoat.lessons.model;
+import lombok.Getter;
+
/**
* ************************************************************************************************
* This file is part of WebGoat, an Open Web Application Security Project utility. For details,
@@ -29,6 +31,7 @@ package org.owasp.webgoat.lessons.model;
* @version $Id: $Id
* @since August 13, 2016
*/
+@Getter
public class AttackResult {
private boolean lessonCompleted;
@@ -54,15 +57,7 @@ public class AttackResult {
return attackResult;
}
- public boolean isLessonCompleted() {
+ public boolean assignmentSolved() {
return lessonCompleted;
}
-
- public String getFeedback() {
- return feedback;
- }
-
- public String getOutput() {
- return output;
- }
}
diff --git a/webgoat-container/src/main/java/org/owasp/webgoat/lessons/model/LessonInfoModel.java b/webgoat-container/src/main/java/org/owasp/webgoat/lessons/model/LessonInfoModel.java
index ad661ab59..427a7f57c 100644
--- a/webgoat-container/src/main/java/org/owasp/webgoat/lessons/model/LessonInfoModel.java
+++ b/webgoat-container/src/main/java/org/owasp/webgoat/lessons/model/LessonInfoModel.java
@@ -1,5 +1,6 @@
package org.owasp.webgoat.lessons.model;
+import lombok.Getter;
import org.owasp.webgoat.lessons.AbstractLesson;
import org.owasp.webgoat.session.WebSession;
@@ -10,6 +11,7 @@ import org.owasp.webgoat.session.WebSession;
* @version $Id: $Id
*/
//// TODO: 11/5/2016 this can be removed???
+@Getter
public class LessonInfoModel {
private String lessonTitle;
diff --git a/webgoat-container/src/main/java/org/owasp/webgoat/plugins/Plugin.java b/webgoat-container/src/main/java/org/owasp/webgoat/plugins/Plugin.java
index b34a1b351..dac0619be 100644
--- a/webgoat-container/src/main/java/org/owasp/webgoat/plugins/Plugin.java
+++ b/webgoat-container/src/main/java/org/owasp/webgoat/plugins/Plugin.java
@@ -3,18 +3,16 @@ package org.owasp.webgoat.plugins;
import com.google.common.base.Optional;
import com.google.common.collect.Lists;
import org.owasp.webgoat.lessons.AbstractLesson;
-import org.owasp.webgoat.lessons.AssignmentEndpoint;
+import org.owasp.webgoat.lessons.Assignment;
+import org.owasp.webgoat.lessons.Endpoint;
import org.owasp.webgoat.lessons.NewLesson;
import org.springframework.util.StringUtils;
import java.io.File;
import java.nio.file.Path;
-import java.util.HashMap;
import java.util.List;
-import java.util.Map;
import static org.owasp.webgoat.plugins.PluginFileUtils.fileEndsWith;
-import static org.owasp.webgoat.plugins.PluginFileUtils.hasParentDirectoryWithName;
/**
* Plugin class.
@@ -24,23 +22,22 @@ import static org.owasp.webgoat.plugins.PluginFileUtils.hasParentDirectoryWithNa
*/
public class Plugin {
- private static final String NAME_LESSON_SOLUTION_DIRECTORY = "lessonSolutions";
- private static final String NAME_LESSON_PLANS_DIRECTORY = "lessonPlans";
-
private PluginClassLoader classLoader;
private Class newLesson;
- private List> lessonEndpoints = Lists.newArrayList();
- private Map solutionLanguageFiles = new HashMap<>();
- private Map lessonPlansLanguageFiles = new HashMap<>();
+ private List> assignments = Lists.newArrayList();
+ private List> endpoints = Lists.newArrayList();
private List pluginFiles = Lists.newArrayList();
- private File lessonSourceFile;
public Plugin(PluginClassLoader classLoader) {
this.classLoader = classLoader;
}
- public List> getLessonEndpoints() {
- return this.lessonEndpoints;
+ public List> getAssignments() {
+ return this.assignments;
+ }
+
+ public List> getEndpoints() {
+ return this.endpoints;
}
/**
@@ -74,8 +71,10 @@ public class Plugin {
try {
Class clazz = classLoader.loadClass(realClassName);
- if (AssignmentEndpoint.class.isAssignableFrom(clazz)) {
- this.lessonEndpoints.add(clazz);
+ if (Assignment.class.isAssignableFrom(clazz)) {
+ this.assignments.add(clazz);
+ } else if (Endpoint.class.isAssignableFrom(clazz)) {
+ this.endpoints.add(clazz);
}
} catch (ClassNotFoundException ce) {
throw new PluginLoadingFailure("Class " + realClassName + " listed in jar but unable to load the class.", ce);
@@ -89,16 +88,6 @@ public class Plugin {
* @param file a {@link java.nio.file.Path} object.
*/
public void loadFiles(Path file) {
- if (fileEndsWith(file, ".html") && hasParentDirectoryWithName(file, NAME_LESSON_SOLUTION_DIRECTORY)) {
- solutionLanguageFiles.put(file.getParent().getFileName().toString(), file.toFile());
- }
- if (fileEndsWith(file, ".html") && hasParentDirectoryWithName(file, NAME_LESSON_PLANS_DIRECTORY)) {
- lessonPlansLanguageFiles.put(file.getParent().getFileName().toString(), file.toFile());
- }
- if (fileEndsWith(file, ".java")) {
- lessonSourceFile = file.toFile();
- }
-
if (fileEndsWith(file, ".css", ".jsp", ".js")) {
pluginFiles.add(file.toFile());
}
@@ -106,13 +95,14 @@ public class Plugin {
/**
* Lesson is optional, it is also possible that the supplied jar contains only helper classes.
- * Lesson could be a new lesson (adoc based) or still ECS based.
*
* @return a {@link com.google.common.base.Optional} object.
*/
public Optional getLesson() {
try {
if (newLesson != null) {
+ AbstractLesson lesson = newLesson.newInstance();
+ lesson.setAssignments(this.assignments);
return Optional.of(newLesson.newInstance());
}
} catch (IllegalAccessException | InstantiationException e) {
@@ -121,42 +111,5 @@ public class Plugin {
return Optional.absent();
}
- /**
- * getLessonSolution.
- *
- * @param language a {@link java.lang.String} object.
- * @return a {@link com.google.common.base.Optional} object.
- */
- public Optional getLessonSolution(String language) {
- return Optional.fromNullable(this.solutionLanguageFiles.get(language));
- }
-
- /**
- * getLessonSolutions.
- *
- * @return a {@link java.util.Map} object.
- */
- public Map getLessonSolutions() {
- return this.solutionLanguageFiles;
- }
-
- /**
- * getLessonSource.
- *
- * @return a {@link com.google.common.base.Optional} object.
- */
- public Optional getLessonSource() {
- return Optional.fromNullable(lessonSourceFile);
- }
-
- /**
- * getLessonPlans.
- *
- * @return a {@link java.util.Map} object.
- */
- public Map getLessonPlans() {
- return this.lessonPlansLanguageFiles;
- }
-
}
diff --git a/webgoat-container/src/main/java/org/owasp/webgoat/plugins/PluginEndpointPublisher.java b/webgoat-container/src/main/java/org/owasp/webgoat/plugins/PluginEndpointPublisher.java
index 98c97b795..9c8654669 100644
--- a/webgoat-container/src/main/java/org/owasp/webgoat/plugins/PluginEndpointPublisher.java
+++ b/webgoat-container/src/main/java/org/owasp/webgoat/plugins/PluginEndpointPublisher.java
@@ -5,6 +5,7 @@ import org.springframework.beans.factory.annotation.Autowire;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.beans.factory.support.RootBeanDefinition;
+import org.springframework.boot.actuate.endpoint.mvc.MvcEndpoint;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.stereotype.Component;
@@ -49,14 +50,17 @@ public class PluginEndpointPublisher {
}
public void publish(Plugin plugin) {
- plugin.getLessonEndpoints().forEach(e -> {
- try {
- BeanDefinition beanDefinition = new RootBeanDefinition(e, Autowire.BY_TYPE.value(), true);
- DefaultListableBeanFactory beanFactory = (DefaultListableBeanFactory) applicationContext.getBeanFactory();
- beanFactory.registerBeanDefinition(beanDefinition.getBeanClassName(), beanDefinition);
- } catch (Exception ex) {
- log.error("Failed to register " + e.getSimpleName() + " as endpoint with Spring, skipping...");
- }
- });
+ plugin.getAssignments().forEach(e -> publishEndpoint(e));
+ plugin.getEndpoints().forEach(e -> publishEndpoint(e));
+ }
+
+ private void publishEndpoint(Class extends MvcEndpoint> e) {
+ try {
+ BeanDefinition beanDefinition = new RootBeanDefinition(e, Autowire.BY_TYPE.value(), true);
+ DefaultListableBeanFactory beanFactory = (DefaultListableBeanFactory) applicationContext.getBeanFactory();
+ beanFactory.registerBeanDefinition(beanDefinition.getBeanClassName(), beanDefinition);
+ } catch (Exception ex) {
+ log.error("Failed to register " + e.getSimpleName() + " as endpoint with Spring, skipping...");
+ }
}
}
diff --git a/webgoat-container/src/main/java/org/owasp/webgoat/service/LessonMenuService.java b/webgoat-container/src/main/java/org/owasp/webgoat/service/LessonMenuService.java
index 3b0cef530..a8c3aca7f 100644
--- a/webgoat-container/src/main/java/org/owasp/webgoat/service/LessonMenuService.java
+++ b/webgoat-container/src/main/java/org/owasp/webgoat/service/LessonMenuService.java
@@ -43,7 +43,6 @@ import org.springframework.web.bind.annotation.ResponseBody;
import java.util.ArrayList;
import java.util.List;
-import java.util.Optional;
/**
* LessonMenuService class.
@@ -56,7 +55,7 @@ import java.util.Optional;
public class LessonMenuService {
private final Course course;
- private final UserTracker userTracker;
+ private UserTracker userTracker;
private final WebSession webSession;
/**
@@ -82,8 +81,8 @@ public class LessonMenuService {
lessonItem.setName(lesson.getTitle());
lessonItem.setLink(lesson.getLink());
lessonItem.setType(LessonMenuItemType.LESSON);
- Optional lessonTracker = userTracker.getLessonTracker(lesson);
- lessonItem.setComplete(lessonTracker.isPresent() ? lessonTracker.get().getCompleted() : false);
+ LessonTracker lessonTracker = userTracker.getLessonTracker(lesson);
+ lessonItem.setComplete(lessonTracker.isLessonSolved());
categoryItem.addChild(lessonItem);
}
menu.add(categoryItem);
diff --git a/webgoat-container/src/main/java/org/owasp/webgoat/service/LessonProgressService.java b/webgoat-container/src/main/java/org/owasp/webgoat/service/LessonProgressService.java
index a9bdeb343..aeb4375f2 100644
--- a/webgoat-container/src/main/java/org/owasp/webgoat/service/LessonProgressService.java
+++ b/webgoat-container/src/main/java/org/owasp/webgoat/service/LessonProgressService.java
@@ -6,6 +6,7 @@ import org.owasp.webgoat.i18n.LabelManager;
import org.owasp.webgoat.lessons.model.LessonInfoModel;
import org.owasp.webgoat.session.LessonTracker;
import org.owasp.webgoat.session.UserTracker;
+import org.owasp.webgoat.session.WebSession;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
@@ -24,6 +25,7 @@ public class LessonProgressService {
private LabelManager labelManager;
private UserTracker userTracker;
+ private WebSession webSession;
/**
* LessonProgressService.
@@ -33,10 +35,14 @@ public class LessonProgressService {
@RequestMapping(value = "/service/lessonprogress.mvc", produces = "application/json")
@ResponseBody
public Map getLessonInfo() {
- LessonTracker lessonTracker = userTracker.getCurrentLessonTracker();
- boolean lessonCompleted = lessonTracker.getCompleted();
- String successMessage = labelManager.get("LessonCompleted");
+ LessonTracker lessonTracker = userTracker.getLessonTracker(webSession.getCurrentLesson());
Map json = Maps.newHashMap();
+ String successMessage = "";
+ boolean lessonCompleted = false;
+ if (lessonTracker != null) {
+ lessonCompleted = lessonTracker.isLessonSolved();
+ successMessage = labelManager.get("LessonCompleted");
+ }
json.put("lessonCompleted", lessonCompleted);
json.put("successMessage", successMessage);
return json;
diff --git a/webgoat-container/src/main/java/org/owasp/webgoat/service/RestartLessonService.java b/webgoat-container/src/main/java/org/owasp/webgoat/service/RestartLessonService.java
index 80d05cbe3..0d3a73adc 100644
--- a/webgoat-container/src/main/java/org/owasp/webgoat/service/RestartLessonService.java
+++ b/webgoat-container/src/main/java/org/owasp/webgoat/service/RestartLessonService.java
@@ -55,7 +55,7 @@ public class RestartLessonService {
String restartLesson() {
AbstractLesson al = webSession.getCurrentLesson();
System.out.println("Restarting lesson: " + al);
- userTracker.getCurrentLessonTracker().setCompleted(false);
+ userTracker.getLessonTracker(al).reset();
return webSession.getCurrentLesson().getLink();
}
diff --git a/webgoat-container/src/main/java/org/owasp/webgoat/session/Course.java b/webgoat-container/src/main/java/org/owasp/webgoat/session/Course.java
index 34be4f847..d2272bfe0 100644
--- a/webgoat-container/src/main/java/org/owasp/webgoat/session/Course.java
+++ b/webgoat-container/src/main/java/org/owasp/webgoat/session/Course.java
@@ -96,7 +96,7 @@ public class Course {
for (Plugin plugin : plugins) {
try {
NewLesson lesson = (NewLesson) plugin.getLesson().get();
- lesson.setTotalNumberOfAssignments(plugin.getLessonEndpoints().size());
+ lesson.setAssignments(plugin.getAssignments());
lessons.add(lesson);
} catch (Exception e) {
log.error("Error in loadLessons: ", e);
diff --git a/webgoat-container/src/main/java/org/owasp/webgoat/session/LessonTracker.java b/webgoat-container/src/main/java/org/owasp/webgoat/session/LessonTracker.java
index 9b7b0371e..d8d36f390 100644
--- a/webgoat-container/src/main/java/org/owasp/webgoat/session/LessonTracker.java
+++ b/webgoat-container/src/main/java/org/owasp/webgoat/session/LessonTracker.java
@@ -1,13 +1,13 @@
package org.owasp.webgoat.session;
-import lombok.extern.slf4j.Slf4j;
+import com.google.common.collect.Sets;
+import org.owasp.webgoat.lessons.AbstractLesson;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.util.Properties;
+import java.io.Serializable;
+import java.util.List;
+import java.util.Set;
+import java.util.stream.Collectors;
/**
@@ -40,290 +40,43 @@ import java.util.Properties;
* @version $Id: $Id
* @since October 29, 2003
*/
-@Slf4j
-public class LessonTracker {
+public class LessonTracker implements Serializable {
+ private static final long serialVersionUID = 5410058267505412928L;
+ private final List assignments;
+ private final Set solvedAssignments = Sets.newHashSet();
+ private int numberOfAttempts = 0;
- private boolean completed = false;
-
- private int maxHintLevel = 0;
-
- private int numVisits = 0;
-
- private boolean viewedCookies = false;
-
- private boolean viewedHtml = false;
-
- private boolean viewedLessonPlan = false;
-
- private boolean viewedParameters = false;
-
- private boolean viewedSource = false;
-
- private boolean viewedSolution = false;
-
- Properties lessonProperties = new Properties();
-
- private int totalNumberOfAssignments = 0;
-
- public void setTotalNumberOfAssignments(int totalNumberOfAssignments) {
- this.totalNumberOfAssignments = totalNumberOfAssignments;
+ public LessonTracker(AbstractLesson lesson) {
+ this.assignments = lesson.getAssignments().stream().map(a -> a.getSimpleName()).collect(Collectors.toList());
}
/**
- * Gets the completed attribute of the LessonTracker object
+ * Mark an assingment as solved
*
- * @return The completed value
+ * @param solvedAssignment the assignment which the user solved
*/
- public boolean getCompleted() {
- return completed;
+ public void assignmentSolved(String solvedAssignment) {
+ solvedAssignments.add(solvedAssignment);
}
/**
- * Gets the maxHintLevel attribute of the LessonTracker object
- *
- * @return The maxHintLevel value
+ * @return did they user solved all assignments for the lesson?
*/
- public int getMaxHintLevel() {
- return maxHintLevel;
+ public boolean isLessonSolved() {
+ return solvedAssignments.size() == assignments.size();
}
/**
- * Gets the numVisits attribute of the LessonTracker object
- *
- * @return The numVisits value
+ * Increase the number attempts to solve the lesson
*/
- public int getNumVisits() {
- return numVisits;
+ public void incrementAttempts() {
+ numberOfAttempts++;
}
/**
- * Gets the viewedCookies attribute of the LessonTracker object
- *
- * @return The viewedCookies value
+ * Reset the tracker. We do not reset the number of attempts here!
*/
- public boolean getViewedCookies() {
- return viewedCookies;
- }
-
- /**
- * Gets the viewedHtml attribute of the LessonTracker object
- *
- * @return The viewedHtml value
- */
- public boolean getViewedHtml() {
- return viewedHtml;
- }
-
- /**
- * Gets the viewedLessonPlan attribute of the LessonTracker object
- *
- * @return The viewedLessonPlan value
- */
- public boolean getViewedLessonPlan() {
- return viewedLessonPlan;
- }
-
- /**
- * Gets the viewedParameters attribute of the LessonTracker object
- *
- * @return The viewedParameters value
- */
- public boolean getViewedParameters() {
- return viewedParameters;
- }
-
- /**
- * Gets the viewedSource attribute of the LessonTracker object
- *
- * @return The viewedSource value
- */
- public boolean getViewedSource() {
- return viewedSource;
- }
-
- /**
- * Getter for the field viewedSolution
.
- *
- * @return a boolean.
- */
- public boolean getViewedSolution() {
- return viewedSource;
- }
-
- /**
- * Description of the Method
- */
- public void incrementNumVisits() {
- numVisits++;
- }
-
-
- /**
- * Sets the properties attribute of the LessonTracker object
- *
- * @param props The new properties value
- * @param screen a {@link org.owasp.webgoat.session.Screen} object.
- */
- protected void setProperties(Properties props, Screen screen) {
- completed = Boolean.valueOf(props.getProperty(screen.getTitle() + ".completed")).booleanValue();
- maxHintLevel = Integer.parseInt(props.getProperty(screen.getTitle() + ".maxHintLevel", "0"));
- numVisits = Integer.parseInt(props.getProperty(screen.getTitle() + ".numVisits", "0"));
- viewedCookies = Boolean.valueOf(props.getProperty(screen.getTitle() + ".viewedCookies", "false")).booleanValue();
- viewedHtml = Boolean.valueOf(props.getProperty(screen.getTitle() + ".viewedHtml", "false")).booleanValue();
- viewedLessonPlan = Boolean.valueOf(props.getProperty(screen.getTitle() + ".viewedLessonPlan", "false")).booleanValue();
- viewedParameters = Boolean.valueOf(props.getProperty(screen.getTitle() + ".viewedParameters", "false")).booleanValue();
- viewedSource = Boolean.valueOf(props.getProperty(screen.getTitle() + ".viewedSource", "false")).booleanValue();
- totalNumberOfAssignments = Integer.parseInt(props.getProperty(screen.getTitle() + ".totalNumberOfAssignments", "0"));
- }
-
- /**
- * getUserDir.
- *
- * @param s a {@link org.owasp.webgoat.session.WebSession} object.
- * @return a {@link java.lang.String} object.
- */
- public static String getUserDir(WebSession s) {
- return "";
- }
-
- private static String getTrackerFile(WebSession s, String user, Screen screen) {
- return getUserDir(s) + user + "." + screen.getClass().getName() + ".props";
- }
-
- /**
- * Description of the Method
- *
- * @param screen Description of the Parameter
- * @param screen Description of the Parameter
- * @param screen Description of the Parameter
- * @param screen Description of the Parameter
- * @param screen Description of the Parameter
- * @param screen Description of the Parameter
- * @param s Description of the Parameter
- * @param user a {@link java.lang.String} object.
- * @return Description of the Return Value
- */
- public static LessonTracker load(WebSession s, String user, Screen screen) {
- FileInputStream in = null;
- try {
- String fileName = getTrackerFile(s, user, screen);
- if (fileName != null) {
- Properties tempProps = new Properties();
- // System.out.println("Loading lesson state from: " + fileName);
- in = new FileInputStream(fileName);
- tempProps.load(in);
- // allow the screen to use any custom properties it may have set
- LessonTracker tempLessonTracker = new LessonTracker();
- tempLessonTracker.setProperties(tempProps, screen);
- return tempLessonTracker;
- }
- } catch (FileNotFoundException e) {
- // Normal if the lesson has not been accessed yet.
- } catch (Exception e) {
- System.out.println("Failed to load lesson state for " + screen);
- e.printStackTrace();
- } finally {
- try {
- in.close();
- } catch (Exception e) {
- }
- }
-
- return new LessonTracker();
- }
-
- /**
- * Sets the completed attribute of the LessonTracker object
- *
- * @param completed The new completed value
- */
- public void setCompleted(boolean completed) {
- this.completed = completed;
- }
-
- /**
- * Sets the maxHintLevel attribute of the LessonTracker object
- *
- * @param maxHintLevel The new maxHintLevel value
- */
- public void setMaxHintLevel(int maxHintLevel) {
- this.maxHintLevel = Math.max(this.maxHintLevel, maxHintLevel);
- }
-
- /**
- * Allows the storing of properties for the logged in and a screen.
- *
- * @param s Description of the Parameter
- * @param screen a {@link org.owasp.webgoat.session.Screen} object.
- * @param screen a {@link org.owasp.webgoat.session.Screen} object.
- */
- public void store(WebSession s, Screen screen) {
- store(s, screen, s.getUserName());
- }
-
- /**
- * Allows the storing of properties for a user and a screen.
- *
- * @param s Description of the Parameter
- * @param screen a {@link org.owasp.webgoat.session.Screen} object.
- * @param screen a {@link org.owasp.webgoat.session.Screen} object.
- * @param user a {@link java.lang.String} object.
- */
- public void store(WebSession s, Screen screen, String user) {
-
- String fileName = getTrackerFile(s, user, screen);
- // System.out.println( "Storing data to" + fileName );
- lessonProperties.setProperty(screen.getTitle() + ".completed", Boolean.toString(completed));
- lessonProperties.setProperty(screen.getTitle() + ".maxHintLevel", Integer.toString(maxHintLevel));
- lessonProperties.setProperty(screen.getTitle() + ".numVisits", Integer.toString(numVisits));
- lessonProperties.setProperty(screen.getTitle() + ".viewedCookies", Boolean.toString(viewedCookies));
- lessonProperties.setProperty(screen.getTitle() + ".viewedHtml", Boolean.toString(viewedHtml));
- lessonProperties.setProperty(screen.getTitle() + ".viewedLessonPlan", Boolean.toString(viewedLessonPlan));
- lessonProperties.setProperty(screen.getTitle() + ".viewedParameters", Boolean.toString(viewedParameters));
- lessonProperties.setProperty(screen.getTitle() + ".viewedSource", Boolean.toString(viewedSource));
- lessonProperties.setProperty(screen.getTitle() + ".totalNumberOfAssignments", Integer.toString(totalNumberOfAssignments));
- try (FileOutputStream out = new FileOutputStream(fileName)) {
- lessonProperties.store(out, s.getUserName());
- } catch (IOException e) {
- log.warn("Warning User data for {} will not persist", s.getUserName());
- }
- }
-
- /**
- * Description of the Method
- *
- * @return Description of the Return Value
- */
- public String toString() {
- StringBuffer buff = new StringBuffer();
- buff.append("LessonTracker:" + "\n");
- buff.append(" - completed:................. " + completed + "\n");
- buff.append(" - maxHintLevel:.............. " + maxHintLevel + "\n");
- buff.append(" - numVisits:................. " + numVisits + "\n");
- buff.append(" - viewedCookies:............. " + viewedCookies + "\n");
- buff.append(" - viewedHtml:................ " + viewedHtml + "\n");
- buff.append(" - viewedLessonPlan:.......... " + viewedLessonPlan + "\n");
- buff.append(" - viewedParameters:.......... " + viewedParameters + "\n");
- buff.append(" - viewedSource:.............. " + viewedSource + "\n" + "\n");
- buff.append(" - totalNumberOfAssignments:.. " + viewedSource + "\n" + "\n");
- return buff.toString();
- }
-
- /**
- * Getter for the field lessonProperties
.
- *
- * @return Returns the lessonProperties.
- */
- public Properties getLessonProperties() {
- return lessonProperties;
- }
-
- /**
- * Setter for the field lessonProperties
.
- *
- * @param lessonProperties The lessonProperties to set.
- */
- public void setLessonProperties(Properties lessonProperties) {
- this.lessonProperties = lessonProperties;
+ public void reset() {
+ solvedAssignments.clear();
}
}
diff --git a/webgoat-container/src/main/java/org/owasp/webgoat/session/UserTracker.java b/webgoat-container/src/main/java/org/owasp/webgoat/session/UserTracker.java
index 1e073b391..692971da5 100644
--- a/webgoat-container/src/main/java/org/owasp/webgoat/session/UserTracker.java
+++ b/webgoat-container/src/main/java/org/owasp/webgoat/session/UserTracker.java
@@ -1,13 +1,16 @@
package org.owasp.webgoat.session;
+import lombok.SneakyThrows;
import org.owasp.webgoat.lessons.AbstractLesson;
+import org.owasp.webgoat.lessons.Assignment;
import org.springframework.beans.factory.annotation.Value;
-import org.springframework.stereotype.Component;
+import org.springframework.util.FileCopyUtils;
+import org.springframework.util.SerializationUtils;
+import java.io.File;
import java.util.HashMap;
import java.util.Map;
-import java.util.Optional;
/**
@@ -40,34 +43,15 @@ import java.util.Optional;
* @version $Id: $Id
* @since October 29, 2003
*/
-@Component
public class UserTracker {
- private static Map> storage = new HashMap<>();
private final String webgoatHome;
- private final WebSession webSession;
+ private final String user;
+ private Map storage = new HashMap<>();
- public UserTracker(@Value("${webgoat.user.directory}") final String webgoatHome, final WebSession webSession) {
+ public UserTracker(@Value("${webgoat.user.directory}") final String webgoatHome, final String user) {
this.webgoatHome = webgoatHome;
- this.webSession = webSession;
- }
-
- /**
- * getCurrentLessonTracker.
- *
- * @return a {@link org.owasp.webgoat.session.LessonTracker} object.
- */
- public LessonTracker getCurrentLessonTracker() {
- String lessonTitle = webSession.getCurrentLesson().getTitle();
- String username = webSession.getUserName();
- HashMap usermap = getUserMap(username);
- LessonTracker tracker = usermap.get(lessonTitle);
- if (tracker == null) {
- // Creates a new lesson tracker, if one does not exist on disk.
- tracker = LessonTracker.load(webSession, username, webSession.getCurrentLesson());
- usermap.put(lessonTitle, tracker);
- }
- return tracker;
+ this.user = user;
}
/**
@@ -76,31 +60,41 @@ public class UserTracker {
* @param lesson the lesson
* @return the optional lesson tracker
*/
- public Optional getLessonTracker(AbstractLesson lesson) {
- String username = webSession.getUserName();
- return Optional.ofNullable(getUserMap(username).getOrDefault(lesson.getTitle(), null));
- }
-
-
- /**
- * Gets the userMap attribute of the UserTracker object
- *
- * @param userName Description of the Parameter
- * @return The userMap value
- */
- private HashMap getUserMap(String userName) {
-
- HashMap usermap = storage.get(userName);
-
- if (usermap == null) {
-
- usermap = new HashMap<>();
-
- storage.put(userName, usermap);
-
+ public LessonTracker getLessonTracker(AbstractLesson lesson) {
+ LessonTracker lessonTracker = storage.get(lesson.getTitle());
+ if (lessonTracker == null) {
+ lessonTracker = new LessonTracker(lesson);
+ storage.put(lesson.getTitle(), lessonTracker);
}
-
- return (usermap);
+ return lessonTracker;
}
+ public void assignmentSolved(AbstractLesson lesson, Assignment assignment) {
+ LessonTracker lessonTracker = getLessonTracker(lesson);
+ lessonTracker.incrementAttempts();
+ lessonTracker.assignmentSolved(assignment.getClass().getSimpleName());
+ save();
+ }
+
+ public void assignmentFailed(AbstractLesson lesson) {
+ LessonTracker lessonTracker = getLessonTracker(lesson);
+ lessonTracker.incrementAttempts();
+ save();
+ }
+
+ @SneakyThrows
+ public void load() {
+ File file = new File(webgoatHome, user);
+ if (file.exists() && file.isFile()) {
+ this.storage = (Map) SerializationUtils.deserialize(FileCopyUtils.copyToByteArray(file));
+ }
+ }
+
+ @SneakyThrows
+ private void save() {
+ File file = new File(webgoatHome, user);
+ FileCopyUtils.copy(SerializationUtils.serialize(this.storage), file);
+ }
+
+
}
diff --git a/webgoat-container/src/main/java/org/owasp/webgoat/session/WebSession.java b/webgoat-container/src/main/java/org/owasp/webgoat/session/WebSession.java
index e70ac70cd..858610b4a 100644
--- a/webgoat-container/src/main/java/org/owasp/webgoat/session/WebSession.java
+++ b/webgoat-container/src/main/java/org/owasp/webgoat/session/WebSession.java
@@ -2,7 +2,6 @@ package org.owasp.webgoat.session;
import lombok.extern.slf4j.Slf4j;
import org.owasp.webgoat.lessons.AbstractLesson;
-import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.User;
@@ -44,13 +43,13 @@ public class WebSession {
private final User currentUser;
private final WebgoatContext webgoatContext;
private AbstractLesson currentLesson;
+ private UserTracker userTracker;
/**
* Constructor for the WebSession object
*
* @param webgoatContext a {@link org.owasp.webgoat.session.WebgoatContext} object.
*/
- @Autowired
public WebSession(WebgoatContext webgoatContext) {
this.webgoatContext = webgoatContext;
this.currentUser = (User) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
@@ -76,7 +75,6 @@ public class WebSession {
DatabaseUtilities.returnConnection(s.getUserName());
}
-
/**
* Setter for the field currentScreen
.
*
diff --git a/webgoat-container/src/main/resources/static/js/goatApp/view/LessonContentView.js b/webgoat-container/src/main/resources/static/js/goatApp/view/LessonContentView.js
index 6cf30b0cd..7d79fac85 100644
--- a/webgoat-container/src/main/resources/static/js/goatApp/view/LessonContentView.js
+++ b/webgoat-container/src/main/resources/static/js/goatApp/view/LessonContentView.js
@@ -77,7 +77,7 @@ define(['jquery',
this.renderFeedback(data.feedback);
this.renderOutput(data.output || "");
- if (data.lessonComplete) {
+ if (data.lessonCompleted) {
this.trigger('lesson:complete');
}
return false;
diff --git a/webgoat-container/src/test/java/org/owasp/webgoat/session/UserTrackerTest.java b/webgoat-container/src/test/java/org/owasp/webgoat/session/UserTrackerTest.java
new file mode 100644
index 000000000..1a29893db
--- /dev/null
+++ b/webgoat-container/src/test/java/org/owasp/webgoat/session/UserTrackerTest.java
@@ -0,0 +1,71 @@
+package org.owasp.webgoat.session;
+
+import com.google.common.collect.Lists;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mockito;
+import org.owasp.webgoat.lessons.AbstractLesson;
+import org.owasp.webgoat.lessons.Assignment;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.List;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.when;
+
+/**
+ * ************************************************************************************************
+ * This file is part of WebGoat, an Open Web Application Security Project utility. For details,
+ * please see http://www.owasp.org/
+ *
+ * Copyright (c) 2002 - 20014 Bruce Mayhew
+ *
+ * This program is free software; you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
+ * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program; if
+ * not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ *
+ * Getting Source ==============
+ *
+ * Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software
+ * projects.
+ *
+ *
+ * @author nbaars
+ * @version $Id: $Id
+ * @since November 15, 2016
+ */
+public class UserTrackerTest {
+
+ private File home;
+
+ @Before
+ public void init() throws IOException {
+ home = File.createTempFile("test", "test");
+ home.deleteOnExit();
+ }
+
+ @Test
+ public void writeAndRead() {
+ UserTracker userTracker = new UserTracker(home.getParent(), "test");
+ AbstractLesson abstractLesson = Mockito.mock(AbstractLesson.class);
+ Assignment assignment = Mockito.mock(Assignment.class);
+ when(abstractLesson.getAssignments()).thenReturn((List)Lists.newArrayList(assignment.getClass()));
+ userTracker.getLessonTracker(abstractLesson);
+ userTracker.assignmentSolved(abstractLesson, assignment);
+
+ userTracker = new UserTracker(home.getParent(), "test");
+ userTracker.load();
+ assertThat(userTracker.getLessonTracker(abstractLesson).isLessonSolved()).isTrue();
+ }
+
+
+}
\ No newline at end of file
diff --git a/webgoat-lessons/client-side-filtering/src/main/java/org/owasp/webgoat/plugin/Attack.java b/webgoat-lessons/client-side-filtering/src/main/java/org/owasp/webgoat/plugin/Attack.java
index 22ededdd9..ffddc5bb3 100644
--- a/webgoat-lessons/client-side-filtering/src/main/java/org/owasp/webgoat/plugin/Attack.java
+++ b/webgoat-lessons/client-side-filtering/src/main/java/org/owasp/webgoat/plugin/Attack.java
@@ -1,7 +1,6 @@
package org.owasp.webgoat.plugin;
-import org.owasp.webgoat.lessons.AssignmentEndpoint;
-import org.owasp.webgoat.lessons.LessonEndpointMapping;
+import org.owasp.webgoat.lessons.Assignment;
import org.owasp.webgoat.lessons.model.AttackResult;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
@@ -39,8 +38,7 @@ import java.io.IOException;
* @version $Id: $Id
* @since August 11, 2016
*/
-@LessonEndpointMapping
-public class Attack extends AssignmentEndpoint {
+public class Attack extends Assignment {
@RequestMapping(method = RequestMethod.POST)
public @ResponseBody AttackResult completed(@RequestParam String answer) throws IOException {
diff --git a/webgoat-lessons/client-side-filtering/src/main/java/org/owasp/webgoat/plugin/Salaries.java b/webgoat-lessons/client-side-filtering/src/main/java/org/owasp/webgoat/plugin/Salaries.java
index 4622007df..5f20f1e69 100644
--- a/webgoat-lessons/client-side-filtering/src/main/java/org/owasp/webgoat/plugin/Salaries.java
+++ b/webgoat-lessons/client-side-filtering/src/main/java/org/owasp/webgoat/plugin/Salaries.java
@@ -7,8 +7,7 @@ package org.owasp.webgoat.plugin;
import org.apache.ecs.html.TD;
import org.apache.ecs.html.TR;
import org.apache.ecs.html.Table;
-import org.owasp.webgoat.lessons.AssignmentEndpoint;
-import org.owasp.webgoat.lessons.LessonEndpointMapping;
+import org.owasp.webgoat.lessons.Endpoint;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.w3c.dom.Node;
@@ -26,8 +25,7 @@ import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
-@LessonEndpointMapping
-public class Salaries extends AssignmentEndpoint {
+public class Salaries extends Endpoint {
@RequestMapping(method = RequestMethod.GET)
public void invoke(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
diff --git a/webgoat-lessons/http-basics/src/main/java/org/owasp/webgoat/plugin/HttpBasicsLesson.java b/webgoat-lessons/http-basics/src/main/java/org/owasp/webgoat/plugin/HttpBasicsLesson.java
index d16685c88..9a5a7eab2 100644
--- a/webgoat-lessons/http-basics/src/main/java/org/owasp/webgoat/plugin/HttpBasicsLesson.java
+++ b/webgoat-lessons/http-basics/src/main/java/org/owasp/webgoat/plugin/HttpBasicsLesson.java
@@ -1,7 +1,6 @@
package org.owasp.webgoat.plugin;
-import org.owasp.webgoat.lessons.AssignmentEndpoint;
-import org.owasp.webgoat.lessons.LessonEndpointMapping;
+import org.owasp.webgoat.lessons.Assignment;
import org.owasp.webgoat.lessons.model.AttackResult;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
@@ -45,8 +44,7 @@ import java.io.IOException;
* @created October 28, 2003
*/
-@LessonEndpointMapping
-public class HttpBasicsLesson extends AssignmentEndpoint {
+public class HttpBasicsLesson extends Assignment {
@RequestMapping(method = RequestMethod.POST)
public @ResponseBody AttackResult completed(@RequestParam String person, HttpServletRequest request) throws IOException {
diff --git a/webgoat-lessons/http-basics/src/main/java/org/owasp/webgoat/plugin/HttpBasicsQuiz.java b/webgoat-lessons/http-basics/src/main/java/org/owasp/webgoat/plugin/HttpBasicsQuiz.java
index 8892ef270..fbfd42e08 100644
--- a/webgoat-lessons/http-basics/src/main/java/org/owasp/webgoat/plugin/HttpBasicsQuiz.java
+++ b/webgoat-lessons/http-basics/src/main/java/org/owasp/webgoat/plugin/HttpBasicsQuiz.java
@@ -1,17 +1,15 @@
package org.owasp.webgoat.plugin;
-import java.io.IOException;
-
-import javax.servlet.http.HttpServletRequest;
-
-import org.owasp.webgoat.lessons.AssignmentEndpoint;
-import org.owasp.webgoat.lessons.LessonEndpointMapping;
+import org.owasp.webgoat.lessons.Assignment;
import org.owasp.webgoat.lessons.model.AttackResult;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
+import javax.servlet.http.HttpServletRequest;
+import java.io.IOException;
+
/**
* *************************************************************************************************
*
@@ -46,8 +44,7 @@ import org.springframework.web.bind.annotation.ResponseBody;
* @created October 28, 2003
*/
-@LessonEndpointMapping
-public class HttpBasicsQuiz extends AssignmentEndpoint {
+public class HttpBasicsQuiz extends Assignment {
@RequestMapping(method = RequestMethod.POST)
public @ResponseBody AttackResult completed(@RequestParam String answer, @RequestParam String magic_answer, @RequestParam String magic_num, HttpServletRequest request) throws IOException {