Fixed issue with lesson tracking
This commit is contained in:
@ -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);
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@ -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>
|
||||
*
|
||||
|
Reference in New Issue
Block a user