Fixed issue with lesson tracking

This commit is contained in:
Nanne Baars
2016-11-15 09:28:39 +01:00
parent 0bec575913
commit 5babe19f2b
25 changed files with 306 additions and 554 deletions

View File

@ -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);

View File

@ -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<String> assignments;
private final Set<String> 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;
}
/**
* <p>Getter for the field <code>viewedSolution</code>.</p>
*
* @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"));
}
/**
* <p>getUserDir.</p>
*
* @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();
}
/**
* <p>Getter for the field <code>lessonProperties</code>.</p>
*
* @return Returns the lessonProperties.
*/
public Properties getLessonProperties() {
return lessonProperties;
}
/**
* <p>Setter for the field <code>lessonProperties</code>.</p>
*
* @param lessonProperties The lessonProperties to set.
*/
public void setLessonProperties(Properties lessonProperties) {
this.lessonProperties = lessonProperties;
public void reset() {
solvedAssignments.clear();
}
}

View File

@ -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<String, HashMap<String, LessonTracker>> storage = new HashMap<>();
private final String webgoatHome;
private final WebSession webSession;
private final String user;
private Map<String, LessonTracker> 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;
}
/**
* <p>getCurrentLessonTracker.</p>
*
* @return a {@link org.owasp.webgoat.session.LessonTracker} object.
*/
public LessonTracker getCurrentLessonTracker() {
String lessonTitle = webSession.getCurrentLesson().getTitle();
String username = webSession.getUserName();
HashMap<String, LessonTracker> 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<LessonTracker> 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<String, LessonTracker> getUserMap(String userName) {
HashMap<String, LessonTracker> 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<String, LessonTracker>) SerializationUtils.deserialize(FileCopyUtils.copyToByteArray(file));
}
}
@SneakyThrows
private void save() {
File file = new File(webgoatHome, user);
FileCopyUtils.copy(SerializationUtils.serialize(this.storage), file);
}
}

View File

@ -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());
}
/**
* <p> Setter for the field <code>currentScreen</code>. </p>
*