From eb7a6bd2be5285cc099a55af3b47d1307dbb8a3b Mon Sep 17 00:00:00 2001 From: Nanne Baars Date: Tue, 2 May 2017 02:29:47 +0200 Subject: [PATCH] Creating endpoint for the scoreboard --- webgoat-container/pom.xml | 8 + .../main/java/org/owasp/webgoat/WebGoat.java | 15 +- .../assignments/AssignmentEndpoint.java | 10 +- .../org/owasp/webgoat/lessons/Assignment.java | 15 +- .../webgoat/service/LessonMenuService.java | 12 +- .../service/LessonProgressService.java | 9 +- .../webgoat/service/ReportCardService.java | 23 +-- .../webgoat/service/RestartLessonService.java | 6 +- .../owasp/webgoat/session/UserDatabase.java | 181 ------------------ .../owasp/webgoat/session/UserTracker.java | 154 --------------- .../org/owasp/webgoat/session/WebSession.java | 1 + .../{session => users}/LessonTracker.java | 13 +- .../webgoat/users/RegistrationController.java | 1 - .../org/owasp/webgoat/users/Scoreboard.java | 66 ++----- .../owasp/webgoat/users/UserRepository.java | 5 +- .../org/owasp/webgoat/users/UserService.java | 3 +- .../org/owasp/webgoat/users/UserTracker.java | 119 ++++++++++++ .../webgoat/users/UserTrackerRepository.java | 12 ++ .../{session => users}/WebGoatUser.java | 8 +- .../src/main/resources/application.properties | 3 + .../assignments/AssignmentEndpointTest.java | 11 +- .../service/LessonMenuServiceTest.java | 21 +- .../service/LessonProgressServiceTest.java | 13 +- .../service/ReportCardServiceTest.java | 16 +- .../webgoat/session/LessonTrackerTest.java | 1 + .../webgoat/session/UserTrackerTest.java | 105 ---------- .../owasp/webgoat/users/UserServiceTest.java | 5 +- .../webgoat/users/UserValidatorTest.java | 1 - .../java/org/owasp/webgoat/plugin/Flag.java | 15 +- 29 files changed, 284 insertions(+), 568 deletions(-) delete mode 100644 webgoat-container/src/main/java/org/owasp/webgoat/session/UserDatabase.java delete mode 100644 webgoat-container/src/main/java/org/owasp/webgoat/session/UserTracker.java rename webgoat-container/src/main/java/org/owasp/webgoat/{session => users}/LessonTracker.java (94%) create mode 100644 webgoat-container/src/main/java/org/owasp/webgoat/users/UserTracker.java create mode 100644 webgoat-container/src/main/java/org/owasp/webgoat/users/UserTrackerRepository.java rename webgoat-container/src/main/java/org/owasp/webgoat/{session => users}/WebGoatUser.java (91%) delete mode 100644 webgoat-container/src/test/java/org/owasp/webgoat/session/UserTrackerTest.java diff --git a/webgoat-container/pom.xml b/webgoat-container/pom.xml index c67c21a8c..0cd862dfc 100644 --- a/webgoat-container/pom.xml +++ b/webgoat-container/pom.xml @@ -121,6 +121,14 @@ liquibase-core 3.4.1 + + org.springframework.boot + spring-boot-starter-data-mongodb + + + de.flapdoodle.embed + de.flapdoodle.embed.mongo + org.apache.commons commons-lang3 diff --git a/webgoat-container/src/main/java/org/owasp/webgoat/WebGoat.java b/webgoat-container/src/main/java/org/owasp/webgoat/WebGoat.java index 36a2c761d..58b269168 100644 --- a/webgoat-container/src/main/java/org/owasp/webgoat/WebGoat.java +++ b/webgoat-container/src/main/java/org/owasp/webgoat/WebGoat.java @@ -31,12 +31,14 @@ package org.owasp.webgoat; import com.fasterxml.jackson.annotation.JsonInclude; -import lombok.SneakyThrows; import lombok.extern.slf4j.Slf4j; import org.apache.catalina.Context; import org.owasp.webgoat.plugins.PluginEndpointPublisher; import org.owasp.webgoat.plugins.PluginsLoader; -import org.owasp.webgoat.session.*; +import org.owasp.webgoat.session.Course; +import org.owasp.webgoat.session.UserSessionData; +import org.owasp.webgoat.session.WebSession; +import org.owasp.webgoat.session.WebgoatContext; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @@ -104,15 +106,6 @@ public class WebGoat extends SpringBootServletInitializer { return new PluginsLoader(pluginEndpointPublisher).loadPlugins(); } - @Bean - @Scope(value = "session", proxyMode = ScopedProxyMode.TARGET_CLASS) - @SneakyThrows - public UserTracker userTracker(@Value("${webgoat.user.directory}") final String webgoatHome, WebSession webSession) { - UserTracker userTracker = new UserTracker(webgoatHome, webSession.getUserName()); - userTracker.load(); - return userTracker; - } - @Bean public EmbeddedServletContainerFactory servletContainer() { TomcatEmbeddedServletContainerFactory factory = new TomcatEmbeddedServletContainerFactory(); diff --git a/webgoat-container/src/main/java/org/owasp/webgoat/assignments/AssignmentEndpoint.java b/webgoat-container/src/main/java/org/owasp/webgoat/assignments/AssignmentEndpoint.java index f44b1cfd0..584ed7155 100644 --- a/webgoat-container/src/main/java/org/owasp/webgoat/assignments/AssignmentEndpoint.java +++ b/webgoat-container/src/main/java/org/owasp/webgoat/assignments/AssignmentEndpoint.java @@ -27,7 +27,8 @@ package org.owasp.webgoat.assignments; import lombok.Getter; import org.owasp.webgoat.i18n.PluginMessages; import org.owasp.webgoat.session.UserSessionData; -import org.owasp.webgoat.session.UserTracker; +import org.owasp.webgoat.users.UserTracker; +import org.owasp.webgoat.users.UserTrackerRepository; import org.owasp.webgoat.session.WebSession; import org.springframework.beans.factory.annotation.Autowired; @@ -43,7 +44,7 @@ import org.springframework.beans.factory.annotation.Autowired; public abstract class AssignmentEndpoint extends Endpoint { @Autowired - private UserTracker userTracker; + private UserTrackerRepository userTrackerRepository; @Autowired private WebSession webSession; @Autowired @@ -54,11 +55,16 @@ public abstract class AssignmentEndpoint extends Endpoint { //// TODO: 11/13/2016 events better fit? protected AttackResult trackProgress(AttackResult attackResult) { + UserTracker userTracker = userTrackerRepository.findOne(webSession.getUserName()); + if (userTracker == null) { + userTracker = new UserTracker(webSession.getUserName()); + } if (attackResult.assignmentSolved()) { userTracker.assignmentSolved(webSession.getCurrentLesson(), this.getClass().getSimpleName()); } else { userTracker.assignmentFailed(webSession.getCurrentLesson()); } + userTrackerRepository.save(userTracker); return attackResult; } 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 index 1df91dc66..0558a5ad3 100644 --- a/webgoat-container/src/main/java/org/owasp/webgoat/lessons/Assignment.java +++ b/webgoat-container/src/main/java/org/owasp/webgoat/lessons/Assignment.java @@ -1,11 +1,7 @@ package org.owasp.webgoat.lessons; -import lombok.AllArgsConstructor; -import lombok.Getter; -import lombok.NonNull; -import lombok.RequiredArgsConstructor; +import lombok.*; -import java.io.Serializable; import java.util.List; /** @@ -39,14 +35,13 @@ import java.util.List; */ @AllArgsConstructor @RequiredArgsConstructor +@NoArgsConstructor @Getter -public class Assignment implements Serializable { - - private static final long serialVersionUID = 5410058267505412928L; +public class Assignment { @NonNull - private final String name; + private String name; @NonNull - private final String path; + private String path; private List hints; } 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 c9f316cf6..097085c48 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 @@ -34,8 +34,10 @@ import org.owasp.webgoat.lessons.Category; import org.owasp.webgoat.lessons.LessonMenuItem; import org.owasp.webgoat.lessons.LessonMenuItemType; import org.owasp.webgoat.session.Course; -import org.owasp.webgoat.session.LessonTracker; -import org.owasp.webgoat.session.UserTracker; +import org.owasp.webgoat.session.WebSession; +import org.owasp.webgoat.users.LessonTracker; +import org.owasp.webgoat.users.UserTracker; +import org.owasp.webgoat.users.UserTrackerRepository; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseBody; @@ -57,7 +59,8 @@ public class LessonMenuService { public static final String URL_LESSONMENU_MVC = "/service/lessonmenu.mvc"; private final Course course; - private UserTracker userTracker; + private final WebSession webSession; + private UserTrackerRepository userTrackerRepository; /** * Returns the lesson menu which is used to build the left nav @@ -68,8 +71,9 @@ public class LessonMenuService { public @ResponseBody List showLeftNav() { - List menu = new ArrayList(); + List menu = new ArrayList<>(); List categories = course.getCategories(); + UserTracker userTracker = userTrackerRepository.findOne(webSession.getUserName()); for (Category category : categories) { LessonMenuItem categoryItem = new LessonMenuItem(); 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 2a6387ac2..fb4fe0071 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 @@ -7,9 +7,10 @@ import lombok.Getter; import org.owasp.webgoat.lessons.AbstractLesson; import org.owasp.webgoat.lessons.Assignment; import org.owasp.webgoat.lessons.LessonInfoModel; -import org.owasp.webgoat.session.LessonTracker; -import org.owasp.webgoat.session.UserTracker; import org.owasp.webgoat.session.WebSession; +import org.owasp.webgoat.users.LessonTracker; +import org.owasp.webgoat.users.UserTracker; +import org.owasp.webgoat.users.UserTrackerRepository; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseBody; @@ -28,7 +29,7 @@ import java.util.Map; @AllArgsConstructor public class LessonProgressService { - private UserTracker userTracker; + private UserTrackerRepository userTrackerRepository; private WebSession webSession; /** @@ -39,6 +40,7 @@ public class LessonProgressService { @RequestMapping(value = "/service/lessonprogress.mvc", produces = "application/json") @ResponseBody public Map getLessonInfo() { + UserTracker userTracker = userTrackerRepository.findOne(webSession.getUserName()); LessonTracker lessonTracker = userTracker.getLessonTracker(webSession.getCurrentLesson()); Map json = Maps.newHashMap(); String successMessage = ""; @@ -61,6 +63,7 @@ public class LessonProgressService { @RequestMapping(value = "/service/lessonoverview.mvc", produces = "application/json") @ResponseBody public List lessonOverview() { + UserTracker userTracker = userTrackerRepository.findOne(webSession.getUserName()); AbstractLesson currentLesson = webSession.getCurrentLesson(); List result = Lists.newArrayList(); if ( currentLesson != null ) { diff --git a/webgoat-container/src/main/java/org/owasp/webgoat/service/ReportCardService.java b/webgoat-container/src/main/java/org/owasp/webgoat/service/ReportCardService.java index 1fc17a5ba..21c8c1f20 100644 --- a/webgoat-container/src/main/java/org/owasp/webgoat/service/ReportCardService.java +++ b/webgoat-container/src/main/java/org/owasp/webgoat/service/ReportCardService.java @@ -29,25 +29,20 @@ package org.owasp.webgoat.service; import com.google.common.collect.Lists; -import com.google.common.collect.Maps; +import lombok.AllArgsConstructor; import lombok.Getter; import lombok.Setter; -import lombok.Singular; -import org.apache.catalina.User; import org.owasp.webgoat.lessons.AbstractLesson; import org.owasp.webgoat.session.Course; -import org.owasp.webgoat.session.LessonTracker; -import org.owasp.webgoat.session.UserTracker; import org.owasp.webgoat.session.WebSession; +import org.owasp.webgoat.users.LessonTracker; +import org.owasp.webgoat.users.UserTracker; +import org.owasp.webgoat.users.UserTrackerRepository; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseBody; -import org.springframework.web.bind.annotation.RestController; -import java.util.HashMap; import java.util.List; -import java.util.Map; /** *

ReportCardService

@@ -56,22 +51,20 @@ import java.util.Map; * @version $Id: $Id */ @Controller +@AllArgsConstructor public class ReportCardService { - private final UserTracker userTracker; + private final WebSession webSession; + private final UserTrackerRepository userTrackerRepository; private final Course course; - public ReportCardService(UserTracker userTracker, Course course) { - this.userTracker = userTracker; - this.course = course; - } - /** * Endpoint which generates the report card for the current use to show the stats on the solved lessons */ @GetMapping(path = "/service/reportcard.mvc", produces = "application/json") @ResponseBody public ReportCard reportCard() { + UserTracker userTracker = userTrackerRepository.findOne(webSession.getUserName()); List lessons = course.getLessons(); ReportCard reportCard = new ReportCard(); reportCard.setTotalNumberOfLessons(course.getTotalOfLessons()); 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 34650cc1c..5a46f90b0 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 @@ -26,8 +26,9 @@ package org.owasp.webgoat.service; import lombok.AllArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.owasp.webgoat.lessons.AbstractLesson; -import org.owasp.webgoat.session.UserTracker; import org.owasp.webgoat.session.WebSession; +import org.owasp.webgoat.users.UserTracker; +import org.owasp.webgoat.users.UserTrackerRepository; import org.springframework.http.HttpStatus; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; @@ -45,7 +46,7 @@ import org.springframework.web.bind.annotation.ResponseStatus; public class RestartLessonService { private final WebSession webSession; - private final UserTracker userTracker; + private UserTrackerRepository userTrackerRepository; /** * Returns current lesson @@ -58,6 +59,7 @@ public class RestartLessonService { AbstractLesson al = webSession.getCurrentLesson(); log.debug("Restarting lesson: " + al); + UserTracker userTracker = userTrackerRepository.findOne(webSession.getUserName()); userTracker.reset(al); } } diff --git a/webgoat-container/src/main/java/org/owasp/webgoat/session/UserDatabase.java b/webgoat-container/src/main/java/org/owasp/webgoat/session/UserDatabase.java deleted file mode 100644 index 09e542487..000000000 --- a/webgoat-container/src/main/java/org/owasp/webgoat/session/UserDatabase.java +++ /dev/null @@ -1,181 +0,0 @@ -package org.owasp.webgoat.session; - -import java.io.File; -import java.sql.Connection; -import java.sql.DriverManager; -import java.sql.PreparedStatement; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.sql.Statement; - -class UserDatabase { - private Connection userDB; - private final String USER_DB_URI = "jdbc:h2:" + System.getProperty("user.dir") + File.separator + "UserDatabase"; - - private final String CREATE_USERS_TABLE = "CREATE TABLE IF NOT EXISTS users (id INTEGER PRIMARY KEY AUTO_INCREMENT, username VARCHAR(255) NOT NULL UNIQUE);"; - private final String CREATE_ROLES_TABLE = "CREATE TABLE IF NOT EXISTS roles (id INTEGER PRIMARY KEY AUTO_INCREMENT, rolename VARCHAR(255) NOT NULL UNIQUE);"; - private final String CREATE_USER_ROLES_TABLE = "CREATE TABLE IF NOT EXISTS user_roles (id INTEGER PRIMARY KEY AUTO_INCREMENT, user_id INTEGER NOT NULL, role_id INTEGER NOT NULL, FOREIGN KEY (user_id) REFERENCES users(id), FOREIGN KEY (role_id) REFERENCES roles(id));"; - private final String ADD_DEFAULT_USERS = "INSERT INTO users (username) VALUES ('webgoat'),('basic'),('guest');"; - private final String ADD_DEFAULT_ROLES = "INSERT INTO roles (rolename) VALUES ('webgoat_basic'),('webgoat_admin'),('webgoat_user');"; - private final String ADD_ROLE_TO_USER = "INSERT INTO user_roles (user_id, role_id) SELECT users.id, roles.id FROM users, roles WHERE users.username = ? AND roles.rolename = ?;"; - - private final String QUERY_ALL_USERS = "SELECT username FROM users;"; - private final String QUERY_ALL_ROLES_FOR_USERNAME = "SELECT rolename FROM roles, user_roles, users WHERE roles.id = user_roles.role_id AND user_roles.user_id = users.id AND users.username = ?;"; - private final String QUERY_TABLE_COUNT = "SELECT count(id) AS count FROM table;"; - - /** - *

Constructor for UserDatabase.

- */ - public UserDatabase() { - createDefaultTables(); - if (getTableCount("users") <= 0) { - createDefaultUsers(); - } - if (getTableCount("roles") <= 0) { - createDefaultRoles(); - } - if (getTableCount("user_roles") <= 0) { - addDefaultRolesToDefaultUsers(); - } - } - - /** - *

open.

- * - * @return a boolean. - */ - public boolean open() { - try { - if (userDB == null || userDB.isClosed()) { - Class.forName("org.h2.Driver"); - userDB = DriverManager.getConnection(USER_DB_URI, "webgoat_admin", ""); - } - } catch (SQLException e) { - e.printStackTrace(); - return false; - } catch (ClassNotFoundException e) { - e.printStackTrace(); - return false; - } - return true; - } - - /** - *

close.

- * - * @return a boolean. - */ - public boolean close() { - try { - if (userDB != null && !userDB.isClosed()) - userDB.close(); - } catch (SQLException e) { - e.printStackTrace(); - return false; - } - return true; - } - - /** - *

getTableCount.

- * - * @param tableName a {@link java.lang.String} object. - * @return a int. - */ - public int getTableCount(String tableName) { - int count = 0; - try { - open(); - Statement statement = userDB.createStatement(); - ResultSet countResult = statement.executeQuery(QUERY_TABLE_COUNT.replace("table", tableName)); - if (countResult.next()) { - count = countResult.getInt("count"); - } - countResult.close(); - statement.close(); - close(); - } catch (SQLException e) { - e.printStackTrace(); - count = -1; - } - return count; - } - - /** - *

addRoleToUser.

- * - * @param username a {@link java.lang.String} object. - * @param rolename a {@link java.lang.String} object. - * @return a boolean. - */ - public boolean addRoleToUser(String username, String rolename) { - try { - open(); - PreparedStatement statement = userDB.prepareStatement(ADD_ROLE_TO_USER); - statement.setString(1, username); - statement.setString(2, rolename); - statement.execute(); - statement.close(); - close(); - } catch (SQLException e) { - e.printStackTrace(); - return false; - } - return true; - } - - /* - * Methods to initialise the default state of the database. - */ - - private boolean createDefaultTables() { - try { - open(); - Statement statement = userDB.createStatement(); - statement.execute(CREATE_USERS_TABLE); - statement.execute(CREATE_ROLES_TABLE); - statement.execute(CREATE_USER_ROLES_TABLE); - statement.close(); - close(); - } catch (SQLException e) { - e.printStackTrace(); - return false; - } - return true; - } - - private boolean createDefaultUsers() { - try { - open(); - Statement statement = userDB.createStatement(); - statement.execute(ADD_DEFAULT_USERS); - statement.close(); - close(); - } catch (SQLException e) { - e.printStackTrace(); - return false; - } - return true; - } - - private boolean createDefaultRoles() { - try { - open(); - Statement statement = userDB.createStatement(); - statement.execute(ADD_DEFAULT_ROLES); - statement.close(); - close(); - } catch (SQLException e) { - e.printStackTrace(); - return false; - } - return true; - } - - private void addDefaultRolesToDefaultUsers() { - addRoleToUser("webgoat", "webgoat_admin"); - addRoleToUser("basic", "webgoat_user"); - addRoleToUser("basic", "webgoat_basic"); - addRoleToUser("guest", "webgoat_user"); - } -} 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 deleted file mode 100644 index a25abd00f..000000000 --- a/webgoat-container/src/main/java/org/owasp/webgoat/session/UserTracker.java +++ /dev/null @@ -1,154 +0,0 @@ - -package org.owasp.webgoat.session; - -import com.google.common.collect.Maps; -import com.google.common.io.ByteStreams; -import lombok.SneakyThrows; -import lombok.extern.slf4j.Slf4j; -import org.owasp.webgoat.lessons.AbstractLesson; -import org.owasp.webgoat.lessons.Assignment; -import org.springframework.core.serializer.DefaultDeserializer; - -import java.io.*; -import java.util.Map; -import java.util.stream.Collectors; - - -/** - * ************************************************************************************************ - *

- *

- * 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 Bruce Mayhew WebGoat - * @version $Id: $Id - * @since October 29, 2003 - */ -@Slf4j -public class UserTracker { - - private final String webgoatHome; - private final String user; - - public UserTracker(final String webgoatHome, final String user) { - this.webgoatHome = webgoatHome; - this.user = user; - } - - /** - * Returns the lesson tracker for a specific lesson if available. - * - * @param lesson the lesson - * @return the optional lesson tracker - */ - public LessonTracker getLessonTracker(AbstractLesson lesson) { - return getLessonTracker(load(), lesson); - } - - /** - * Returns the lesson tracker for a specific lesson if available. - * - * @param lesson the lesson - * @return the optional lesson tracker - */ - public LessonTracker getLessonTracker(Map storage, AbstractLesson lesson) { - LessonTracker lessonTracker = storage.get(lesson.getTitle()); - if (lessonTracker == null) { - lessonTracker = new LessonTracker(lesson); - storage.put(lesson.getTitle(), lessonTracker); - save(storage); - } - return lessonTracker; - } - - public void assignmentSolved(AbstractLesson lesson, String assignmentName) { - Map storage = load(); - LessonTracker lessonTracker = storage.get(lesson.getTitle()); - lessonTracker.incrementAttempts(); - lessonTracker.assignmentSolved(assignmentName); - save(storage); - } - - public void assignmentFailed(AbstractLesson lesson) { - Map storage = load(); - LessonTracker lessonTracker = storage.get(lesson.getTitle()); - lessonTracker.incrementAttempts(); - save(storage); - } - - public Map load() { - File file = new File(webgoatHome, user + ".progress"); - Map storage = Maps.newHashMap(); - if (file.exists() && file.isFile()) { - try { - DefaultDeserializer deserializer = new DefaultDeserializer(Thread.currentThread().getContextClassLoader()); - try (FileInputStream fis = new FileInputStream(file)) { - byte[] b = ByteStreams.toByteArray(fis); - storage = (Map) deserializer.deserialize(new ByteArrayInputStream(b)); - } - } catch (Exception e) { - log.error("Unable to read the progress file, creating a new one..."); - } - } - return storage; - } - - @SneakyThrows - private void save(Map storage) { - File file = new File(webgoatHome, user + ".progress"); - - try (ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream(file))) { - objectOutputStream.writeObject(storage); - objectOutputStream.flush(); - } - } - - - public void reset(AbstractLesson al) { - Map storage = load(); - LessonTracker lessonTracker = getLessonTracker(storage, al); - lessonTracker.reset(); - save(storage); - } - - public int numberOfLessonsSolved() { - int numberOfLessonsSolved = 0; - Map storage = load(); - for (LessonTracker lessonTracker : storage.values()) { - if (lessonTracker.isLessonSolved()) { - numberOfLessonsSolved = numberOfLessonsSolved + 1; - } - } - return numberOfLessonsSolved; - } - - public int numberOfAssignmentsSolved() { - int numberOfAssignmentsSolved = 0; - Map storage = load(); - for (LessonTracker lessonTracker : storage.values()) { - Map lessonOverview = lessonTracker.getLessonOverview(); - numberOfAssignmentsSolved = lessonOverview.values().stream().filter(b -> b).collect(Collectors.counting()).intValue(); - } - return numberOfAssignmentsSolved; - } -} 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 bc12af039..33196575a 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,6 +2,7 @@ package org.owasp.webgoat.session; import lombok.extern.slf4j.Slf4j; import org.owasp.webgoat.lessons.AbstractLesson; +import org.owasp.webgoat.users.WebGoatUser; import org.springframework.security.core.context.SecurityContextHolder; import java.sql.Connection; diff --git a/webgoat-container/src/main/java/org/owasp/webgoat/session/LessonTracker.java b/webgoat-container/src/main/java/org/owasp/webgoat/users/LessonTracker.java similarity index 94% rename from webgoat-container/src/main/java/org/owasp/webgoat/session/LessonTracker.java rename to webgoat-container/src/main/java/org/owasp/webgoat/users/LessonTracker.java index 3d16e90a8..bff30316e 100644 --- a/webgoat-container/src/main/java/org/owasp/webgoat/session/LessonTracker.java +++ b/webgoat-container/src/main/java/org/owasp/webgoat/users/LessonTracker.java @@ -1,5 +1,5 @@ -package org.owasp.webgoat.session; +package org.owasp.webgoat.users; import com.google.common.collect.Lists; import com.google.common.collect.Sets; @@ -7,7 +7,6 @@ import lombok.Getter; import org.owasp.webgoat.lessons.AbstractLesson; import org.owasp.webgoat.lessons.Assignment; -import java.io.Serializable; import java.util.List; import java.util.Map; import java.util.Optional; @@ -45,14 +44,20 @@ import java.util.stream.Collectors; * @version $Id: $Id * @since October 29, 2003 */ -public class LessonTracker implements Serializable { - private static final long serialVersionUID = 5410058267505412928L; +public class LessonTracker { + @Getter + private String lessonName; private final Set solvedAssignments = Sets.newHashSet(); private final List allAssignments = Lists.newArrayList(); @Getter private int numberOfAttempts = 0; + protected LessonTracker() { + //Mongo + } + public LessonTracker(AbstractLesson lesson) { + lessonName = lesson.getId(); allAssignments.addAll(lesson.getAssignments()); } diff --git a/webgoat-container/src/main/java/org/owasp/webgoat/users/RegistrationController.java b/webgoat-container/src/main/java/org/owasp/webgoat/users/RegistrationController.java index f4bf8fe61..5c7a4fff3 100644 --- a/webgoat-container/src/main/java/org/owasp/webgoat/users/RegistrationController.java +++ b/webgoat-container/src/main/java/org/owasp/webgoat/users/RegistrationController.java @@ -2,7 +2,6 @@ package org.owasp.webgoat.users; import lombok.AllArgsConstructor; import lombok.extern.slf4j.Slf4j; -import org.owasp.webgoat.session.WebGoatUser; import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.core.context.SecurityContextHolder; diff --git a/webgoat-container/src/main/java/org/owasp/webgoat/users/Scoreboard.java b/webgoat-container/src/main/java/org/owasp/webgoat/users/Scoreboard.java index f6809852d..1e0c66da5 100644 --- a/webgoat-container/src/main/java/org/owasp/webgoat/users/Scoreboard.java +++ b/webgoat-container/src/main/java/org/owasp/webgoat/users/Scoreboard.java @@ -1,22 +1,13 @@ package org.owasp.webgoat.users; -import com.google.common.collect.Maps; -import com.google.common.io.ByteStreams; +import com.google.common.collect.Lists; import lombok.AllArgsConstructor; import lombok.Getter; -import lombok.SneakyThrows; -import org.owasp.webgoat.lessons.Assignment; -import org.owasp.webgoat.session.LessonTracker; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.core.serializer.DefaultDeserializer; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; -import java.io.ByteArrayInputStream; -import java.io.File; -import java.io.FileInputStream; import java.util.List; -import java.util.Map; +import java.util.stream.Collectors; /** * Temp endpoint just for the CTF. @@ -25,13 +16,11 @@ import java.util.Map; * @since 3/23/17. */ @RestController +@AllArgsConstructor public class Scoreboard { - @AllArgsConstructor - @Getter - private class Challenge { - private List rankings; - } + private final UserTrackerRepository userTrackerRepository; + private final UserRepository userRepository; @AllArgsConstructor @Getter @@ -40,40 +29,23 @@ public class Scoreboard { private int flagsCaptured; } - private final String webgoatDirectory; - - public Scoreboard(@Value("${webgoat.server.directory}") final String webgoatDirectory) { - this.webgoatDirectory = webgoatDirectory; - } - @GetMapping("/scoreboard") - public Challenge getRankings() { - File homeDir = new File(webgoatDirectory); - File[] files = homeDir.listFiles(f -> f.getName().endsWith(".progress")); - for (File progressFile : files) { - String username = progressFile.getName().replace(".progress", ""); - Map storage = load(progressFile); - LessonTracker lessonTracker = storage.get("WebGoat Challenge"); - Map lessonOverview = lessonTracker.getLessonOverview(); - for (int i = 0; i <= 5; i++) { - //lessonOverview.e - - } + public List getRankings() { + List allUsers = userRepository.findAll(); + List rankings = Lists.newArrayList(); + for (WebGoatUser user : allUsers) { + UserTracker userTracker = userTrackerRepository.findOne(user.getUsername()); + int challengesSolved = challengesSolved(userTracker); + rankings.add(new Ranking(user.getUsername(), challengesSolved)); } - return null; + return rankings; } - @SneakyThrows - private Map load(File progressFile) { - Map storage = Maps.newHashMap(); - if (progressFile.exists() && progressFile.isFile()) { - DefaultDeserializer deserializer = new DefaultDeserializer(Thread.currentThread().getContextClassLoader()); - try (FileInputStream fis = new FileInputStream(progressFile)) { - byte[] b = ByteStreams.toByteArray(fis); - storage = (Map) deserializer.deserialize(new ByteArrayInputStream(b)); - } - } - return storage; + private int challengesSolved(UserTracker userTracker) { + List challenges = Lists.newArrayList("Challenge1", "Challenge2", "Challenge3", "Challenge4", "Challenge5"); + List challengeTrackers = challenges.stream() + .map(c -> userTracker.getLessonTracker(c)) + .filter(l -> l.isPresent()).map(l -> l.get()).collect(Collectors.toList()); + return challengeTrackers.size(); } - } diff --git a/webgoat-container/src/main/java/org/owasp/webgoat/users/UserRepository.java b/webgoat-container/src/main/java/org/owasp/webgoat/users/UserRepository.java index d7d85db54..ae2f1063e 100644 --- a/webgoat-container/src/main/java/org/owasp/webgoat/users/UserRepository.java +++ b/webgoat-container/src/main/java/org/owasp/webgoat/users/UserRepository.java @@ -1,13 +1,12 @@ package org.owasp.webgoat.users; -import org.owasp.webgoat.session.WebGoatUser; -import org.springframework.data.repository.CrudRepository; +import org.springframework.data.mongodb.repository.MongoRepository; /** * @author nbaars * @since 3/19/17. */ -public interface UserRepository extends CrudRepository { +public interface UserRepository extends MongoRepository { WebGoatUser findByUsername(String username); } diff --git a/webgoat-container/src/main/java/org/owasp/webgoat/users/UserService.java b/webgoat-container/src/main/java/org/owasp/webgoat/users/UserService.java index 15a6cf6d4..7a1175c45 100644 --- a/webgoat-container/src/main/java/org/owasp/webgoat/users/UserService.java +++ b/webgoat-container/src/main/java/org/owasp/webgoat/users/UserService.java @@ -1,7 +1,6 @@ package org.owasp.webgoat.users; import lombok.AllArgsConstructor; -import org.owasp.webgoat.session.WebGoatUser; import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.security.core.userdetails.UsernameNotFoundException; import org.springframework.stereotype.Service; @@ -15,6 +14,7 @@ import org.springframework.stereotype.Service; public class UserService implements UserDetailsService { private final UserRepository userRepository; + private final UserTrackerRepository userTrackerRepository; @Override public WebGoatUser loadUserByUsername(String username) throws UsernameNotFoundException { @@ -29,5 +29,6 @@ public class UserService implements UserDetailsService { public void addUser(String username, String password) { userRepository.save(new WebGoatUser(username, password)); + userTrackerRepository.save(new UserTracker(username)); } } diff --git a/webgoat-container/src/main/java/org/owasp/webgoat/users/UserTracker.java b/webgoat-container/src/main/java/org/owasp/webgoat/users/UserTracker.java new file mode 100644 index 000000000..c139d2571 --- /dev/null +++ b/webgoat-container/src/main/java/org/owasp/webgoat/users/UserTracker.java @@ -0,0 +1,119 @@ + +package org.owasp.webgoat.users; + +import com.google.common.collect.Lists; +import lombok.extern.slf4j.Slf4j; +import org.owasp.webgoat.lessons.AbstractLesson; +import org.owasp.webgoat.lessons.Assignment; +import org.springframework.data.annotation.Id; + +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.stream.Collectors; + + +/** + * ************************************************************************************************ + *

+ *

+ * 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 Bruce Mayhew WebGoat + * @version $Id: $Id + * @since October 29, 2003 + */ +@Slf4j +public class UserTracker { + + @Id + private final String user; + private List lessonTrackers = Lists.newArrayList(); + + public UserTracker(final String user) { + this.user = user; + } + + /** + * Returns an existing lesson tracker or create a new one based on the lesson + * + * @param lesson the lesson + * @return a lesson tracker created if not already present + */ + public LessonTracker getLessonTracker(AbstractLesson lesson) { + Optional lessonTracker = lessonTrackers + .stream().filter(l -> l.getLessonName().equals(lesson.getId())).findFirst(); + if (!lessonTracker.isPresent()) { + LessonTracker newLessonTracker = new LessonTracker(lesson); + lessonTrackers.add(newLessonTracker); + return newLessonTracker; + } else { + return lessonTracker.get(); + } + } + + /** + * Query method for finding a specific lesson tracker based on id + * + * @param id the id of the lesson + * @return optional due to the fact we can only create a lesson tracker based on a lesson + */ + public Optional getLessonTracker(String id) { + return lessonTrackers.stream().filter(l -> l.getLessonName().equals(id)).findFirst(); + } + + public void assignmentSolved(AbstractLesson lesson, String assignmentName) { + LessonTracker lessonTracker = getLessonTracker(lesson); + lessonTracker.incrementAttempts(); + lessonTracker.assignmentSolved(assignmentName); + } + + public void assignmentFailed(AbstractLesson lesson) { + LessonTracker lessonTracker = getLessonTracker(lesson); + lessonTracker.incrementAttempts(); + } + + public void reset(AbstractLesson al) { + LessonTracker lessonTracker = getLessonTracker(al); + lessonTracker.reset(); + } + + public int numberOfLessonsSolved() { + int numberOfLessonsSolved = 0; + for (LessonTracker lessonTracker : lessonTrackers) { + if (lessonTracker.isLessonSolved()) { + numberOfLessonsSolved = numberOfLessonsSolved + 1; + } + } + return numberOfLessonsSolved; + } + + public int numberOfAssignmentsSolved() { + int numberOfAssignmentsSolved = 0; + for (LessonTracker lessonTracker : lessonTrackers) { + Map lessonOverview = lessonTracker.getLessonOverview(); + numberOfAssignmentsSolved = lessonOverview.values().stream().filter(b -> b).collect(Collectors.counting()).intValue(); + } + return numberOfAssignmentsSolved; + } +} diff --git a/webgoat-container/src/main/java/org/owasp/webgoat/users/UserTrackerRepository.java b/webgoat-container/src/main/java/org/owasp/webgoat/users/UserTrackerRepository.java new file mode 100644 index 000000000..f915154cb --- /dev/null +++ b/webgoat-container/src/main/java/org/owasp/webgoat/users/UserTrackerRepository.java @@ -0,0 +1,12 @@ +package org.owasp.webgoat.users; + +import org.springframework.data.mongodb.repository.MongoRepository; + +/** + * @author nbaars + * @since 4/30/17. + */ +public interface UserTrackerRepository extends MongoRepository { + + +} diff --git a/webgoat-container/src/main/java/org/owasp/webgoat/session/WebGoatUser.java b/webgoat-container/src/main/java/org/owasp/webgoat/users/WebGoatUser.java similarity index 91% rename from webgoat-container/src/main/java/org/owasp/webgoat/session/WebGoatUser.java rename to webgoat-container/src/main/java/org/owasp/webgoat/users/WebGoatUser.java index 381617386..8b3c7c88c 100644 --- a/webgoat-container/src/main/java/org/owasp/webgoat/session/WebGoatUser.java +++ b/webgoat-container/src/main/java/org/owasp/webgoat/users/WebGoatUser.java @@ -1,14 +1,13 @@ -package org.owasp.webgoat.session; +package org.owasp.webgoat.users; import lombok.Getter; +import org.springframework.data.annotation.Id; +import org.springframework.data.annotation.Transient; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.authority.SimpleGrantedAuthority; import org.springframework.security.core.userdetails.User; import org.springframework.security.core.userdetails.UserDetails; -import javax.persistence.Entity; -import javax.persistence.Id; -import javax.persistence.Transient; import java.util.Collection; import java.util.Collections; @@ -17,7 +16,6 @@ import java.util.Collections; * @since 3/19/17. */ @Getter -@Entity public class WebGoatUser implements UserDetails { public static final String ROLE_USER = "WEBGOAT_USER"; diff --git a/webgoat-container/src/main/resources/application.properties b/webgoat-container/src/main/resources/application.properties index c326c44cb..f582a16e6 100644 --- a/webgoat-container/src/main/resources/application.properties +++ b/webgoat-container/src/main/resources/application.properties @@ -29,6 +29,9 @@ webgoat.database.driver=org.hsqldb.jdbcDriver webgoat.database.connection.string=jdbc:hsqldb:mem:{USER} webgoat.default.language=en +spring.data.mongodb.database=webgoat +spring.mongodb.embedded.storage.databaseDir=${webgoat.user.directory}/mongodb/ + liquibase.change-log=classpath:db/changelog/db.changelog-master.xml spring.datasource.url=jdbc:hsqldb:file:${user.home}/.webgoat/WebGoatDatabase;hsqldb.write_delay=false diff --git a/webgoat-container/src/test/java/org/owasp/webgoat/assignments/AssignmentEndpointTest.java b/webgoat-container/src/test/java/org/owasp/webgoat/assignments/AssignmentEndpointTest.java index 787711c67..1f9628fb0 100644 --- a/webgoat-container/src/test/java/org/owasp/webgoat/assignments/AssignmentEndpointTest.java +++ b/webgoat-container/src/test/java/org/owasp/webgoat/assignments/AssignmentEndpointTest.java @@ -30,18 +30,24 @@ import org.owasp.webgoat.i18n.Language; import org.owasp.webgoat.i18n.Messages; import org.owasp.webgoat.i18n.PluginMessages; import org.owasp.webgoat.session.UserSessionData; -import org.owasp.webgoat.session.UserTracker; +import org.owasp.webgoat.users.UserTracker; import org.owasp.webgoat.session.WebSession; +import org.owasp.webgoat.users.UserTrackerRepository; import org.springframework.test.util.ReflectionTestUtils; import org.springframework.web.servlet.i18n.FixedLocaleResolver; import java.util.Locale; +import static org.mockito.Matchers.anyString; +import static org.mockito.Mockito.when; + public class AssignmentEndpointTest { @Mock protected UserTracker userTracker; @Mock + protected UserTrackerRepository userTrackerRepository; + @Mock protected WebSession webSession; @Mock protected UserSessionData userSessionData; @@ -56,7 +62,8 @@ public class AssignmentEndpointTest { public void init(AssignmentEndpoint a) { messages.setBasenames("classpath:/i18n/messages", "classpath:/i18n/WebGoatLabels"); - ReflectionTestUtils.setField(a, "userTracker", userTracker); + when(userTrackerRepository.findOne(anyString())).thenReturn(userTracker); + ReflectionTestUtils.setField(a, "userTrackerRepository", userTrackerRepository); ReflectionTestUtils.setField(a, "userSessionData", userSessionData); ReflectionTestUtils.setField(a, "webSession", webSession); ReflectionTestUtils.setField(a, "messages", pluginMessages); diff --git a/webgoat-container/src/test/java/org/owasp/webgoat/service/LessonMenuServiceTest.java b/webgoat-container/src/test/java/org/owasp/webgoat/service/LessonMenuServiceTest.java index 17a51a948..d71126d82 100644 --- a/webgoat-container/src/test/java/org/owasp/webgoat/service/LessonMenuServiceTest.java +++ b/webgoat-container/src/test/java/org/owasp/webgoat/service/LessonMenuServiceTest.java @@ -8,15 +8,19 @@ import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.Mockito; import org.mockito.runners.MockitoJUnitRunner; +import org.owasp.webgoat.lessons.AbstractLesson; import org.owasp.webgoat.lessons.Category; import org.owasp.webgoat.lessons.NewLesson; import org.owasp.webgoat.session.Course; -import org.owasp.webgoat.session.LessonTracker; -import org.owasp.webgoat.session.UserTracker; +import org.owasp.webgoat.session.WebSession; +import org.owasp.webgoat.users.LessonTracker; +import org.owasp.webgoat.users.UserTracker; +import org.owasp.webgoat.users.UserTrackerRepository; import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; import static org.mockito.Matchers.any; +import static org.mockito.Matchers.anyString; import static org.mockito.Mockito.when; import static org.owasp.webgoat.service.LessonMenuService.URL_LESSONMENU_MVC; import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; @@ -35,11 +39,15 @@ public class LessonMenuServiceTest { private Course course; @Mock private UserTracker userTracker; + @Mock + private UserTrackerRepository userTrackerRepository; + @Mock + private WebSession webSession; private MockMvc mockMvc; @Before public void setup() { - this.mockMvc = standaloneSetup(new LessonMenuService(course, userTracker)).build(); + this.mockMvc = standaloneSetup(new LessonMenuService(course, webSession, userTrackerRepository)).build(); } @Test @@ -54,7 +62,8 @@ public class LessonMenuServiceTest { when(lessonTracker.isLessonSolved()).thenReturn(false); when(course.getLessons(any())).thenReturn(Lists.newArrayList(l1, l2)); when(course.getCategories()).thenReturn(Lists.newArrayList(Category.ACCESS_CONTROL)); - when(userTracker.getLessonTracker(any())).thenReturn(lessonTracker); + when(userTracker.getLessonTracker(any(AbstractLesson.class))).thenReturn(lessonTracker); + when(userTrackerRepository.findOne(anyString())).thenReturn(userTracker); mockMvc.perform(MockMvcRequestBuilders.get(URL_LESSONMENU_MVC)) .andExpect(status().isOk()) @@ -71,7 +80,9 @@ public class LessonMenuServiceTest { when(lessonTracker.isLessonSolved()).thenReturn(true); when(course.getLessons(any())).thenReturn(Lists.newArrayList(l1)); when(course.getCategories()).thenReturn(Lists.newArrayList(Category.ACCESS_CONTROL)); - when(userTracker.getLessonTracker(any())).thenReturn(lessonTracker); + when(userTracker.getLessonTracker(any(AbstractLesson.class))).thenReturn(lessonTracker); + when(userTrackerRepository.findOne(anyString())).thenReturn(userTracker); + mockMvc.perform(MockMvcRequestBuilders.get(URL_LESSONMENU_MVC)) .andExpect(status().isOk()).andDo(print()) diff --git a/webgoat-container/src/test/java/org/owasp/webgoat/service/LessonProgressServiceTest.java b/webgoat-container/src/test/java/org/owasp/webgoat/service/LessonProgressServiceTest.java index b89d4fa23..2ca3e9169 100644 --- a/webgoat-container/src/test/java/org/owasp/webgoat/service/LessonProgressServiceTest.java +++ b/webgoat-container/src/test/java/org/owasp/webgoat/service/LessonProgressServiceTest.java @@ -8,9 +8,10 @@ import org.mockito.Mock; import org.mockito.runners.MockitoJUnitRunner; import org.owasp.webgoat.lessons.AbstractLesson; import org.owasp.webgoat.lessons.Assignment; -import org.owasp.webgoat.session.LessonTracker; -import org.owasp.webgoat.session.UserTracker; import org.owasp.webgoat.session.WebSession; +import org.owasp.webgoat.users.LessonTracker; +import org.owasp.webgoat.users.UserTracker; +import org.owasp.webgoat.users.UserTrackerRepository; import org.springframework.http.MediaType; import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; @@ -18,6 +19,7 @@ import org.springframework.test.web.servlet.setup.MockMvcBuilders; import static org.hamcrest.CoreMatchers.is; import static org.mockito.Matchers.any; +import static org.mockito.Matchers.anyString; import static org.mockito.Mockito.when; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; @@ -63,15 +65,18 @@ public class LessonProgressServiceTest { @Mock private LessonTracker lessonTracker; @Mock + private UserTrackerRepository userTrackerRepository; + @Mock private WebSession websession; @Before public void setup() { Assignment assignment = new Assignment("test", "test"); - when(userTracker.getLessonTracker(any())).thenReturn(lessonTracker); + when(userTrackerRepository.findOne(anyString())).thenReturn(userTracker); + when(userTracker.getLessonTracker(any(AbstractLesson.class))).thenReturn(lessonTracker); when(websession.getCurrentLesson()).thenReturn(lesson); when(lessonTracker.getLessonOverview()).thenReturn(Maps.newHashMap(assignment, true)); - this.mockMvc = MockMvcBuilders.standaloneSetup(new LessonProgressService(userTracker, websession)).build(); + this.mockMvc = MockMvcBuilders.standaloneSetup(new LessonProgressService(userTrackerRepository, websession)).build(); } @Test diff --git a/webgoat-container/src/test/java/org/owasp/webgoat/service/ReportCardServiceTest.java b/webgoat-container/src/test/java/org/owasp/webgoat/service/ReportCardServiceTest.java index bd3685d86..e1b6f639f 100644 --- a/webgoat-container/src/test/java/org/owasp/webgoat/service/ReportCardServiceTest.java +++ b/webgoat-container/src/test/java/org/owasp/webgoat/service/ReportCardServiceTest.java @@ -8,14 +8,17 @@ import org.mockito.Mock; import org.mockito.runners.MockitoJUnitRunner; import org.owasp.webgoat.lessons.AbstractLesson; import org.owasp.webgoat.session.Course; -import org.owasp.webgoat.session.LessonTracker; -import org.owasp.webgoat.session.UserTracker; +import org.owasp.webgoat.session.WebSession; +import org.owasp.webgoat.users.LessonTracker; +import org.owasp.webgoat.users.UserTracker; +import org.owasp.webgoat.users.UserTrackerRepository; import org.springframework.security.test.context.support.WithMockUser; import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; import static org.hamcrest.CoreMatchers.is; import static org.mockito.Matchers.any; +import static org.mockito.Matchers.anyString; import static org.mockito.Mockito.when; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; @@ -33,10 +36,14 @@ public class ReportCardServiceTest { private AbstractLesson lesson; @Mock private LessonTracker lessonTracker; + @Mock + private UserTrackerRepository userTrackerRepository; + @Mock + private WebSession websession; @Before public void setup() { - this.mockMvc = standaloneSetup(new ReportCardService(userTracker, course)).build(); + this.mockMvc = standaloneSetup(new ReportCardService(websession, userTrackerRepository, course)).build(); } @Test @@ -46,7 +53,8 @@ public class ReportCardServiceTest { when(course.getTotalOfLessons()).thenReturn(1); when(course.getTotalOfAssignments()).thenReturn(10); when(course.getLessons()).thenReturn(Lists.newArrayList(lesson)); - when(userTracker.getLessonTracker(any())).thenReturn(lessonTracker); + when(userTrackerRepository.findOne(anyString())).thenReturn(userTracker); + when(userTracker.getLessonTracker(any(AbstractLesson.class))).thenReturn(lessonTracker); mockMvc.perform(MockMvcRequestBuilders.get("/service/reportcard.mvc")) .andExpect(status().isOk()) .andExpect(jsonPath("$.totalNumberOfLessons", is(1))) diff --git a/webgoat-container/src/test/java/org/owasp/webgoat/session/LessonTrackerTest.java b/webgoat-container/src/test/java/org/owasp/webgoat/session/LessonTrackerTest.java index 9a24193d4..4f11569ce 100644 --- a/webgoat-container/src/test/java/org/owasp/webgoat/session/LessonTrackerTest.java +++ b/webgoat-container/src/test/java/org/owasp/webgoat/session/LessonTrackerTest.java @@ -4,6 +4,7 @@ import com.google.common.collect.Lists; import org.junit.Test; import org.owasp.webgoat.lessons.AbstractLesson; import org.owasp.webgoat.lessons.Assignment; +import org.owasp.webgoat.users.LessonTracker; import java.util.List; import java.util.Map; 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 deleted file mode 100644 index 209c19a31..000000000 --- a/webgoat-container/src/test/java/org/owasp/webgoat/session/UserTrackerTest.java +++ /dev/null @@ -1,105 +0,0 @@ -package org.owasp.webgoat.session; - -import com.google.common.collect.Lists; -import org.junit.Before; -import org.junit.Test; -import org.owasp.webgoat.lessons.AbstractLesson; -import org.owasp.webgoat.lessons.Assignment; - -import java.io.File; -import java.io.IOException; -import java.util.UUID; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.Mockito.mock; -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 lesson = mock(AbstractLesson.class); - when(lesson.getAssignments()).thenReturn(Lists.newArrayList(new Assignment("assignment", "assignment"))); - userTracker.getLessonTracker(lesson); - userTracker.assignmentSolved(lesson, lesson.getAssignments().get(0).getName()); - - userTracker = new UserTracker(home.getParent(), "test"); - userTracker.load(); - assertThat(userTracker.getLessonTracker(lesson).isLessonSolved()).isTrue(); - } - - @Test - public void assignmentFailedShouldIncrementAttempts() { - UserTracker userTracker = new UserTracker(home.getParent(), UUID.randomUUID().toString()); - AbstractLesson lesson = mock(AbstractLesson.class); - when(lesson.getAssignments()).thenReturn(Lists.newArrayList(new Assignment("assignment", "assignment"))); - userTracker.getLessonTracker(lesson); - userTracker.assignmentFailed(lesson); - userTracker.assignmentFailed(lesson); - - assertThat(userTracker.getLessonTracker(lesson).getNumberOfAttempts()).isEqualTo(2); - } - - @Test - public void resetShouldClearSolvedAssignment() { - UserTracker userTracker = new UserTracker(home.getParent(), "test"); - AbstractLesson lesson = mock(AbstractLesson.class); - when(lesson.getAssignments()).thenReturn(Lists.newArrayList(new Assignment("assignment", "assignment"))); - userTracker.getLessonTracker(lesson); - userTracker.assignmentSolved(lesson, "assignment"); - - assertThat(userTracker.getLessonTracker(lesson).isLessonSolved()).isTrue(); - userTracker.reset(lesson); - assertThat(userTracker.getLessonTracker(lesson).isLessonSolved()).isFalse(); - } - - @Test - public void totalAssignmentsSolved() { - UserTracker userTracker = new UserTracker(home.getParent(), "test"); - AbstractLesson lesson = mock(AbstractLesson.class); - when(lesson.getAssignments()).thenReturn(Lists.newArrayList(new Assignment("assignment", "assignment"))); - userTracker.getLessonTracker(lesson); - userTracker.assignmentSolved(lesson, "assignment"); - - assertThat(userTracker.numberOfAssignmentsSolved()).isEqualTo(1); - assertThat(userTracker.numberOfLessonsSolved()).isEqualTo(1); - } -} diff --git a/webgoat-container/src/test/java/org/owasp/webgoat/users/UserServiceTest.java b/webgoat-container/src/test/java/org/owasp/webgoat/users/UserServiceTest.java index 15606b7e8..b4128f79a 100644 --- a/webgoat-container/src/test/java/org/owasp/webgoat/users/UserServiceTest.java +++ b/webgoat-container/src/test/java/org/owasp/webgoat/users/UserServiceTest.java @@ -14,11 +14,14 @@ public class UserServiceTest { @Mock private UserRepository userRepository; + @Mock + private UserTrackerRepository userTrackerRepository; + @Test(expected = UsernameNotFoundException.class) public void shouldThrowExceptionWhenUserIsNotFound() { when(userRepository.findByUsername(any())).thenReturn(null); - UserService userService = new UserService(userRepository); + UserService userService = new UserService(userRepository, userTrackerRepository); userService.loadUserByUsername("unknown"); } diff --git a/webgoat-container/src/test/java/org/owasp/webgoat/users/UserValidatorTest.java b/webgoat-container/src/test/java/org/owasp/webgoat/users/UserValidatorTest.java index 7968ed30f..c2f767e44 100644 --- a/webgoat-container/src/test/java/org/owasp/webgoat/users/UserValidatorTest.java +++ b/webgoat-container/src/test/java/org/owasp/webgoat/users/UserValidatorTest.java @@ -4,7 +4,6 @@ import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.runners.MockitoJUnitRunner; -import org.owasp.webgoat.session.WebGoatUser; import org.springframework.validation.BeanPropertyBindingResult; import org.springframework.validation.Errors; diff --git a/webgoat-lessons/challenge/src/main/java/org/owasp/webgoat/plugin/Flag.java b/webgoat-lessons/challenge/src/main/java/org/owasp/webgoat/plugin/Flag.java index 159e91b8d..1cf13301c 100644 --- a/webgoat-lessons/challenge/src/main/java/org/owasp/webgoat/plugin/Flag.java +++ b/webgoat-lessons/challenge/src/main/java/org/owasp/webgoat/plugin/Flag.java @@ -3,8 +3,10 @@ package org.owasp.webgoat.plugin; import com.google.common.collect.Maps; import lombok.AllArgsConstructor; import lombok.Getter; +import lombok.extern.slf4j.Slf4j; import org.owasp.webgoat.assignments.Endpoint; -import org.owasp.webgoat.session.UserTracker; +import org.owasp.webgoat.users.UserTracker; +import org.owasp.webgoat.users.UserTrackerRepository; import org.owasp.webgoat.session.WebSession; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; @@ -23,11 +25,12 @@ import java.util.stream.IntStream; * @author nbaars * @since 3/23/17. */ +@Slf4j public class Flag extends Endpoint { public static final Map FLAGS = Maps.newHashMap(); @Autowired - private UserTracker userTracker; + private UserTrackerRepository userTrackerRepository; @Autowired private WebSession webSession; @@ -39,7 +42,8 @@ public class Flag extends Endpoint { @PostConstruct public void initFlags() { - IntStream.range(1, 5).forEach(i -> FLAGS.put(i, UUID.randomUUID().toString())); + IntStream.range(1, 6).forEach(i -> FLAGS.put(i, UUID.randomUUID().toString())); + FLAGS.entrySet().stream().forEach(e -> log.debug("Flag {} {}", e.getKey(), e.getValue())); } @Override @@ -50,6 +54,10 @@ public class Flag extends Endpoint { @RequestMapping(method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE) @ResponseStatus(HttpStatus.OK) public void postFlag(@RequestParam String flag) { + UserTracker userTracker = userTrackerRepository.findOne(webSession.getUserName()); + if (userTracker == null) { + userTracker = new UserTracker(webSession.getUserName()); + } String currentChallenge = webSession.getCurrentLesson().getName(); int challengeNumber = Integer.valueOf(currentChallenge.substring(currentChallenge.length() - 1, currentChallenge.length())); String expectedFlag = FLAGS.get(challengeNumber); @@ -58,6 +66,7 @@ public class Flag extends Endpoint { } else { userTracker.assignmentFailed(webSession.getCurrentLesson()); } + userTrackerRepository.save(userTracker); } }