Finishing challenge 5
This commit is contained in:
parent
3cb089d675
commit
262d82f80b
@ -5,9 +5,12 @@ package org.owasp.webgoat.plugin.challenge5;
|
|||||||
* @since 4/30/17.
|
* @since 4/30/17.
|
||||||
*/
|
*/
|
||||||
public class Views {
|
public class Views {
|
||||||
interface GuestView {}
|
interface GuestView {
|
||||||
interface UserView extends GuestView {}
|
}
|
||||||
interface AdminView extends UserView {}
|
|
||||||
|
|
||||||
|
interface UserView extends GuestView {
|
||||||
|
}
|
||||||
|
|
||||||
|
interface AdminView extends UserView {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,49 @@
|
|||||||
|
package org.owasp.webgoat.plugin.challenge5;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonView;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author nbaars
|
||||||
|
* @since 5/2/17.
|
||||||
|
*/
|
||||||
|
@Getter
|
||||||
|
public class Vote {
|
||||||
|
@JsonView(Views.GuestView.class)
|
||||||
|
private final String title;
|
||||||
|
@JsonView(Views.GuestView.class)
|
||||||
|
private final String information;
|
||||||
|
@JsonView(Views.GuestView.class)
|
||||||
|
private final String imageSmall;
|
||||||
|
@JsonView(Views.GuestView.class)
|
||||||
|
private final String imageBig;
|
||||||
|
@JsonView(Views.UserView.class)
|
||||||
|
private int numberOfVotes;
|
||||||
|
@JsonView(Views.AdminView.class)
|
||||||
|
@Setter
|
||||||
|
private String flag;
|
||||||
|
@JsonView(Views.UserView.class)
|
||||||
|
private boolean votingAllowed = true;
|
||||||
|
@JsonView(Views.UserView.class)
|
||||||
|
private long average = 0;
|
||||||
|
|
||||||
|
|
||||||
|
public Vote(String title, String information, String imageSmall, String imageBig, int numberOfVotes, int totalVotes) {
|
||||||
|
this.title = title;
|
||||||
|
this.information = information;
|
||||||
|
this.imageSmall = imageSmall;
|
||||||
|
this.imageBig = imageBig;
|
||||||
|
this.numberOfVotes = numberOfVotes;
|
||||||
|
this.average = calculateStars(totalVotes);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void incrementNumberOfVotes(int totalVotes) {
|
||||||
|
this.numberOfVotes = this.numberOfVotes + 1;
|
||||||
|
this.average = calculateStars(totalVotes);
|
||||||
|
}
|
||||||
|
|
||||||
|
private long calculateStars(int totalVotes) {
|
||||||
|
return Math.round(((double) numberOfVotes / (double) totalVotes) * 4);
|
||||||
|
}
|
||||||
|
}
|
@ -1,25 +1,27 @@
|
|||||||
package org.owasp.webgoat.plugin.challenge5;
|
package org.owasp.webgoat.plugin.challenge5;
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonView;
|
|
||||||
import com.google.common.collect.Lists;
|
|
||||||
import com.google.common.collect.Maps;
|
import com.google.common.collect.Maps;
|
||||||
import io.jsonwebtoken.Claims;
|
import io.jsonwebtoken.Claims;
|
||||||
import io.jsonwebtoken.Jwt;
|
import io.jsonwebtoken.Jwt;
|
||||||
import io.jsonwebtoken.Jwts;
|
import io.jsonwebtoken.Jwts;
|
||||||
import io.jsonwebtoken.SignatureAlgorithm;
|
import io.jsonwebtoken.SignatureAlgorithm;
|
||||||
import lombok.Getter;
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.springframework.http.HttpStatus;
|
import org.springframework.http.HttpStatus;
|
||||||
|
import org.springframework.http.ResponseEntity;
|
||||||
import org.springframework.http.converter.json.MappingJacksonValue;
|
import org.springframework.http.converter.json.MappingJacksonValue;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
|
import javax.annotation.PostConstruct;
|
||||||
import javax.servlet.http.Cookie;
|
import javax.servlet.http.Cookie;
|
||||||
import javax.servlet.http.HttpServletResponse;
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
import java.util.Collection;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
import static java.util.Comparator.comparingLong;
|
||||||
|
import static java.util.Optional.ofNullable;
|
||||||
|
import static java.util.stream.Collectors.toList;
|
||||||
import static org.owasp.webgoat.plugin.Flag.FLAGS;
|
import static org.owasp.webgoat.plugin.Flag.FLAGS;
|
||||||
import static org.owasp.webgoat.plugin.SolutionConstants.JWT_PASSWORD;
|
import static org.owasp.webgoat.plugin.SolutionConstants.JWT_PASSWORD;
|
||||||
|
|
||||||
@ -29,55 +31,31 @@ import static org.owasp.webgoat.plugin.SolutionConstants.JWT_PASSWORD;
|
|||||||
*/
|
*/
|
||||||
@RestController
|
@RestController
|
||||||
@RequestMapping("/votings")
|
@RequestMapping("/votings")
|
||||||
public class Votes {
|
public class VotesEndpoint {
|
||||||
|
|
||||||
private static String validUsers = "TomJerrySylvester";
|
private static String validUsers = "TomJerrySylvester";
|
||||||
|
|
||||||
@Getter
|
|
||||||
private static class Voting {
|
|
||||||
@JsonView(Views.GuestView.class)
|
|
||||||
private final String title;
|
|
||||||
@JsonView(Views.GuestView.class)
|
|
||||||
private final String information;
|
|
||||||
@JsonView(Views.GuestView.class)
|
|
||||||
private final String imageSmall;
|
|
||||||
@JsonView(Views.GuestView.class)
|
|
||||||
private final String imageBig;
|
|
||||||
@JsonView(Views.UserView.class)
|
|
||||||
private final int numberOfVotes;
|
|
||||||
@JsonView(Views.AdminView.class)
|
|
||||||
private String flag = FLAGS.get(5);
|
|
||||||
@JsonView(Views.UserView.class)
|
|
||||||
private boolean votingAllowed = true;
|
|
||||||
@JsonView(Views.UserView.class)
|
|
||||||
private String average = "0.0";
|
|
||||||
|
|
||||||
|
|
||||||
public Voting(String title, String information, String imageSmall, String imageBig, int numberOfVotes) {
|
|
||||||
this.title = title;
|
|
||||||
this.information = information;
|
|
||||||
this.imageSmall = imageSmall;
|
|
||||||
this.imageBig = imageBig;
|
|
||||||
this.numberOfVotes = numberOfVotes;
|
|
||||||
this.average = String.valueOf((double)numberOfVotes / (double)totalVotes);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static int totalVotes = 38929;
|
private static int totalVotes = 38929;
|
||||||
private List votes = Lists.newArrayList(
|
private Map<String, Vote> votes = Maps.newHashMap();
|
||||||
new Voting("Admin lost password",
|
|
||||||
"In this challenge you will need to help the admin and find the password in order to login",
|
@PostConstruct
|
||||||
"challenge1-small.png", "challenge1.png", 14242),
|
private void initVotes() {
|
||||||
new Voting("Vote for your favourite",
|
votes.put("Admin lost password", new Vote("Admin lost password",
|
||||||
"In this challenge ...",
|
"In this challenge you will need to help the admin and find the password in order to login",
|
||||||
"challenge5-small.png", "challenge5.png", 12345),
|
"challenge1-small.png", "challenge1.png", 36000, totalVotes));
|
||||||
new Voting("Get is for free",
|
votes.put("Vote for your favourite",
|
||||||
"The objective for this challenge is to buy a Samsung phone for free.",
|
new Vote("Vote for your favourite",
|
||||||
"challenge2-small.png", "challenge2.png", 12342),
|
"In this challenge ...",
|
||||||
new Voting("Photo comments",
|
"challenge5-small.png", "challenge5.png", 30000, totalVotes));
|
||||||
"n this challenge you can comment on the photo you will need to find the flag somewhere.",
|
votes.put("Get it for free",
|
||||||
"challenge3-small.png", "challenge3.png", 12342)
|
new Vote("Get it for free",
|
||||||
);
|
"The objective for this challenge is to buy a Samsung phone for free.",
|
||||||
|
"challenge2-small.png", "challenge2.png", 20000, totalVotes));
|
||||||
|
votes.put("Photo comments",
|
||||||
|
new Vote("Photo comments",
|
||||||
|
"n this challenge you can comment on the photo you will need to find the flag somewhere.",
|
||||||
|
"challenge3-small.png", "challenge3.png", 10000, totalVotes));
|
||||||
|
}
|
||||||
|
|
||||||
@GetMapping("/login")
|
@GetMapping("/login")
|
||||||
public void login(@RequestParam("user") String user, HttpServletResponse response) {
|
public void login(@RequestParam("user") String user, HttpServletResponse response) {
|
||||||
@ -102,18 +80,19 @@ public class Votes {
|
|||||||
|
|
||||||
@GetMapping
|
@GetMapping
|
||||||
public MappingJacksonValue getVotes(@CookieValue(value = "access_token", required = false) String accessToken) {
|
public MappingJacksonValue getVotes(@CookieValue(value = "access_token", required = false) String accessToken) {
|
||||||
MappingJacksonValue value = new MappingJacksonValue(votes);
|
MappingJacksonValue value = new MappingJacksonValue(votes.values().stream().sorted(comparingLong(Vote::getAverage).reversed()).collect(toList()));
|
||||||
if (StringUtils.isEmpty(accessToken)) {
|
if (StringUtils.isEmpty(accessToken)) {
|
||||||
value.setSerializationView(Views.GuestView.class);
|
value.setSerializationView(Views.GuestView.class);
|
||||||
} else {
|
} else {
|
||||||
try {
|
try {
|
||||||
Jwt jwt = Jwts.parser().parse(accessToken);
|
Jwt jwt = Jwts.parser().setSigningKey(JWT_PASSWORD).parse(accessToken);
|
||||||
Claims claims = (Claims) jwt.getBody();
|
Claims claims = (Claims) jwt.getBody();
|
||||||
String user = (String) claims.get("user");
|
String user = (String) claims.get("user");
|
||||||
boolean isAdmin = Boolean.valueOf((String) claims.get("admin"));
|
boolean isAdmin = Boolean.valueOf((String) claims.get("admin"));
|
||||||
if ("Guest".equals(user)) {
|
if ("Guest".equals(user)) {
|
||||||
value.setSerializationView(Views.GuestView.class);
|
value.setSerializationView(Views.GuestView.class);
|
||||||
} else {
|
} else {
|
||||||
|
((Collection<Vote>)value.getValue()).forEach(v -> v.setFlag(FLAGS.get(5)));
|
||||||
value.setSerializationView(isAdmin ? Views.AdminView.class : Views.UserView.class);
|
value.setSerializationView(isAdmin ? Views.AdminView.class : Views.UserView.class);
|
||||||
}
|
}
|
||||||
} catch (IllegalArgumentException e) {
|
} catch (IllegalArgumentException e) {
|
||||||
@ -123,11 +102,22 @@ public class Votes {
|
|||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
@PostMapping
|
@PostMapping(value = "{title}")
|
||||||
@ResponseBody
|
@ResponseBody
|
||||||
@ResponseStatus(HttpStatus.ACCEPTED)
|
@ResponseStatus(HttpStatus.ACCEPTED)
|
||||||
public void vote(String title) {
|
public ResponseEntity<?> vote(@PathVariable String title, @CookieValue(value = "access_token", required = false) String accessToken) {
|
||||||
totalVotes = totalVotes + 1;
|
if (StringUtils.isEmpty(accessToken)) {
|
||||||
//return
|
return ResponseEntity.status(HttpStatus.UNAUTHORIZED).build();
|
||||||
|
} else {
|
||||||
|
Jwt jwt = Jwts.parser().setSigningKey(JWT_PASSWORD).parse(accessToken);
|
||||||
|
Claims claims = (Claims) jwt.getBody();
|
||||||
|
String user = (String) claims.get("user");
|
||||||
|
if (validUsers.contains(user)) {
|
||||||
|
ofNullable(votes.get(title)).ifPresent(v -> v.incrementNumberOfVotes(totalVotes));
|
||||||
|
return ResponseEntity.accepted().build();
|
||||||
|
} else {
|
||||||
|
return ResponseEntity.status(HttpStatus.UNAUTHORIZED).build();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,13 +1,15 @@
|
|||||||
$(document).ready(function () {
|
$(document).ready(function () {
|
||||||
getVotings();
|
|
||||||
login('Guest');
|
login('Guest');
|
||||||
})
|
})
|
||||||
|
|
||||||
function login(user) {
|
function login(user) {
|
||||||
$("#name").text(user);
|
$("#name").text(user);
|
||||||
$.get("votings/login?user=" + user, function (result, status) {
|
$.ajax({
|
||||||
|
url: "votings/login?user=" + user,
|
||||||
|
complete: function (result, status) {
|
||||||
|
getVotings();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
getVotings();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var html = '<a href="#" class="list-group-item ACTIVE">' +
|
var html = '<a href="#" class="list-group-item ACTIVE">' +
|
||||||
@ -21,17 +23,17 @@ var html = '<a href="#" class="list-group-item ACTIVE">' +
|
|||||||
'<p class="list-group-item-text">INFORMATION</p>' +
|
'<p class="list-group-item-text">INFORMATION</p>' +
|
||||||
'</div>' +
|
'</div>' +
|
||||||
'<div class="col-md-3 text-center">' +
|
'<div class="col-md-3 text-center">' +
|
||||||
'<h2>NO_VOTES' +
|
'<h2 HIDDEN_VIEW_VOTES>NO_VOTES' +
|
||||||
'<small> votes</small>' +
|
'<small HIDDEN_VIEW_VOTES> votes</small>' +
|
||||||
'</h2>' +
|
'</h2>' +
|
||||||
'<button type="button" class="btn BUTTON btn-lg btn-block">Vote Now!</button>' +
|
'<button type="button" id="TITLE" class="btn BUTTON btn-lg btn-block" onclick="vote(this.id)">Vote Now!</button>' +
|
||||||
'<div class="stars"> ' +
|
'<div style="visibility:HIDDEN_VIEW_RATING;" class="stars"> ' +
|
||||||
'<span class="glyphicon glyphicon-star"></span>' +
|
'<span class="glyphicon glyphicon-star"></span>' +
|
||||||
'<span class="glyphicon glyphicon-star"></span>' +
|
'<span class="glyphicon glyphicon-star"></span>' +
|
||||||
'<span class="glyphicon glyphicon-star"></span>' +
|
'<span class="glyphicon glyphicon-star"></span>' +
|
||||||
'<span class="glyphicon glyphicon-star-empty"></span>' +
|
'<span class="glyphicon glyphicon-star-empty"></span>' +
|
||||||
'</div>' +
|
'</div>' +
|
||||||
'<p>Average AVERAGE<small> /</small>4</p>' +
|
'<p HIDDEN_VIEW_RATING>Average AVERAGE<small> /</small>4</p>' +
|
||||||
'</div>' +
|
'</div>' +
|
||||||
'<div class="clearfix"></div>' +
|
'<div class="clearfix"></div>' +
|
||||||
'</a>';
|
'</a>';
|
||||||
@ -41,19 +43,42 @@ function getVotings() {
|
|||||||
$.get("votings/", function (result, status) {
|
$.get("votings/", function (result, status) {
|
||||||
for (var i = 0; i < result.length; i++) {
|
for (var i = 0; i < result.length; i++) {
|
||||||
var voteTemplate = html.replace('IMAGE_SMALL', result[i].imageSmall);
|
var voteTemplate = html.replace('IMAGE_SMALL', result[i].imageSmall);
|
||||||
if ( i === 0 ) {
|
if (i === 0) {
|
||||||
voteTemplate = voteTemplate.replace('ACTIVE', 'active');
|
voteTemplate = voteTemplate.replace('ACTIVE', 'active');
|
||||||
voteTemplate = voteTemplate.replace('BUTTON', 'btn-default');
|
voteTemplate = voteTemplate.replace('BUTTON', 'btn-default');
|
||||||
} else {
|
} else {
|
||||||
voteTemplate = voteTemplate.replace('ACTIVE', '');
|
voteTemplate = voteTemplate.replace('ACTIVE', '');
|
||||||
voteTemplate = voteTemplate.replace('BUTTON', 'btn-primary');
|
voteTemplate = voteTemplate.replace('BUTTON', 'btn-primary');
|
||||||
}
|
}
|
||||||
|
voteTemplate = voteTemplate.replace(/TITLE/g, result[i].title);
|
||||||
voteTemplate = voteTemplate.replace('TITLE', result[i].title);
|
|
||||||
voteTemplate = voteTemplate.replace('INFORMATION', result[i].information || '');
|
voteTemplate = voteTemplate.replace('INFORMATION', result[i].information || '');
|
||||||
voteTemplate = voteTemplate.replace('NO_VOTES', result[i].numberOfVotes || '');
|
voteTemplate = voteTemplate.replace('NO_VOTES', result[i].numberOfVotes || '');
|
||||||
|
voteTemplate = voteTemplate.replace('AVERAGE', result[i].average || '');
|
||||||
|
|
||||||
|
var hidden = (result[i].numberOfVotes === undefined ? 'hidden' : '');
|
||||||
|
voteTemplate = voteTemplate.replace(/HIDDEN_VIEW_VOTES/g, hidden);
|
||||||
|
hidden = (result[i].average === undefined ? 'hidden' : '');
|
||||||
|
voteTemplate = voteTemplate.replace(/HIDDEN_VIEW_RATING/g, hidden);
|
||||||
|
|
||||||
$("#votesList").append(voteTemplate);
|
$("#votesList").append(voteTemplate);
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function vote(title) {
|
||||||
|
var user = $("#name").text();
|
||||||
|
if (user === 'Guest') {
|
||||||
|
alert("As a guest you are not allowed to vote, please login first.")
|
||||||
|
} else {
|
||||||
|
$.ajax({
|
||||||
|
type: 'POST',
|
||||||
|
url: 'votings/' + title
|
||||||
|
}).then(
|
||||||
|
function () {
|
||||||
|
getVotings();
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user