Commit e986186f authored by Antek Grzanka's avatar Antek Grzanka

Merge branch 'master' into antek

parents 787f4546 d052c8fa
...@@ -4,13 +4,12 @@ server: ...@@ -4,13 +4,12 @@ server:
- type: http - type: http
port: 8080 port: 8080
dbHost: 46.4.242.141 dbHost: 92f653f4-cf83-4801-8475-cd748954c3b6.node.dockerapp.io
#dbHost: 127.0.0.1 #dbHost: 127.0.0.1
dbPort: 27017 dbPort: 27017
dbName: db dbName: db
flagHashMethod: "MD5" digestMethod: "MD5"
salt: "SECURE_SALT"
admins: admins:
- name: "gpietrus_admin" - name: "gpietrus_admin"
...@@ -74,19 +73,19 @@ textTasks: ...@@ -74,19 +73,19 @@ textTasks:
text: "Odszyfruj1" text: "Odszyfruj1"
level: 1 level: 1
flags: flags:
- value: "sdfg1f1" - value: "AGH_sdfg1f1"
description: "flaga 1" description: "flaga 1"
- value: "sdfg1f2" - value: "AGH_sdfg1f2"
description: "flaga 2" description: "flaga 2"
- value: "sdfgf13" - value: "AGH_sdfgf13"
description: "flaga 3" description: "flaga 3"
- name: "Szyfro2" - name: "Szyfro2"
text: "Odszyfruj2" text: "Odszyfruj2"
level: 2 level: 2
flags: flags:
- value: "sdfg1" - value: "AGH_sdfg1"
description: "flaga 1" description: "AGH_flaga 1"
- value: "sdfg1" - value: "sdfg1"
description: "flaga 2" description: "flaga 2"
...@@ -95,20 +94,20 @@ webTasks: ...@@ -95,20 +94,20 @@ webTasks:
url: "http://google.pl" url: "http://google.pl"
level: 3 level: 3
flags: flags:
- value: "sdfg1fs" - value: "AGH_sdfg1fs"
description: "flaga 11" description: "flaga 11"
- value: "sdfdg1f" - value: "AGH_sdfdg1f"
description: "flaga 22" description: "flaga 22"
- value: "sfdfgf1" - value: "AGH_sfdfgf1"
description: "flaga 33" description: "flaga 33"
- name: "Inna dziura" - name: "Inna dziura"
url: "http://wikipedia.pl" url: "http://wikipedia.pl"
level: 4 level: 4
flags: flags:
- value: "sdfffg1fs" - value: "AGH_sdfffg1fs"
description: "flaga 11" description: "flaga 11"
- value: "sffdfdg1f" - value: "AGH_sffdfdg1f"
description: "flaga 22" description: "flaga 22"
- value: "sdfassfdfgf1" - value: "AGH_sdfassfdfgf1"
description: "flaga 33" description: "flaga 33"
...@@ -15,14 +15,12 @@ public class Solution ...@@ -15,14 +15,12 @@ public class Solution
private Task task; private Task task;
private Team team; private Team team;
private Flag flag; private Flag flag;
private String hashValue;
public Solution(Team team, Task task, Flag flag, String hashValue) public Solution(Team team, Task task, Flag flag)
{ {
this.team = checkNotNull(team); this.team = checkNotNull(team);
this.task = checkNotNull(task); this.task = checkNotNull(task);
this.flag = checkNotNull(flag); this.flag = checkNotNull(flag);
this.hashValue = checkNotNull(hashValue);
} }
public Solution() public Solution()
...@@ -58,14 +56,4 @@ public class Solution ...@@ -58,14 +56,4 @@ public class Solution
{ {
this.flag = flag; this.flag = flag;
} }
public String getHashValue()
{
return hashValue;
}
public void setHashValue(String hashValue)
{
this.hashValue = hashValue;
}
} }
...@@ -16,12 +16,12 @@ import java.util.List; ...@@ -16,12 +16,12 @@ import java.util.List;
public abstract class Task public abstract class Task
{ {
@Id @Id
protected ObjectId id; private ObjectId id;
@PublicProperty @PublicProperty
protected String name; private String name;
@PublicProperty @PublicProperty
protected int level; private int level;
protected List<Flag> flags; private List<Flag> flags;
public Task(String name, int level, List<Flag> flags) public Task(String name, int level, List<Flag> flags)
{ {
......
...@@ -6,19 +6,34 @@ import com.telephoners.krakyournet.ctf.beans.tasks.TextTask; ...@@ -6,19 +6,34 @@ import com.telephoners.krakyournet.ctf.beans.tasks.TextTask;
import com.telephoners.krakyournet.ctf.beans.tasks.WebTask; import com.telephoners.krakyournet.ctf.beans.tasks.WebTask;
import io.dropwizard.Configuration; import io.dropwizard.Configuration;
import javax.validation.constraints.NotNull;
import java.util.List; import java.util.List;
public class ApplicationConfiguration extends Configuration public class ApplicationConfiguration extends Configuration
{ {
@NotNull
private String dbHost; private String dbHost;
@NotNull
private int dbPort; private int dbPort;
@NotNull
private String dbName; private String dbName;
private String flagHashMethod;
@NotNull
private String digestMethod;
@NotNull
private List<Team> teams; private List<Team> teams;
@NotNull
private List<TextTask> textTasks; private List<TextTask> textTasks;
@NotNull
private List<WebTask> webTasks; private List<WebTask> webTasks;
@NotNull
private List<User> admins; private List<User> admins;
private String salt;
public List<User> getAdmins() public List<User> getAdmins()
{ {
...@@ -30,9 +45,9 @@ public class ApplicationConfiguration extends Configuration ...@@ -30,9 +45,9 @@ public class ApplicationConfiguration extends Configuration
this.admins = admins; this.admins = admins;
} }
public String getFlagHashMethod() public String getDigestMethod()
{ {
return flagHashMethod; return digestMethod;
} }
public List<Team> getTeams() public List<Team> getTeams()
...@@ -45,9 +60,9 @@ public class ApplicationConfiguration extends Configuration ...@@ -45,9 +60,9 @@ public class ApplicationConfiguration extends Configuration
this.teams = teams; this.teams = teams;
} }
public void setFlagHashMethod(String flagHashMethod) public void setDigestMethodHashMethod(String digestMethod)
{ {
this.flagHashMethod = flagHashMethod; this.digestMethod = digestMethod;
} }
public String getDbHost() public String getDbHost()
...@@ -99,14 +114,4 @@ public class ApplicationConfiguration extends Configuration ...@@ -99,14 +114,4 @@ public class ApplicationConfiguration extends Configuration
{ {
this.webTasks = webTasks; this.webTasks = webTasks;
} }
public String getSalt()
{
return salt;
}
public void setSalt(String salt)
{
this.salt = salt;
}
} }
package com.telephoners.krakyournet.ctf.core;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import com.telephoners.krakyournet.ctf.beans.User;
import com.telephoners.krakyournet.ctf.providers.MessageDigestProvider;
import org.apache.commons.codec.binary.Hex;
@Singleton
public class HashValidator
{
private ApplicationConfiguration applicationConfiguration;
private MessageDigestProvider messageDigestProvider;
@Inject
public HashValidator(ApplicationConfiguration applicationConfiguration,
MessageDigestProvider messageDigestProvider)
{
this.applicationConfiguration = applicationConfiguration;
this.messageDigestProvider = messageDigestProvider;
}
public String calculateHashValue(User user, String flagValue)
{
String combinedStrings = applicationConfiguration.getSalt() + user.getName() + flagValue;
return Hex.encodeHexString(messageDigestProvider.getMessageDigest().digest(combinedStrings.getBytes()));
}
}
package com.telephoners.krakyournet.ctf.core;
/**
* Created by gpietrus on 21.02.2016.
*/
public class Test {
private String value;
private String asdf;
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
public String getAsdf() {
return asdf;
}
public void setAsdf(String asdf) {
this.asdf = asdf;
}
}
package com.telephoners.krakyournet.ctf.exceptions;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.Response;
public class InvalidSolutionException extends WebApplicationException
{
public InvalidSolutionException() {
super(Response.status(Response.Status.NOT_ACCEPTABLE)
.entity("Solution invalid").type("text/plain").build());
}
}
package com.telephoners.krakyournet.ctf.exceptions;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.Response;
public class SolutionAlreadySubmittedException extends WebApplicationException
{
public SolutionAlreadySubmittedException()
{
super(Response.status(Response.Status.NOT_ACCEPTABLE)
.entity("Solution already submitted.").type("text/plain").build());
}
}
package com.telephoners.krakyournet.ctf.exceptions;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.Response;
public class TaskNotFoundException extends WebApplicationException
{
public TaskNotFoundException() {
super(Response.status(Response.Status.NOT_FOUND)
.entity("Task not found.").type("text/plain").build());
}
}
package com.telephoners.krakyournet.ctf.exceptions;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.Response;
public class TeamNotFoundException extends WebApplicationException
{
public TeamNotFoundException() {
super(Response.status(Response.Status.NOT_FOUND)
.entity("Team not found.").type("text/plain").build());
}
}
package com.telephoners.krakyournet.ctf.exceptions;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.Response;
public class UserNotFoundException extends WebApplicationException
{
public UserNotFoundException() {
super(Response.status(Response.Status.NOT_FOUND)
.entity("User not found.").type("text/plain").build());
}
}
...@@ -13,10 +13,6 @@ import java.io.InputStream; ...@@ -13,10 +13,6 @@ import java.io.InputStream;
import java.util.logging.Level; import java.util.logging.Level;
import java.util.logging.Logger; import java.util.logging.Logger;
/**
* Created by adam on 20.03.16.
*/
@Singleton @Singleton
public class LoggingFilter implements ContainerRequestFilter { public class LoggingFilter implements ContainerRequestFilter {
private static final Logger LOG = Logger.getLogger(LoggingFilter.class.getName()); private static final Logger LOG = Logger.getLogger(LoggingFilter.class.getName());
......
...@@ -7,7 +7,7 @@ import org.mongodb.morphia.Datastore; ...@@ -7,7 +7,7 @@ import org.mongodb.morphia.Datastore;
public class ApplicationModule extends AbstractModule public class ApplicationModule extends AbstractModule
{ {
private ApplicationConfiguration applicationConfiguration; private final ApplicationConfiguration applicationConfiguration;
public ApplicationModule(ApplicationConfiguration applicationConfiguration) public ApplicationModule(ApplicationConfiguration applicationConfiguration)
{ {
......
...@@ -9,7 +9,7 @@ import javax.inject.Inject; ...@@ -9,7 +9,7 @@ import javax.inject.Inject;
public class DatastoreProvider public class DatastoreProvider
{ {
private ApplicationConfiguration applicationConfiguration; private final ApplicationConfiguration applicationConfiguration;
@Inject @Inject
public DatastoreProvider(ApplicationConfiguration applicationConfiguration) public DatastoreProvider(ApplicationConfiguration applicationConfiguration)
......
...@@ -10,7 +10,7 @@ import java.security.NoSuchAlgorithmException; ...@@ -10,7 +10,7 @@ import java.security.NoSuchAlgorithmException;
@Singleton @Singleton
public class MessageDigestProvider public class MessageDigestProvider
{ {
private ApplicationConfiguration applicationConfiguration; private final ApplicationConfiguration applicationConfiguration;
@Inject @Inject
public MessageDigestProvider(ApplicationConfiguration applicationConfiguration) public MessageDigestProvider(ApplicationConfiguration applicationConfiguration)
...@@ -21,7 +21,7 @@ public class MessageDigestProvider ...@@ -21,7 +21,7 @@ public class MessageDigestProvider
public MessageDigest getMessageDigest() public MessageDigest getMessageDigest()
{ {
try { try {
return MessageDigest.getInstance(applicationConfiguration.getFlagHashMethod()); return MessageDigest.getInstance(applicationConfiguration.getDigestMethod());
} catch (NoSuchAlgorithmException e) { } catch (NoSuchAlgorithmException e) {
e.printStackTrace(); e.printStackTrace();
} }
......
...@@ -8,7 +8,7 @@ import java.util.List; ...@@ -8,7 +8,7 @@ import java.util.List;
public abstract class Repository<T> public abstract class Repository<T>
{ {
protected Datastore datastore; protected final Datastore datastore;
@Inject @Inject
public Repository(Datastore datastore) public Repository(Datastore datastore)
...@@ -23,7 +23,6 @@ public abstract class Repository<T> ...@@ -23,7 +23,6 @@ public abstract class Repository<T>
public List<T> getAll() public List<T> getAll()
{ {
//todo: unchecked cast
return datastore.createQuery(getRepositoryType()).asList(); return datastore.createQuery(getRepositoryType()).asList();
} }
......
...@@ -3,6 +3,7 @@ package com.telephoners.krakyournet.ctf.repositories; ...@@ -3,6 +3,7 @@ package com.telephoners.krakyournet.ctf.repositories;
import com.telephoners.krakyournet.ctf.beans.Solution; import com.telephoners.krakyournet.ctf.beans.Solution;
import com.telephoners.krakyournet.ctf.beans.Team; import com.telephoners.krakyournet.ctf.beans.Team;
import com.telephoners.krakyournet.ctf.beans.tasks.Task; import com.telephoners.krakyournet.ctf.beans.tasks.Task;
import com.telephoners.krakyournet.ctf.exceptions.SolutionAlreadySubmittedException;
import org.mongodb.morphia.Datastore; import org.mongodb.morphia.Datastore;
import javax.inject.Inject; import javax.inject.Inject;
...@@ -15,7 +16,7 @@ import java.util.stream.Collectors; ...@@ -15,7 +16,7 @@ import java.util.stream.Collectors;
@Singleton @Singleton
public class SolutionsRepository extends Repository<Solution> public class SolutionsRepository extends Repository<Solution>
{ {
private TasksRepository tasksRepository; private final TasksRepository tasksRepository;
@Inject @Inject
public SolutionsRepository(TasksRepository tasksRepository, public SolutionsRepository(TasksRepository tasksRepository,
...@@ -29,7 +30,7 @@ public class SolutionsRepository extends Repository<Solution> ...@@ -29,7 +30,7 @@ public class SolutionsRepository extends Repository<Solution>
{ {
//todo: do not identify team by name? conflict in team ids? //todo: do not identify team by name? conflict in team ids?
return datastore.createQuery(Solution.class) return datastore.createQuery(Solution.class)
.filter("team.name",team.getName()).asList() .filter("team.name", team.getName()).asList()
.stream() .stream()
.collect(Collectors.groupingBy(new Function<Solution, Task>() .collect(Collectors.groupingBy(new Function<Solution, Task>()
{ {
...@@ -48,11 +49,12 @@ public class SolutionsRepository extends Repository<Solution> ...@@ -48,11 +49,12 @@ public class SolutionsRepository extends Repository<Solution>
)); ));
} }
public boolean isAlreadySubmittedSolution(Solution solution) private boolean isAlreadySubmittedSolution(Solution solution)
{ {
return datastore.find(Solution.class) return !datastore.find(Solution.class)
.filter("flag.value", solution.getFlag().getValue()) .filter("flag.value", solution.getFlag().getValue())
.get() != null; .asList()
.isEmpty();
} }
public List<Integer> getCompletedTasks(Team team) public List<Integer> getCompletedTasks(Team team)
...@@ -67,12 +69,11 @@ public class SolutionsRepository extends Repository<Solution> ...@@ -67,12 +69,11 @@ public class SolutionsRepository extends Repository<Solution>
.collect(Collectors.toList()); .collect(Collectors.toList());
} }
public boolean submitSolution(Solution solution) public void submitSolution(Solution solution)
{ {
if (!isAlreadySubmittedSolution(solution)) { if (isAlreadySubmittedSolution(solution)) {
add(solution); throw new SolutionAlreadySubmittedException();
return true;
} }
return false; add(solution);
} }
} }
\ No newline at end of file
package com.telephoners.krakyournet.ctf.repositories; package com.telephoners.krakyournet.ctf.repositories;
import com.telephoners.krakyournet.ctf.beans.Flag;
import com.telephoners.krakyournet.ctf.beans.User;
import com.telephoners.krakyournet.ctf.beans.tasks.Task; import com.telephoners.krakyournet.ctf.beans.tasks.Task;
import com.telephoners.krakyournet.ctf.core.HashValidator; import com.telephoners.krakyournet.ctf.exceptions.TaskNotFoundException;
import com.telephoners.krakyournet.ctf.helpers.DBObjectUtils; import com.telephoners.krakyournet.ctf.helpers.DBObjectUtils;
import javafx.util.Pair;
import org.mongodb.morphia.Datastore; import org.mongodb.morphia.Datastore;
import javax.inject.Inject; import javax.inject.Inject;
import javax.inject.Singleton; import javax.inject.Singleton;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
@Singleton @Singleton
public class TasksRepository extends Repository<Task> public class TasksRepository extends Repository<Task>
{ {
private Datastore datastore; private final Datastore datastore;
private UsersRepository usersRepository;
private HashValidator hashValidator;
@Inject @Inject
public TasksRepository(Datastore datastore, public TasksRepository(Datastore datastore)
UsersRepository usersRepository,
HashValidator hashValidator)
{ {
super(datastore); super(datastore);
this.datastore = datastore; this.datastore = datastore;
this.usersRepository = usersRepository;
this.hashValidator = hashValidator;
} }
public Task getByLevel(int level) public Task getByLevel(int level)
{ {
return datastore.createQuery(Task.class) return datastore.createQuery(Task.class)
.filter("level", level) .filter("level", level)
.get(); .asList()
.stream()
.findFirst()
.orElseThrow(TaskNotFoundException::new);
} }
public List<Task> getAllPublic() public List<Task> getAllPublic()
...@@ -45,24 +37,4 @@ public class TasksRepository extends Repository<Task> ...@@ -45,24 +37,4 @@ public class TasksRepository extends Repository<Task>
.retrievedFields(true, DBObjectUtils.getPublicFields(Task.class)) .retrievedFields(true, DBObjectUtils.getPublicFields(Task.class))
.asList(); .asList();
} }
public Map<Integer, List<String>> getUserFlagsHashes(String username)
{
return getAll().stream()
.collect(Collectors.toMap(
Task::getLevel,
task -> task.getFlags().stream()
.map(flag -> hashValidator.calculateHashValue(usersRepository.getUserByName(username), flag.getValue()))
.collect(Collectors.toList())
));
}
public Pair<Task, Flag> getTaskFlagPairByHashValue(User user, String userHash, int taskLevel)
{
Flag matchedFlag = getByLevel(taskLevel).getFlags().stream()
.filter(flag -> hashValidator.calculateHashValue(user, flag.getValue()).equals(userHash))
.findFirst()
.get();
return new Pair<>(getByLevel(taskLevel), matchedFlag);
}
} }
\ No newline at end of file
...@@ -2,6 +2,7 @@ package com.telephoners.krakyournet.ctf.repositories; ...@@ -2,6 +2,7 @@ package com.telephoners.krakyournet.ctf.repositories;
import com.telephoners.krakyournet.ctf.beans.Team; import com.telephoners.krakyournet.ctf.beans.Team;
import com.telephoners.krakyournet.ctf.beans.User; import com.telephoners.krakyournet.ctf.beans.User;
import com.telephoners.krakyournet.ctf.exceptions.TeamNotFoundException;
import org.mongodb.morphia.Datastore; import org.mongodb.morphia.Datastore;
import javax.inject.Inject; import javax.inject.Inject;
...@@ -11,8 +12,8 @@ import javax.inject.Singleton; ...@@ -11,8 +12,8 @@ import javax.inject.Singleton;
public class TeamsRepository extends Repository<Team> public class TeamsRepository extends Repository<Team>
{ {
private Datastore datastore; private final Datastore datastore;
private UsersRepository usersRepository; private final UsersRepository usersRepository;
@Inject @Inject
public TeamsRepository(Datastore datastore, public TeamsRepository(Datastore datastore,
...@@ -27,7 +28,8 @@ public class TeamsRepository extends Repository<Team> ...@@ -27,7 +28,8 @@ public class TeamsRepository extends Repository<Team>
{ {
return datastore.createQuery(Team.class).asList().stream() return datastore.createQuery(Team.class).asList().stream()
.filter(team -> team.getMembers().contains(user)) .filter(team -> team.getMembers().contains(user))
.findFirst().get(); .findFirst()
.orElseThrow(TeamNotFoundException::new);
} }
public Team getTeamByUserName(String username) public Team getTeamByUserName(String username)
......
...@@ -3,6 +3,7 @@ package com.telephoners.krakyournet.ctf.repositories; ...@@ -3,6 +3,7 @@ package com.telephoners.krakyournet.ctf.repositories;
import com.google.inject.Inject; import com.google.inject.Inject;
import com.google.inject.Singleton; import com.google.inject.Singleton;
import com.telephoners.krakyournet.ctf.beans.User; import com.telephoners.krakyournet.ctf.beans.User;
import com.telephoners.krakyournet.ctf.exceptions.UserNotFoundException;
import com.telephoners.krakyournet.ctf.providers.MessageDigestProvider; import com.telephoners.krakyournet.ctf.providers.MessageDigestProvider;
import io.dropwizard.auth.basic.BasicCredentials; import io.dropwizard.auth.basic.BasicCredentials;
import org.apache.commons.codec.binary.Hex; import org.apache.commons.codec.binary.Hex;
...@@ -11,7 +12,7 @@ import org.mongodb.morphia.Datastore; ...@@ -11,7 +12,7 @@ import org.mongodb.morphia.Datastore;
@Singleton @Singleton
public class UsersRepository extends Repository<User> public class UsersRepository extends Repository<User>
{ {
private MessageDigestProvider messageDigestProvider; private final MessageDigestProvider messageDigestProvider;
@Inject @Inject
public UsersRepository(Datastore datastore, MessageDigestProvider messageDigestProvider) public UsersRepository(Datastore datastore, MessageDigestProvider messageDigestProvider)
...@@ -24,7 +25,10 @@ public class UsersRepository extends Repository<User> ...@@ -24,7 +25,10 @@ public class UsersRepository extends Repository<User>
{ {
return datastore.createQuery(User.class) return datastore.createQuery(User.class)
.field("name").equal(username) .field("name").equal(username)
.get(); .asList()
.stream()
.findFirst()
.orElseThrow(UserNotFoundException::new);
} }
public User authenticateUser(BasicCredentials basicCredentials) public User authenticateUser(BasicCredentials basicCredentials)
......
...@@ -5,12 +5,11 @@ import com.telephoners.krakyournet.ctf.beans.Solution; ...@@ -5,12 +5,11 @@ import com.telephoners.krakyournet.ctf.beans.Solution;
import com.telephoners.krakyournet.ctf.beans.Team; import com.telephoners.krakyournet.ctf.beans.Team;
import com.telephoners.krakyournet.ctf.beans.User; import com.telephoners.krakyournet.ctf.beans.User;
import com.telephoners.krakyournet.ctf.beans.tasks.Task; import com.telephoners.krakyournet.ctf.beans.tasks.Task;
import com.telephoners.krakyournet.ctf.core.HashValidator; import com.telephoners.krakyournet.ctf.exceptions.InvalidSolutionException;
import com.telephoners.krakyournet.ctf.repositories.SolutionsRepository; import com.telephoners.krakyournet.ctf.repositories.SolutionsRepository;
import com.telephoners.krakyournet.ctf.repositories.TasksRepository; import com.telephoners.krakyournet.ctf.repositories.TasksRepository;
import com.telephoners.krakyournet.ctf.repositories.TeamsRepository; import com.telephoners.krakyournet.ctf.repositories.TeamsRepository;
import io.dropwizard.auth.Auth; import io.dropwizard.auth.Auth;
import javafx.util.Pair;
import javax.inject.Inject; import javax.inject.Inject;
import javax.inject.Singleton; import javax.inject.Singleton;
...@@ -26,9 +25,9 @@ import java.util.stream.Collectors; ...@@ -26,9 +25,9 @@ import java.util.stream.Collectors;
@Produces(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON)
public class SolutionsResource public class SolutionsResource
{ {
private TeamsRepository teamsRepository; private final TeamsRepository teamsRepository;
private SolutionsRepository solutionsRepository; private final SolutionsRepository solutionsRepository;
private TasksRepository tasksRepository; private final TasksRepository tasksRepository;
@Inject @Inject
public SolutionsResource(SolutionsRepository solutionsRepository, TasksRepository tasksRepository, public SolutionsResource(SolutionsRepository solutionsRepository, TasksRepository tasksRepository,
...@@ -43,16 +42,18 @@ public class SolutionsResource ...@@ -43,16 +42,18 @@ public class SolutionsResource
@Path("/{task_level}") @Path("/{task_level}")
public Response submitSolution(@Auth User user, public Response submitSolution(@Auth User user,
@PathParam("task_level") int taskLevel, @PathParam("task_level") int taskLevel,
String hash) throws Exception String userFlag) throws Exception
{ {
Pair<Task, Flag> taskFlagPair = tasksRepository.getTaskFlagPairByHashValue(user, hash, taskLevel); Task task = tasksRepository.getByLevel(taskLevel);
if (taskFlagPair != null) { Flag flag = task.getFlags()
if(solutionsRepository.submitSolution(new Solution(teamsRepository.getTeamByUser(user), taskFlagPair.getKey(), taskFlagPair.getValue(), hash))) { .stream()
.filter(taskFlag -> taskFlag.getValue().equals(userFlag))
.findFirst()
.orElseThrow(InvalidSolutionException::new);
solutionsRepository.submitSolution(new Solution(teamsRepository.getTeamByUser(user), task, flag));
return Response.ok().build(); return Response.ok().build();
} }
}
return Response.status(Response.Status.NOT_ACCEPTABLE).build();
}
@GET @GET
@Path("/my/completed") @Path("/my/completed")
...@@ -73,14 +74,6 @@ public class SolutionsResource ...@@ -73,14 +74,6 @@ public class SolutionsResource
)); ));
} }
@GET
@Path("/my")
public Map<Integer, List<String>> getTeamSolutions(@Auth User user)
{
Team team = teamsRepository.getTeamByUser(user);
return solutionsRepository.getTeamSolutions(team);
}
@GET @GET
@Path("/all") @Path("/all")
public Map<String, Map<Integer, List<String>>> getTeamsSolutions() public Map<String, Map<Integer, List<String>>> getTeamsSolutions()
......
...@@ -2,15 +2,8 @@ package com.telephoners.krakyournet.ctf.resources; ...@@ -2,15 +2,8 @@ package com.telephoners.krakyournet.ctf.resources;
import com.telephoners.krakyournet.ctf.beans.User; import com.telephoners.krakyournet.ctf.beans.User;
import com.telephoners.krakyournet.ctf.beans.tasks.Task; import com.telephoners.krakyournet.ctf.beans.tasks.Task;
import com.telephoners.krakyournet.ctf.beans.tasks.TextTask;
import com.telephoners.krakyournet.ctf.beans.tasks.WebTask;
import com.telephoners.krakyournet.ctf.repositories.TasksRepository; import com.telephoners.krakyournet.ctf.repositories.TasksRepository;
import io.dropwizard.auth.Auth; import io.dropwizard.auth.Auth;
import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import javax.inject.Inject; import javax.inject.Inject;
import javax.inject.Singleton; import javax.inject.Singleton;
...@@ -18,18 +11,13 @@ import javax.ws.rs.GET; ...@@ -18,18 +11,13 @@ import javax.ws.rs.GET;
import javax.ws.rs.Path; import javax.ws.rs.Path;
import javax.ws.rs.PathParam; import javax.ws.rs.PathParam;
import javax.ws.rs.core.Response; import javax.ws.rs.core.Response;
import java.io.BufferedReader;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.stream.Collectors;
@Singleton @Singleton
@Path(value = "/task") @Path(value = "/task")
public class TaskResource public class TaskResource
{ {
private final TasksRepository tasksRepository;
protected TasksRepository tasksRepository;
@Inject @Inject
public TaskResource(TasksRepository tasksRepository) public TaskResource(TasksRepository tasksRepository)
...@@ -43,9 +31,6 @@ public class TaskResource ...@@ -43,9 +31,6 @@ public class TaskResource
final @PathParam("task_level") int taskLevel) throws IOException final @PathParam("task_level") int taskLevel) throws IOException
{ {
Task task = tasksRepository.getByLevel(taskLevel); Task task = tasksRepository.getByLevel(taskLevel);
if (task == null) {
return Response.status(Response.Status.BAD_REQUEST).build();
}
return Response.ok().entity(task.getTextForUser(user)).build(); return Response.ok().entity(task.getTextForUser(user)).build();
} }
} }
package com.telephoners.krakyournet.ctf.resources; package com.telephoners.krakyournet.ctf.resources;
import com.telephoners.krakyournet.ctf.beans.User;
import com.telephoners.krakyournet.ctf.beans.tasks.Task; import com.telephoners.krakyournet.ctf.beans.tasks.Task;
import com.telephoners.krakyournet.ctf.repositories.TasksRepository; import com.telephoners.krakyournet.ctf.repositories.TasksRepository;
import io.dropwizard.auth.Auth;
import javax.inject.Inject; import javax.inject.Inject;
import javax.inject.Singleton; import javax.inject.Singleton;
import javax.ws.rs.GET; import javax.ws.rs.GET;
import javax.ws.rs.Path; import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces; import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType; import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import java.util.List; import java.util.List;
@Singleton @Singleton
...@@ -20,7 +16,7 @@ import java.util.List; ...@@ -20,7 +16,7 @@ import java.util.List;
@Produces(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON)
public class TasksResource public class TasksResource
{ {
private TasksRepository tasksRepository; private final TasksRepository tasksRepository;
@Inject @Inject
public TasksResource(TasksRepository tasksRepository) public TasksResource(TasksRepository tasksRepository)
...@@ -33,20 +29,4 @@ public class TasksResource ...@@ -33,20 +29,4 @@ public class TasksResource
{ {
return tasksRepository.getAllPublic(); return tasksRepository.getAllPublic();
} }
@GET
@Path("/{username}")
public Response getUserFlags(@Auth User user, final @PathParam("username") String username)
{
if (user.isAdmin()) {
try {
return Response.ok()
.entity(tasksRepository.getUserFlagsHashes(username))
.build();
} catch (Exception e) {
return Response.status(Response.Status.BAD_REQUEST).build();
}
}
return Response.status(Response.Status.UNAUTHORIZED).build();
}
} }
...@@ -16,7 +16,7 @@ import java.util.List; ...@@ -16,7 +16,7 @@ import java.util.List;
@Produces(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON)
public class TeamsResource public class TeamsResource
{ {
private TeamsRepository teamsRepository; private final TeamsRepository teamsRepository;
@Inject @Inject
public TeamsResource(TeamsRepository teamsRepository) { public TeamsResource(TeamsRepository teamsRepository) {
......
...@@ -24,7 +24,7 @@ import java.io.IOException; ...@@ -24,7 +24,7 @@ import java.io.IOException;
public class UtilResource public class UtilResource
{ {
private TeamsRepository teamsRepository; private final TeamsRepository teamsRepository;
@Inject @Inject
public UtilResource(TeamsRepository teamsRepository) public UtilResource(TeamsRepository teamsRepository)
......
...@@ -3,4 +3,4 @@ ...@@ -3,4 +3,4 @@
</div> </div>
<div style="text-align:center;width:100%">made with <i class="fa fa-heart"></i> by <a <div style="text-align:center;width:100%">made with <i class="fa fa-heart"></i> by <a
href="http://telephoners.agh.edu.pl" id="telephoners"><img href="http://telephoners.agh.edu.pl" id="telephoners"><img
src="/statics/img/logo_telephoners.svg"></img></a></div> src="/statics/img/logo_telephoners.svg"></a></div>
\ No newline at end of file \ No newline at end of file
test - sprawdzic czy zadanie jest oznaczone jako zakonczone po zakomitowaniu wszystkich jego flag przez jedna druzyne
\ No newline at end of file
{
"name": "Example scenario",
"description": "This is an example scenario.",
"url": "http://google.com/",
"method": "GET",
"user": {
"login":,
"password":,
},
"payload": {},
"expected_output": {}
}
import requests
import json
import os
SCENARIOS_PATH = "scenarios/";
class Test:
def __init__(self):
self.scenarios = []
def run(self):
for scenario in self.scenarios:
if scenario.get("method") == "GET":
self.send_get_request(scenario)
elif scenario.get("method") == "POST":
self.send_post_request(scenario)
else:
print "Skipping ", scenario["name"], " please specify request method."
def load_test_scenarios(self, scenarios_path):
scenario_names = [scenario_file for scenario_file in os.listdir(scenarios_path) if scenario_file.endswith('.json')]
for scenario_name in scenario_names:
with open(os.path.join(scenarios_path, scenario_name)) as scenario_file:
self.scenarios.append(json.load(scenario_file))
def send_get_request(self, scenario):
if scenario.get("user"):
auth = (scenario["user"]["login"], scenario["user"]["password"])
else:
auth = None
try:
res = requests.get(scenario["url"], auth=auth)
except Exception:
print "Test {0} failed!".format(scenario["name"])
return
if res.status_code == 200:
if scenario.get("expected_output") != None:
if scenario.get("expected_output") == res.json():
print "Test {0} OK!".format(scenario["name"])
else:
print "Test {0}, expected {1} but got {2}!".format(scenario["name"],
scenario["expected_output"], res.json())
else:
print "Test {0} OK!".format(scenario["name"])
else:
print "Test {0} failed!".format(scenario["name"])
def send_post_request(self, scenario):
if scenario.get("user"):
auth = (scenario["user"]["login"], scenario["user"]["password"])
else:
auth = None
res = requests.post(scenario["url"], auth=auth, data=scenario.get("payload"))
if res.status_code == 200:
if scenario.get("expected_output") != None:
if scenario.get("expected_output") == res.json():
print "Test {0} OK!".format(scenario["name"])
else:
print "Test {0}, expected {1} but got {2}!".format(scenario["name"],
scenario["expected_output"], res.json())
else:
print "Test {0} OK!".format(scenario["name"])
else:
print "Test {0} failed!".format(scenario["name"])
file_path = os.path.join(os.path.dirname(__file__), SCENARIOS_PATH)
test = Test()
test.load_test_scenarios(file_path)
test.run()
{
"name": "'Auth api' is up",
"description": "This scenario checks if auth api is up and working",
"url": "http://localhost:8080/api/v1/auth",
"method": "GET",
"user": {
"login":"rosiu1",
"password":"rosiu321"
}
}
{
"name": "'Login' page is up",
"description": "Checks if login page is up",
"method": "GET",
"url": "http://localhost:8080/"
}
{
"name": "'Solutions completed' page is up",
"description": "Checks if solutions completed returns empty list",
"method": "GET",
"url": "http://localhost:8080/api/v1/solutions/completed",
"expected_output": [],
"user": {
"login":"rosiu1",
"password": "rosiu321"
}
}
{
"name": "'My solutions' page is up",
"description": "Checks if my solutions retuns empty object",
"method": "GET",
"url": "http://localhost:8080/api/v1/solutions/completed",
"user": {
"login": "rosiu1",
"password": "rosiu321"
}
}
{
"name": "'Submit flag'",
"description": "Submits flag, if test wil be ran 2 times without pruging database it will fail (one flag cannot be submited more that once)",
"url": "http://localhost:8080/api/v1/solutions/1/",
"method": "POST",
"user": {
"login":"rosiu1",
"password":"rosiu321"
},
"payload": "AGH_sdfg1f1"
}
{
"name": "'Tasks' api page is up",
"description": "This scenario checks if tasks endpoint is up and working.",
"url": "http://localhost:8080/api/v1/tasks",
"method": "GET",
"expected_output": [{"name":"Szyfro1","level":1},{"name":"Szyfro2","level":2},{"name":"SQL Injection","level":3},{"name":"Inna dziura","level":4}]
}
{
"name": "'Teams' page is up",
"description": "This is scenario checks if teams resources have been correctly populated.",
"url": "http://localhost:8080/api/v1/teams",
"method": "GET",
"expected_output": [{"name":"misiaczki","description":"misiaczki opis","members":[{"name":"gpietrus1","password":"41b450e73c974fca46911eba84e114f2","email":"gpietrusza@gmail.com","admin":false},{"name":"mehow1","password":"c4d24515428cb3ad50e7840be8718f23","email":"mehow@gmail.com","admin":false},{"name":"rosiu1","password":"188ed9df2dac8e10f5c5fd2e02383765","email":"rosiu@gmail.com","admin":false},{"name":"anteq1","password":"1a7fcdd5a9fd433523268883cfded9d0","email":"antonigrzanka@gmail.com","admin":false}]},{"name":"prosiaczki","description":"prosiaczki opis","members":[{"name":"gpietrus2","password":"41b450e73c974fca46911eba84e114f2","email":"gpietrusza@gmail.com","admin":false},{"name":"mehow2","password":"c4d24515428cb3ad50e7840be8718f23","email":"mehow@gmail.com","admin":false},{"name":"rosiu2","password":"188ed9df2dac8e10f5c5fd2e02383765","email":"rosiu@gmail.com","admin":false},{"name":"anteq2","password":"1a7fcdd5a9fd433523268883cfded9d0","email":"antonigrzanka@gmail.com","admin":false}]},{"name":"dupeczki","description":"dupeczki opis","members":[{"name":"gpietrus3","password":"41b450e73c974fca46911eba84e114f2","email":"gpietrusza@gmail.com","admin":false},{"name":"mehow3","password":"c4d24515428cb3ad50e7840be8718f23","email":"mehow@gmail.com","admin":false},{"name":"rosiu3","password":"188ed9df2dac8e10f5c5fd2e02383765","email":"rosiu@gmail.com","admin":false},{"name":"anteq3","password":"1a7fcdd5a9fd433523268883cfded9d0","email":"antonigrzanka@gmail.com","admin":false}]}]
}
{
"name": "'Who am I' is up",
"description": "This is scenario checks if who_am_i endpoint is up and working",
"url": "http://localhost:8080/api/v1/whoami",
"method": "GET",
"user": {
"login":"rosiu1",
"password": "rosiu321"
},
"expected_output": {"userName":"rosiu1","teamName":"misiaczki"}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment