Fix report card (#1845)

* fix: report card

Fix and simplify calculation of the number of assignments a user solved.
Rename `UserTracker` to `UserProgress`
Rename `LessonTracker` to `LessonProgress`
Rename tables in database
This commit is contained in:
Nanne Baars 2024-07-09 20:07:09 +02:00 committed by GitHub
parent 1531987da5
commit a0b6decf34
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
27 changed files with 237 additions and 248 deletions

View File

@ -11,7 +11,7 @@ jobs:
strategy: strategy:
matrix: matrix:
os: [ ubuntu-latest, windows-latest, macos-latest ] os: [ ubuntu-latest, windows-latest, macos-latest ]
java-version: [ 17, 21 ] java-version: [ 21 ]
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
- name: Set up JDK ${{ matrix.java-version }} - name: Set up JDK ${{ matrix.java-version }}

View File

@ -14,8 +14,10 @@ jobs:
build: build:
runs-on: ${{ matrix.os }} runs-on: ${{ matrix.os }}
strategy: strategy:
fail-fast: true
matrix: matrix:
os: [ ubuntu-latest, windows-latest, macos-latest ] os: [ windows-latest, ubuntu-latest, macos-13 ]
max-parallel: 1
steps: steps:
- uses: actions/checkout@v4.1.6 - uses: actions/checkout@v4.1.6
- name: Set up JDK 21 - name: Set up JDK 21
@ -31,16 +33,4 @@ jobs:
key: ${{ runner.os }}-m2-${{ hashFiles('**/pom.xml') }} key: ${{ runner.os }}-m2-${{ hashFiles('**/pom.xml') }}
restore-keys: ${{ runner.os }}-m2- restore-keys: ${{ runner.os }}-m2-
- name: Build with Maven - name: Build with Maven
run: | run: mvn --no-transfer-progress verify
if [ "$RUNNER_OS" == "macOS" ]; then
# Make "localhost" DNS entry available; see https://github.com/actions/runner-images/issues/6383
# sudo networksetup -setdnsservers Ethernet 9.9.9.9
echo -e "$(ipconfig getifaddr en0) $(hostname -f) $(hostname -s)" | sudo tee -a /etc/hosts
echo `sudo lsof -PiTCP -sTCP:LISTEN`
cat /etc/hosts
mvn --no-transfer-progress verify -DskipTests -DwaittimeForServerStart=150
# skip tests on macos, takes too long with the current runners
else
mvn --no-transfer-progress verify -DwaittimeForServerStart=30
fi
shell: bash

View File

View File

@ -669,10 +669,6 @@
<plugin> <plugin>
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId> <artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>17</source>
<target>17</target>
</configuration>
</plugin> </plugin>
</plugins> </plugins>
</build> </build>

View File

@ -23,8 +23,8 @@
package org.owasp.webgoat.container.assignments; package org.owasp.webgoat.container.assignments;
import org.owasp.webgoat.container.session.WebSession; import org.owasp.webgoat.container.session.WebSession;
import org.owasp.webgoat.container.users.UserTracker; import org.owasp.webgoat.container.users.UserProgress;
import org.owasp.webgoat.container.users.UserTrackerRepository; import org.owasp.webgoat.container.users.UserProgressRepository;
import org.springframework.core.MethodParameter; import org.springframework.core.MethodParameter;
import org.springframework.http.MediaType; import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter; import org.springframework.http.converter.HttpMessageConverter;
@ -36,11 +36,11 @@ import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;
@RestControllerAdvice @RestControllerAdvice
public class LessonTrackerInterceptor implements ResponseBodyAdvice<Object> { public class LessonTrackerInterceptor implements ResponseBodyAdvice<Object> {
private UserTrackerRepository userTrackerRepository; private UserProgressRepository userTrackerRepository;
private WebSession webSession; private WebSession webSession;
public LessonTrackerInterceptor( public LessonTrackerInterceptor(
UserTrackerRepository userTrackerRepository, WebSession webSession) { UserProgressRepository userTrackerRepository, WebSession webSession) {
this.userTrackerRepository = userTrackerRepository; this.userTrackerRepository = userTrackerRepository;
this.webSession = webSession; this.webSession = webSession;
} }
@ -66,9 +66,9 @@ public class LessonTrackerInterceptor implements ResponseBodyAdvice<Object> {
} }
protected AttackResult trackProgress(AttackResult attackResult) { protected AttackResult trackProgress(AttackResult attackResult) {
UserTracker userTracker = userTrackerRepository.findByUser(webSession.getUserName()); UserProgress userTracker = userTrackerRepository.findByUser(webSession.getUserName());
if (userTracker == null) { if (userTracker == null) {
userTracker = new UserTracker(webSession.getUserName()); userTracker = new UserProgress(webSession.getUserName());
} }
if (attackResult.assignmentSolved()) { if (attackResult.assignmentSolved()) {
userTracker.assignmentSolved(webSession.getCurrentLesson(), attackResult.getAssignment()); userTracker.assignmentSolved(webSession.getCurrentLesson(), attackResult.getAssignment());

View File

@ -54,7 +54,7 @@ public class Assignment {
@Transient private List<String> hints; @Transient private List<String> hints;
private Assignment() { protected Assignment() {
// Hibernate // Hibernate
} }

View File

@ -0,0 +1,3 @@
package org.owasp.webgoat.container.report;
record LessonStatistics(String name, boolean solved, int numberOfAttempts) {}

View File

@ -0,0 +1,93 @@
/**
* *************************************************************************************************
*
* <p>
*
* <p>This file is part of WebGoat, an Open Web Application Security Project utility. For details,
* please see http://www.owasp.org/
*
* <p>Copyright (c) 2002 - 2014 Bruce Mayhew
*
* <p>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.
*
* <p>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.
*
* <p>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.
*
* <p>Getting Source ==============
*
* <p>Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository
* for free software projects.
*/
package org.owasp.webgoat.container.report;
import java.util.List;
import org.owasp.webgoat.container.i18n.PluginMessages;
import org.owasp.webgoat.container.session.Course;
import org.owasp.webgoat.container.session.WebSession;
import org.owasp.webgoat.container.users.UserProgressRepository;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class ReportCardController {
private final WebSession webSession;
private final UserProgressRepository userProgressRepository;
private final Course course;
private final PluginMessages pluginMessages;
public ReportCardController(
WebSession webSession,
UserProgressRepository userProgressRepository,
Course course,
PluginMessages pluginMessages) {
this.webSession = webSession;
this.userProgressRepository = userProgressRepository;
this.course = course;
this.pluginMessages = pluginMessages;
}
/**
* 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() {
var userProgress = userProgressRepository.findByUser(webSession.getUserName());
var lessonStatistics =
course.getLessons().stream()
.map(
lesson -> {
var lessonTracker = userProgress.getLessonProgress(lesson);
return new LessonStatistics(
pluginMessages.getMessage(lesson.getTitle()),
lessonTracker.isLessonSolved(),
lessonTracker.getNumberOfAttempts());
})
.toList();
return new ReportCard(
course.getTotalOfLessons(),
course.getTotalOfAssignments(),
userProgress.numberOfAssignmentsSolved(),
userProgress.numberOfLessonsSolved(),
lessonStatistics);
}
private record ReportCard(
int totalNumberOfLessons,
int totalNumberOfAssignments,
long numberOfAssignmentsSolved,
long numberOfLessonsSolved,
List<LessonStatistics> lessonStatistics) {}
private record LessonStatistics(String name, boolean solved, int numberOfAttempts) {}
}

View File

@ -39,9 +39,9 @@ import org.owasp.webgoat.container.lessons.LessonMenuItem;
import org.owasp.webgoat.container.lessons.LessonMenuItemType; import org.owasp.webgoat.container.lessons.LessonMenuItemType;
import org.owasp.webgoat.container.session.Course; import org.owasp.webgoat.container.session.Course;
import org.owasp.webgoat.container.session.WebSession; import org.owasp.webgoat.container.session.WebSession;
import org.owasp.webgoat.container.users.LessonTracker; import org.owasp.webgoat.container.users.LessonProgress;
import org.owasp.webgoat.container.users.UserTracker; import org.owasp.webgoat.container.users.UserProgress;
import org.owasp.webgoat.container.users.UserTrackerRepository; import org.owasp.webgoat.container.users.UserProgressRepository;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller; import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
@ -60,7 +60,7 @@ public class LessonMenuService {
public static final String URL_LESSONMENU_MVC = "/service/lessonmenu.mvc"; public static final String URL_LESSONMENU_MVC = "/service/lessonmenu.mvc";
private final Course course; private final Course course;
private final WebSession webSession; private final WebSession webSession;
private UserTrackerRepository userTrackerRepository; private UserProgressRepository userTrackerRepository;
@Value("#{'${exclude.categories}'.split(',')}") @Value("#{'${exclude.categories}'.split(',')}")
private List<String> excludeCategories; private List<String> excludeCategories;
@ -77,7 +77,7 @@ public class LessonMenuService {
public @ResponseBody List<LessonMenuItem> showLeftNav() { public @ResponseBody List<LessonMenuItem> showLeftNav() {
List<LessonMenuItem> menu = new ArrayList<>(); List<LessonMenuItem> menu = new ArrayList<>();
List<Category> categories = course.getCategories(); List<Category> categories = course.getCategories();
UserTracker userTracker = userTrackerRepository.findByUser(webSession.getUserName()); UserProgress userTracker = userTrackerRepository.findByUser(webSession.getUserName());
for (Category category : categories) { for (Category category : categories) {
if (excludeCategories.contains(category.name())) { if (excludeCategories.contains(category.name())) {
@ -97,7 +97,7 @@ public class LessonMenuService {
lessonItem.setName(lesson.getTitle()); lessonItem.setName(lesson.getTitle());
lessonItem.setLink(lesson.getLink()); lessonItem.setLink(lesson.getLink());
lessonItem.setType(LessonMenuItemType.LESSON); lessonItem.setType(LessonMenuItemType.LESSON);
LessonTracker lessonTracker = userTracker.getLessonTracker(lesson); LessonProgress lessonTracker = userTracker.getLessonProgress(lesson);
boolean lessonSolved = lessonCompleted(lessonTracker.getLessonOverview(), lesson); boolean lessonSolved = lessonCompleted(lessonTracker.getLessonOverview(), lesson);
lessonItem.setComplete(lessonSolved); lessonItem.setComplete(lessonSolved);
categoryItem.addChild(lessonItem); categoryItem.addChild(lessonItem);

View File

@ -6,7 +6,7 @@ import lombok.Getter;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import org.owasp.webgoat.container.lessons.Assignment; import org.owasp.webgoat.container.lessons.Assignment;
import org.owasp.webgoat.container.session.WebSession; import org.owasp.webgoat.container.session.WebSession;
import org.owasp.webgoat.container.users.UserTrackerRepository; import org.owasp.webgoat.container.users.UserProgressRepository;
import org.springframework.stereotype.Controller; import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.bind.annotation.ResponseBody;
@ -20,7 +20,7 @@ import org.springframework.web.bind.annotation.ResponseBody;
@RequiredArgsConstructor @RequiredArgsConstructor
public class LessonProgressService { public class LessonProgressService {
private final UserTrackerRepository userTrackerRepository; private final UserProgressRepository userTrackerRepository;
private final WebSession webSession; private final WebSession webSession;
/** /**
@ -36,7 +36,7 @@ public class LessonProgressService {
var currentLesson = webSession.getCurrentLesson(); var currentLesson = webSession.getCurrentLesson();
if (currentLesson != null) { if (currentLesson != null) {
var lessonTracker = userTracker.getLessonTracker(currentLesson); var lessonTracker = userTracker.getLessonProgress(currentLesson);
return lessonTracker.getLessonOverview().entrySet().stream() return lessonTracker.getLessonOverview().entrySet().stream()
.map(entry -> new LessonOverview(entry.getKey(), entry.getValue())) .map(entry -> new LessonOverview(entry.getKey(), entry.getValue()))
.toList(); .toList();

View File

@ -1,105 +0,0 @@
/**
* *************************************************************************************************
*
* <p>
*
* <p>This file is part of WebGoat, an Open Web Application Security Project utility. For details,
* please see http://www.owasp.org/
*
* <p>Copyright (c) 2002 - 2014 Bruce Mayhew
*
* <p>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.
*
* <p>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.
*
* <p>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.
*
* <p>Getting Source ==============
*
* <p>Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository
* for free software projects.
*/
package org.owasp.webgoat.container.service;
import java.util.ArrayList;
import java.util.List;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.Setter;
import org.owasp.webgoat.container.i18n.PluginMessages;
import org.owasp.webgoat.container.lessons.Lesson;
import org.owasp.webgoat.container.session.Course;
import org.owasp.webgoat.container.session.WebSession;
import org.owasp.webgoat.container.users.LessonTracker;
import org.owasp.webgoat.container.users.UserTracker;
import org.owasp.webgoat.container.users.UserTrackerRepository;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ResponseBody;
/**
* ReportCardService
*
* @author nbaars
* @version $Id: $Id
*/
@Controller
@AllArgsConstructor
public class ReportCardService {
private final WebSession webSession;
private final UserTrackerRepository userTrackerRepository;
private final Course course;
private final PluginMessages pluginMessages;
/**
* 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() {
final ReportCard reportCard = new ReportCard();
reportCard.setTotalNumberOfLessons(course.getTotalOfLessons());
reportCard.setTotalNumberOfAssignments(course.getTotalOfAssignments());
UserTracker userTracker = userTrackerRepository.findByUser(webSession.getUserName());
reportCard.setNumberOfAssignmentsSolved(userTracker.numberOfAssignmentsSolved());
reportCard.setNumberOfLessonsSolved(userTracker.numberOfLessonsSolved());
for (Lesson lesson : course.getLessons()) {
LessonTracker lessonTracker = userTracker.getLessonTracker(lesson);
final LessonStatistics lessonStatistics = new LessonStatistics();
lessonStatistics.setName(pluginMessages.getMessage(lesson.getTitle()));
lessonStatistics.setNumberOfAttempts(lessonTracker.getNumberOfAttempts());
lessonStatistics.setSolved(lessonTracker.isLessonSolved());
reportCard.lessonStatistics.add(lessonStatistics);
}
return reportCard;
}
@Getter
@Setter
private final class ReportCard {
private int totalNumberOfLessons;
private int totalNumberOfAssignments;
private int solvedLessons;
private int numberOfAssignmentsSolved;
private int numberOfLessonsSolved;
private List<LessonStatistics> lessonStatistics = new ArrayList<>();
}
@Setter
@Getter
private final class LessonStatistics {
private String name;
private boolean solved;
private int numberOfAttempts;
}
}

View File

@ -32,8 +32,8 @@ import org.flywaydb.core.Flyway;
import org.owasp.webgoat.container.lessons.Initializeable; import org.owasp.webgoat.container.lessons.Initializeable;
import org.owasp.webgoat.container.lessons.Lesson; import org.owasp.webgoat.container.lessons.Lesson;
import org.owasp.webgoat.container.session.WebSession; import org.owasp.webgoat.container.session.WebSession;
import org.owasp.webgoat.container.users.UserTracker; import org.owasp.webgoat.container.users.UserProgress;
import org.owasp.webgoat.container.users.UserTrackerRepository; import org.owasp.webgoat.container.users.UserProgressRepository;
import org.springframework.http.HttpStatus; import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Controller; import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
@ -45,7 +45,7 @@ import org.springframework.web.bind.annotation.ResponseStatus;
public class RestartLessonService { public class RestartLessonService {
private final WebSession webSession; private final WebSession webSession;
private final UserTrackerRepository userTrackerRepository; private final UserProgressRepository userTrackerRepository;
private final Function<String, Flyway> flywayLessons; private final Function<String, Flyway> flywayLessons;
private final List<Initializeable> lessonsToInitialize; private final List<Initializeable> lessonsToInitialize;
@ -55,7 +55,7 @@ public class RestartLessonService {
Lesson al = webSession.getCurrentLesson(); Lesson al = webSession.getCurrentLesson();
log.debug("Restarting lesson: " + al); log.debug("Restarting lesson: " + al);
UserTracker userTracker = userTrackerRepository.findByUser(webSession.getUserName()); UserProgress userTracker = userTrackerRepository.findByUser(webSession.getUserName());
userTracker.reset(al); userTracker.reset(al);
userTrackerRepository.save(userTracker); userTrackerRepository.save(userTracker);

View File

@ -52,7 +52,7 @@ import org.owasp.webgoat.container.lessons.Lesson;
*/ */
@Entity @Entity
@EqualsAndHashCode @EqualsAndHashCode
public class LessonTracker { public class LessonProgress {
@Id @Id
@GeneratedValue(strategy = GenerationType.IDENTITY) @GeneratedValue(strategy = GenerationType.IDENTITY)
@ -69,11 +69,11 @@ public class LessonTracker {
@Getter private int numberOfAttempts = 0; @Getter private int numberOfAttempts = 0;
@Version private Integer version; @Version private Integer version;
private LessonTracker() { protected LessonProgress() {
// JPA // JPA
} }
public LessonTracker(Lesson lesson) { public LessonProgress(Lesson lesson) {
lessonName = lesson.getId(); lessonName = lesson.getId();
allAssignments.addAll(lesson.getAssignments() == null ? List.of() : lesson.getAssignments()); allAssignments.addAll(lesson.getAssignments() == null ? List.of() : lesson.getAssignments());
} }
@ -119,4 +119,8 @@ public class LessonTracker {
overview.putAll(solvedAssignments.stream().collect(Collectors.toMap(a -> a, b -> true))); overview.putAll(solvedAssignments.stream().collect(Collectors.toMap(a -> a, b -> true)));
return overview; return overview;
} }
long numberOfSolvedAssignments() {
return solvedAssignments.size();
}
} }

View File

@ -21,7 +21,7 @@ import org.springframework.web.bind.annotation.RestController;
@AllArgsConstructor @AllArgsConstructor
public class Scoreboard { public class Scoreboard {
private final UserTrackerRepository userTrackerRepository; private final UserProgressRepository userTrackerRepository;
private final UserRepository userRepository; private final UserRepository userRepository;
private final Course course; private final Course course;
private final PluginMessages pluginMessages; private final PluginMessages pluginMessages;
@ -46,7 +46,7 @@ public class Scoreboard {
.collect(Collectors.toList()); .collect(Collectors.toList());
} }
private List<String> challengesSolved(UserTracker userTracker) { private List<String> challengesSolved(UserProgress userTracker) {
List<String> challenges = List<String> challenges =
List.of( List.of(
"Challenge1", "Challenge1",
@ -59,10 +59,10 @@ public class Scoreboard {
"Challenge8", "Challenge8",
"Challenge9"); "Challenge9");
return challenges.stream() return challenges.stream()
.map(userTracker::getLessonTracker) .map(userTracker::getLessonProgress)
.flatMap(Optional::stream) .flatMap(Optional::stream)
.filter(LessonTracker::isLessonSolved) .filter(LessonProgress::isLessonSolved)
.map(LessonTracker::getLessonName) .map(LessonProgress::getLessonName)
.map(this::toLessonTitle) .map(this::toLessonTitle)
.toList(); .toList();
} }

View File

@ -9,13 +9,10 @@ import jakarta.persistence.GenerationType;
import jakarta.persistence.Id; import jakarta.persistence.Id;
import jakarta.persistence.OneToMany; import jakarta.persistence.OneToMany;
import java.util.HashSet; import java.util.HashSet;
import java.util.Map;
import java.util.Optional; import java.util.Optional;
import java.util.Set; import java.util.Set;
import java.util.stream.Collectors;
import lombok.EqualsAndHashCode; import lombok.EqualsAndHashCode;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.owasp.webgoat.container.lessons.Assignment;
import org.owasp.webgoat.container.lessons.Lesson; import org.owasp.webgoat.container.lessons.Lesson;
/** /**
@ -52,7 +49,7 @@ import org.owasp.webgoat.container.lessons.Lesson;
@Slf4j @Slf4j
@Entity @Entity
@EqualsAndHashCode @EqualsAndHashCode
public class UserTracker { public class UserProgress {
@Id @Id
@GeneratedValue(strategy = GenerationType.IDENTITY) @GeneratedValue(strategy = GenerationType.IDENTITY)
@ -62,11 +59,11 @@ public class UserTracker {
private String user; private String user;
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER) @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
private Set<LessonTracker> lessonTrackers = new HashSet<>(); private Set<LessonProgress> lessonProgress = new HashSet<>();
private UserTracker() {} protected UserProgress() {}
public UserTracker(final String user) { public UserProgress(final String user) {
this.user = user; this.user = user;
} }
@ -76,15 +73,15 @@ public class UserTracker {
* @param lesson the lesson * @param lesson the lesson
* @return a lesson tracker created if not already present * @return a lesson tracker created if not already present
*/ */
public LessonTracker getLessonTracker(Lesson lesson) { public LessonProgress getLessonProgress(Lesson lesson) {
Optional<LessonTracker> lessonTracker = Optional<LessonProgress> progress =
lessonTrackers.stream().filter(l -> l.getLessonName().equals(lesson.getId())).findFirst(); lessonProgress.stream().filter(l -> l.getLessonName().equals(lesson.getId())).findFirst();
if (!lessonTracker.isPresent()) { if (!progress.isPresent()) {
LessonTracker newLessonTracker = new LessonTracker(lesson); LessonProgress newLessonTracker = new LessonProgress(lesson);
lessonTrackers.add(newLessonTracker); lessonProgress.add(newLessonTracker);
return newLessonTracker; return newLessonTracker;
} else { } else {
return lessonTracker.get(); return progress.get();
} }
} }
@ -94,43 +91,34 @@ public class UserTracker {
* @param id the id of the lesson * @param id the id of the lesson
* @return optional due to the fact we can only create a lesson tracker based on a lesson * @return optional due to the fact we can only create a lesson tracker based on a lesson
*/ */
public Optional<LessonTracker> getLessonTracker(String id) { public Optional<LessonProgress> getLessonProgress(String id) {
return lessonTrackers.stream().filter(l -> l.getLessonName().equals(id)).findFirst(); return lessonProgress.stream().filter(l -> l.getLessonName().equals(id)).findFirst();
} }
public void assignmentSolved(Lesson lesson, String assignmentName) { public void assignmentSolved(Lesson lesson, String assignmentName) {
LessonTracker lessonTracker = getLessonTracker(lesson); LessonProgress progress = getLessonProgress(lesson);
lessonTracker.incrementAttempts(); progress.incrementAttempts();
lessonTracker.assignmentSolved(assignmentName); progress.assignmentSolved(assignmentName);
} }
public void assignmentFailed(Lesson lesson) { public void assignmentFailed(Lesson lesson) {
LessonTracker lessonTracker = getLessonTracker(lesson); LessonProgress progress = getLessonProgress(lesson);
lessonTracker.incrementAttempts(); progress.incrementAttempts();
} }
public void reset(Lesson al) { public void reset(Lesson al) {
LessonTracker lessonTracker = getLessonTracker(al); LessonProgress progress = getLessonProgress(al);
lessonTracker.reset(); progress.reset();
} }
public int numberOfLessonsSolved() { public long numberOfLessonsSolved() {
int numberOfLessonsSolved = 0; return lessonProgress.stream().filter(LessonProgress::isLessonSolved).count();
for (LessonTracker lessonTracker : lessonTrackers) {
if (lessonTracker.isLessonSolved()) {
numberOfLessonsSolved = numberOfLessonsSolved + 1;
}
}
return numberOfLessonsSolved;
} }
public int numberOfAssignmentsSolved() { public long numberOfAssignmentsSolved() {
int numberOfAssignmentsSolved = 0; return lessonProgress.stream()
for (LessonTracker lessonTracker : lessonTrackers) { .map(LessonProgress::numberOfSolvedAssignments)
Map<Assignment, Boolean> lessonOverview = lessonTracker.getLessonOverview(); .mapToLong(Long::valueOf)
numberOfAssignmentsSolved = .sum();
lessonOverview.values().stream().filter(b -> b).collect(Collectors.counting()).intValue();
}
return numberOfAssignmentsSolved;
} }
} }

View File

@ -6,7 +6,7 @@ import org.springframework.data.jpa.repository.JpaRepository;
* @author nbaars * @author nbaars
* @since 4/30/17. * @since 4/30/17.
*/ */
public interface UserTrackerRepository extends JpaRepository<UserTracker, String> { public interface UserProgressRepository extends JpaRepository<UserProgress, String> {
UserTracker findByUser(String user); UserProgress findByUser(String user);
} }

View File

@ -19,7 +19,7 @@ import org.springframework.stereotype.Service;
public class UserService implements UserDetailsService { public class UserService implements UserDetailsService {
private final UserRepository userRepository; private final UserRepository userRepository;
private final UserTrackerRepository userTrackerRepository; private final UserProgressRepository userTrackerRepository;
private final JdbcTemplate jdbcTemplate; private final JdbcTemplate jdbcTemplate;
private final Function<String, Flyway> flywayLessons; private final Function<String, Flyway> flywayLessons;
private final List<Initializeable> lessonInitializables; private final List<Initializeable> lessonInitializables;
@ -43,7 +43,7 @@ public class UserService implements UserDetailsService {
if (!userAlreadyExists) { if (!userAlreadyExists) {
userTrackerRepository.save( userTrackerRepository.save(
new UserTracker(username)); // if user previously existed it will not get another tracker new UserProgress(username)); // if user previously existed it will not get another tracker
createLessonsForUser(webGoatUser); createLessonsForUser(webGoatUser);
} }
} }

View File

@ -26,8 +26,8 @@ import jakarta.servlet.http.HttpServletRequest;
import org.owasp.webgoat.container.assignments.AssignmentEndpoint; import org.owasp.webgoat.container.assignments.AssignmentEndpoint;
import org.owasp.webgoat.container.assignments.AssignmentHints; import org.owasp.webgoat.container.assignments.AssignmentHints;
import org.owasp.webgoat.container.assignments.AttackResult; import org.owasp.webgoat.container.assignments.AttackResult;
import org.owasp.webgoat.container.users.UserTracker; import org.owasp.webgoat.container.users.UserProgress;
import org.owasp.webgoat.container.users.UserTrackerRepository; import org.owasp.webgoat.container.users.UserProgressRepository;
import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
@ -40,9 +40,9 @@ import org.springframework.web.bind.annotation.RestController;
@AssignmentHints({"csrf-login-hint1", "csrf-login-hint2", "csrf-login-hint3"}) @AssignmentHints({"csrf-login-hint1", "csrf-login-hint2", "csrf-login-hint3"})
public class CSRFLogin extends AssignmentEndpoint { public class CSRFLogin extends AssignmentEndpoint {
private final UserTrackerRepository userTrackerRepository; private final UserProgressRepository userTrackerRepository;
public CSRFLogin(UserTrackerRepository userTrackerRepository) { public CSRFLogin(UserProgressRepository userTrackerRepository) {
this.userTrackerRepository = userTrackerRepository; this.userTrackerRepository = userTrackerRepository;
} }
@ -60,7 +60,7 @@ public class CSRFLogin extends AssignmentEndpoint {
} }
private void markAssignmentSolvedWithRealUser(String username) { private void markAssignmentSolvedWithRealUser(String username) {
UserTracker userTracker = userTrackerRepository.findByUser(username); UserProgress userTracker = userTrackerRepository.findByUser(username);
userTracker.assignmentSolved( userTracker.assignmentSolved(
getWebSession().getCurrentLesson(), this.getClass().getSimpleName()); getWebSession().getCurrentLesson(), this.getClass().getSimpleName());
userTrackerRepository.save(userTracker); userTrackerRepository.save(userTracker);

View File

@ -0,0 +1,22 @@
ALTER TABLE container.lesson_tracker
RENAME TO container.lesson_progress;
ALTER TABLE container.lesson_tracker_all_assignments
ALTER COLUMN lesson_tracker_id RENAME TO lesson_progress_id;
ALTER TABLE container.lesson_tracker_all_assignments
RENAME TO container.lesson_progress_all_assignments;
ALTER TABLE container.lesson_tracker_solved_assignments
ALTER COLUMN lesson_tracker_id RENAME TO lesson_progress_id;
ALTER TABLE container.lesson_tracker_solved_assignments
RENAME TO container.lesson_progress_solved_assignments;
ALTER TABLE container.user_tracker
RENAME TO container.user_progress;
ALTER TABLE container.user_tracker_lesson_trackers
ALTER COLUMN user_tracker_id RENAME TO user_progress_id;
ALTER TABLE container.user_tracker_lesson_trackers
ALTER COLUMN lesson_trackers_id RENAME TO lesson_progress_id;
ALTER TABLE container.user_tracker_lesson_trackers
RENAME TO container.user_progress_lesson_progress;

View File

@ -8,8 +8,7 @@ define(['jquery',
'goatApp/support/GoatUtils', 'goatApp/support/GoatUtils',
'goatApp/view/UserAndInfoView', 'goatApp/view/UserAndInfoView',
'goatApp/view/MenuButtonView', 'goatApp/view/MenuButtonView',
'goatApp/model/LessonInfoModel', 'goatApp/model/LessonInfoModel'
'goatApp/view/TitleView'
], ],
function($, function($,
_, _,
@ -21,8 +20,7 @@ define(['jquery',
GoatUtils, GoatUtils,
UserAndInfoView, UserAndInfoView,
MenuButtonView, MenuButtonView,
LessonInfoModel, LessonInfoModel
TitleView
) { ) {
'use strict' 'use strict'

View File

@ -32,8 +32,8 @@ import org.owasp.webgoat.container.i18n.Messages;
import org.owasp.webgoat.container.i18n.PluginMessages; import org.owasp.webgoat.container.i18n.PluginMessages;
import org.owasp.webgoat.container.session.UserSessionData; import org.owasp.webgoat.container.session.UserSessionData;
import org.owasp.webgoat.container.session.WebSession; import org.owasp.webgoat.container.session.WebSession;
import org.owasp.webgoat.container.users.UserTracker; import org.owasp.webgoat.container.users.UserProgress;
import org.owasp.webgoat.container.users.UserTrackerRepository; import org.owasp.webgoat.container.users.UserProgressRepository;
import org.springframework.context.support.ClassPathXmlApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.test.util.ReflectionTestUtils; import org.springframework.test.util.ReflectionTestUtils;
import org.springframework.web.servlet.i18n.FixedLocaleResolver; import org.springframework.web.servlet.i18n.FixedLocaleResolver;
@ -41,8 +41,8 @@ import org.springframework.web.servlet.i18n.FixedLocaleResolver;
// Do not remove is the base class for all assignments tests // Do not remove is the base class for all assignments tests
public class AssignmentEndpointTest { public class AssignmentEndpointTest {
@Mock protected UserTracker userTracker; @Mock protected UserProgress userTracker;
@Mock protected UserTrackerRepository userTrackerRepository; @Mock protected UserProgressRepository userTrackerRepository;
@Mock protected WebSession webSession; @Mock protected WebSession webSession;
@Mock protected UserSessionData userSessionData; @Mock protected UserSessionData userSessionData;

View File

@ -1,4 +1,4 @@
package org.owasp.webgoat.container.service; package org.owasp.webgoat.container.report;
import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.CoreMatchers.is;
import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.any;
@ -18,22 +18,23 @@ import org.owasp.webgoat.container.i18n.PluginMessages;
import org.owasp.webgoat.container.lessons.Lesson; import org.owasp.webgoat.container.lessons.Lesson;
import org.owasp.webgoat.container.session.Course; import org.owasp.webgoat.container.session.Course;
import org.owasp.webgoat.container.session.WebSession; import org.owasp.webgoat.container.session.WebSession;
import org.owasp.webgoat.container.users.LessonTracker; import org.owasp.webgoat.container.users.LessonProgress;
import org.owasp.webgoat.container.users.UserTracker; import org.owasp.webgoat.container.users.UserProgress;
import org.owasp.webgoat.container.users.UserTrackerRepository; import org.owasp.webgoat.container.users.UserProgressRepository;
import org.springframework.security.test.context.support.WithMockUser; import org.springframework.security.test.context.support.WithMockUser;
import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
@ExtendWith(MockitoExtension.class) @ExtendWith(MockitoExtension.class)
public class ReportCardServiceTest { // TODO: Rewrite this as end-to-end test this mocks too many classes
public class ReportCardControllerTest {
private MockMvc mockMvc; private MockMvc mockMvc;
@Mock private Course course; @Mock private Course course;
@Mock private UserTracker userTracker; @Mock private UserProgress userTracker;
@Mock private Lesson lesson; @Mock private Lesson lesson;
@Mock private LessonTracker lessonTracker; @Mock private LessonProgress lessonTracker;
@Mock private UserTrackerRepository userTrackerRepository; @Mock private UserProgressRepository userTrackerRepository;
@Mock private WebSession websession; @Mock private WebSession websession;
@Mock private PluginMessages pluginMessages; @Mock private PluginMessages pluginMessages;
@ -41,7 +42,7 @@ public class ReportCardServiceTest {
void setup() { void setup() {
this.mockMvc = this.mockMvc =
standaloneSetup( standaloneSetup(
new ReportCardService(websession, userTrackerRepository, course, pluginMessages)) new ReportCardController(websession, userTrackerRepository, course, pluginMessages))
.build(); .build();
when(pluginMessages.getMessage(anyString())).thenReturn("Test"); when(pluginMessages.getMessage(anyString())).thenReturn("Test");
} }
@ -54,12 +55,11 @@ public class ReportCardServiceTest {
when(course.getTotalOfAssignments()).thenReturn(10); when(course.getTotalOfAssignments()).thenReturn(10);
when(course.getLessons()).thenAnswer(x -> List.of(lesson)); when(course.getLessons()).thenAnswer(x -> List.of(lesson));
when(userTrackerRepository.findByUser(any())).thenReturn(userTracker); when(userTrackerRepository.findByUser(any())).thenReturn(userTracker);
when(userTracker.getLessonTracker(any(Lesson.class))).thenReturn(lessonTracker); when(userTracker.getLessonProgress(any(Lesson.class))).thenReturn(lessonTracker);
mockMvc mockMvc
.perform(MockMvcRequestBuilders.get("/service/reportcard.mvc")) .perform(MockMvcRequestBuilders.get("/service/reportcard.mvc"))
.andExpect(status().isOk()) .andExpect(status().isOk())
.andExpect(jsonPath("$.totalNumberOfLessons", is(1))) .andExpect(jsonPath("$.totalNumberOfLessons", is(1)))
.andExpect(jsonPath("$.solvedLessons", is(0)))
.andExpect(jsonPath("$.numberOfAssignmentsSolved", is(0))) .andExpect(jsonPath("$.numberOfAssignmentsSolved", is(0)))
.andExpect(jsonPath("$.totalNumberOfAssignments", is(10))) .andExpect(jsonPath("$.totalNumberOfAssignments", is(10)))
.andExpect(jsonPath("$.lessonStatistics[0].name", is("Test"))) .andExpect(jsonPath("$.lessonStatistics[0].name", is("Test")))

View File

@ -41,9 +41,9 @@ import org.owasp.webgoat.container.lessons.Category;
import org.owasp.webgoat.container.lessons.Lesson; import org.owasp.webgoat.container.lessons.Lesson;
import org.owasp.webgoat.container.session.Course; import org.owasp.webgoat.container.session.Course;
import org.owasp.webgoat.container.session.WebSession; import org.owasp.webgoat.container.session.WebSession;
import org.owasp.webgoat.container.users.LessonTracker; import org.owasp.webgoat.container.users.LessonProgress;
import org.owasp.webgoat.container.users.UserTracker; import org.owasp.webgoat.container.users.UserProgress;
import org.owasp.webgoat.container.users.UserTrackerRepository; import org.owasp.webgoat.container.users.UserProgressRepository;
import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
@ -51,11 +51,11 @@ import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
public class LessonMenuServiceTest { public class LessonMenuServiceTest {
@Mock(lenient = true) @Mock(lenient = true)
private LessonTracker lessonTracker; private LessonProgress lessonTracker;
@Mock private Course course; @Mock private Course course;
@Mock private UserTracker userTracker; @Mock private UserProgress userTracker;
@Mock private UserTrackerRepository userTrackerRepository; @Mock private UserProgressRepository userTrackerRepository;
@Mock private WebSession webSession; @Mock private WebSession webSession;
private MockMvc mockMvc; private MockMvc mockMvc;
@ -81,7 +81,7 @@ public class LessonMenuServiceTest {
when(lessonTracker.isLessonSolved()).thenReturn(false); when(lessonTracker.isLessonSolved()).thenReturn(false);
when(course.getLessons(any())).thenReturn(Lists.newArrayList(l1, l2)); when(course.getLessons(any())).thenReturn(Lists.newArrayList(l1, l2));
when(course.getCategories()).thenReturn(Lists.newArrayList(Category.A1)); when(course.getCategories()).thenReturn(Lists.newArrayList(Category.A1));
when(userTracker.getLessonTracker(any(Lesson.class))).thenReturn(lessonTracker); when(userTracker.getLessonProgress(any(Lesson.class))).thenReturn(lessonTracker);
when(userTrackerRepository.findByUser(any())).thenReturn(userTracker); when(userTrackerRepository.findByUser(any())).thenReturn(userTracker);
mockMvc mockMvc
@ -98,7 +98,7 @@ public class LessonMenuServiceTest {
when(lessonTracker.isLessonSolved()).thenReturn(true); when(lessonTracker.isLessonSolved()).thenReturn(true);
when(course.getLessons(any())).thenReturn(Lists.newArrayList(l1)); when(course.getLessons(any())).thenReturn(Lists.newArrayList(l1));
when(course.getCategories()).thenReturn(Lists.newArrayList(Category.A1)); when(course.getCategories()).thenReturn(Lists.newArrayList(Category.A1));
when(userTracker.getLessonTracker(any(Lesson.class))).thenReturn(lessonTracker); when(userTracker.getLessonProgress(any(Lesson.class))).thenReturn(lessonTracker);
when(userTrackerRepository.findByUser(any())).thenReturn(userTracker); when(userTrackerRepository.findByUser(any())).thenReturn(userTracker);
mockMvc mockMvc

View File

@ -16,9 +16,9 @@ import org.mockito.junit.jupiter.MockitoExtension;
import org.owasp.webgoat.container.lessons.Assignment; import org.owasp.webgoat.container.lessons.Assignment;
import org.owasp.webgoat.container.lessons.Lesson; import org.owasp.webgoat.container.lessons.Lesson;
import org.owasp.webgoat.container.session.WebSession; import org.owasp.webgoat.container.session.WebSession;
import org.owasp.webgoat.container.users.LessonTracker; import org.owasp.webgoat.container.users.LessonProgress;
import org.owasp.webgoat.container.users.UserTracker; import org.owasp.webgoat.container.users.UserProgress;
import org.owasp.webgoat.container.users.UserTrackerRepository; import org.owasp.webgoat.container.users.UserProgressRepository;
import org.springframework.http.MediaType; import org.springframework.http.MediaType;
import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
@ -60,16 +60,16 @@ class LessonProgressServiceTest {
private MockMvc mockMvc; private MockMvc mockMvc;
@Mock private Lesson lesson; @Mock private Lesson lesson;
@Mock private UserTracker userTracker; @Mock private UserProgress userTracker;
@Mock private LessonTracker lessonTracker; @Mock private LessonProgress lessonTracker;
@Mock private UserTrackerRepository userTrackerRepository; @Mock private UserProgressRepository userTrackerRepository;
@Mock private WebSession websession; @Mock private WebSession websession;
@BeforeEach @BeforeEach
void setup() { void setup() {
Assignment assignment = new Assignment("test", "test", List.of()); Assignment assignment = new Assignment("test", "test", List.of());
when(userTrackerRepository.findByUser(any())).thenReturn(userTracker); when(userTrackerRepository.findByUser(any())).thenReturn(userTracker);
when(userTracker.getLessonTracker(any(Lesson.class))).thenReturn(lessonTracker); when(userTracker.getLessonProgress(any(Lesson.class))).thenReturn(lessonTracker);
when(websession.getCurrentLesson()).thenReturn(lesson); when(websession.getCurrentLesson()).thenReturn(lesson);
when(lessonTracker.getLessonOverview()).thenReturn(Maps.newHashMap(assignment, true)); when(lessonTracker.getLessonOverview()).thenReturn(Maps.newHashMap(assignment, true));
this.mockMvc = this.mockMvc =

View File

@ -10,7 +10,7 @@ import org.assertj.core.api.Assertions;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.owasp.webgoat.container.lessons.Assignment; import org.owasp.webgoat.container.lessons.Assignment;
import org.owasp.webgoat.container.lessons.Lesson; import org.owasp.webgoat.container.lessons.Lesson;
import org.owasp.webgoat.container.users.LessonTracker; import org.owasp.webgoat.container.users.LessonProgress;
/** /**
* ************************************************************************************************ * ************************************************************************************************
@ -49,7 +49,7 @@ class LessonTrackerTest {
Lesson lesson = mock(Lesson.class); Lesson lesson = mock(Lesson.class);
when(lesson.getAssignments()) when(lesson.getAssignments())
.thenReturn(List.of(new Assignment("assignment", "assignment", List.of("")))); .thenReturn(List.of(new Assignment("assignment", "assignment", List.of(""))));
LessonTracker lessonTracker = new LessonTracker(lesson); LessonProgress lessonTracker = new LessonProgress(lesson);
lessonTracker.assignmentSolved("assignment"); lessonTracker.assignmentSolved("assignment");
Assertions.assertThat(lessonTracker.isLessonSolved()).isTrue(); Assertions.assertThat(lessonTracker.isLessonSolved()).isTrue();
@ -62,7 +62,7 @@ class LessonTrackerTest {
Assignment a2 = new Assignment("a2"); Assignment a2 = new Assignment("a2");
List<Assignment> assignments = List.of(a1, a2); List<Assignment> assignments = List.of(a1, a2);
when(lesson.getAssignments()).thenReturn(assignments); when(lesson.getAssignments()).thenReturn(assignments);
LessonTracker lessonTracker = new LessonTracker(lesson); LessonProgress lessonTracker = new LessonProgress(lesson);
lessonTracker.assignmentSolved("a1"); lessonTracker.assignmentSolved("a1");
Map<Assignment, Boolean> lessonOverview = lessonTracker.getLessonOverview(); Map<Assignment, Boolean> lessonOverview = lessonTracker.getLessonOverview();
@ -76,7 +76,7 @@ class LessonTrackerTest {
Assignment a1 = new Assignment("a1"); Assignment a1 = new Assignment("a1");
List<Assignment> assignments = List.of(a1); List<Assignment> assignments = List.of(a1);
when(lesson.getAssignments()).thenReturn(assignments); when(lesson.getAssignments()).thenReturn(assignments);
LessonTracker lessonTracker = new LessonTracker(lesson); LessonProgress lessonTracker = new LessonProgress(lesson);
lessonTracker.assignmentSolved("a1"); lessonTracker.assignmentSolved("a1");
lessonTracker.assignmentSolved("a1"); lessonTracker.assignmentSolved("a1");

View File

@ -18,7 +18,7 @@ import org.springframework.security.core.userdetails.UsernameNotFoundException;
class UserServiceTest { class UserServiceTest {
@Mock private UserRepository userRepository; @Mock private UserRepository userRepository;
@Mock private UserTrackerRepository userTrackerRepository; @Mock private UserProgressRepository userTrackerRepository;
@Mock private JdbcTemplate jdbcTemplate; @Mock private JdbcTemplate jdbcTemplate;
@Mock private Function<String, Flyway> flywayLessons; @Mock private Function<String, Flyway> flywayLessons;

View File

@ -34,23 +34,23 @@ class UserTrackerRepositoryTest {
} }
} }
@Autowired private UserTrackerRepository userTrackerRepository; @Autowired private UserProgressRepository userTrackerRepository;
@Test @Test
void saveUserTracker() { void saveUserTracker() {
UserTracker userTracker = new UserTracker("test"); UserProgress userTracker = new UserProgress("test");
userTrackerRepository.save(userTracker); userTrackerRepository.save(userTracker);
userTracker = userTrackerRepository.findByUser("test"); userTracker = userTrackerRepository.findByUser("test");
Assertions.assertThat(userTracker.getLessonTracker("test")).isNotNull(); Assertions.assertThat(userTracker.getLessonProgress("test")).isNotNull();
} }
@Test @Test
void solvedAssignmentsShouldBeSaved() { void solvedAssignmentsShouldBeSaved() {
UserTracker userTracker = new UserTracker("test"); UserProgress userTracker = new UserProgress("test");
TestLesson lesson = new TestLesson(); TestLesson lesson = new TestLesson();
userTracker.getLessonTracker(lesson); userTracker.getLessonProgress(lesson);
userTracker.assignmentFailed(lesson); userTracker.assignmentFailed(lesson);
userTracker.assignmentFailed(lesson); userTracker.assignmentFailed(lesson);
userTracker.assignmentSolved(lesson, "test"); userTracker.assignmentSolved(lesson, "test");
@ -63,9 +63,9 @@ class UserTrackerRepositoryTest {
@Test @Test
void saveAndLoadShouldHaveCorrectNumberOfAttempts() { void saveAndLoadShouldHaveCorrectNumberOfAttempts() {
UserTracker userTracker = new UserTracker("test"); UserProgress userTracker = new UserProgress("test");
TestLesson lesson = new TestLesson(); TestLesson lesson = new TestLesson();
userTracker.getLessonTracker(lesson); userTracker.getLessonProgress(lesson);
userTracker.assignmentFailed(lesson); userTracker.assignmentFailed(lesson);
userTracker.assignmentFailed(lesson); userTracker.assignmentFailed(lesson);
userTrackerRepository.saveAndFlush(userTracker); userTrackerRepository.saveAndFlush(userTracker);
@ -75,6 +75,6 @@ class UserTrackerRepositoryTest {
userTracker.assignmentFailed(lesson); userTracker.assignmentFailed(lesson);
userTrackerRepository.saveAndFlush(userTracker); userTrackerRepository.saveAndFlush(userTracker);
Assertions.assertThat(userTracker.getLessonTracker(lesson).getNumberOfAttempts()).isEqualTo(4); Assertions.assertThat(userTracker.getLessonProgress(lesson).getNumberOfAttempts()).isEqualTo(4);
} }
} }