Skip to content

Commit

Permalink
Merge pull request #110 from Arquisoft/rest-api
Browse files Browse the repository at this point in the history
Rest api, updates on page style
  • Loading branch information
uo287545 authored Mar 5, 2024
2 parents f8e2673 + 778a18d commit 18e2795
Show file tree
Hide file tree
Showing 36 changed files with 1,017 additions and 46 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import com.fasterxml.jackson.databind.JsonNode;
import com.uniovi.services.CategoryService;
import org.springframework.scheduling.annotation.Scheduled;

import java.util.ArrayList;
import java.util.List;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.web.servlet.LocaleResolver;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
Expand All @@ -11,6 +12,7 @@
import java.util.Locale;

@Configuration
@EnableScheduling
public class CustomConfiguration implements WebMvcConfigurer {
@Bean
public LocaleResolver localeResolver() {
Expand Down
1 change: 1 addition & 0 deletions src/main/java/com/uniovi/configuration/SecurityConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
.requestMatchers("/css/**", "/img/**", "/script/**").permitAll()
.requestMatchers("/home").authenticated()
.requestMatchers("/signup/**").permitAll()
.requestMatchers("/api/**").permitAll()
.requestMatchers("/**").permitAll()
).formLogin(
form -> form
Expand Down
5 changes: 5 additions & 0 deletions src/main/java/com/uniovi/controllers/HomeController.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,9 @@ public HomeController(PlayerService playerService) {
public String home(){
return "index";
}

@GetMapping("/api")
public String apiHome() {
return "api/apiHome";
}
}
89 changes: 89 additions & 0 deletions src/main/java/com/uniovi/controllers/RestApiController.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
package com.uniovi.controllers;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.uniovi.entities.*;
import com.uniovi.repositories.GameSessionRepository;
import com.uniovi.services.ApiKeyService;
import com.uniovi.services.RestApiService;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.lang.reflect.Array;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;

@RestController
public class RestApiController {
private final ApiKeyService apiKeyService;
private final RestApiService restApiService;

@Autowired
public RestApiController(ApiKeyService apiKeyService, RestApiService restApiService) {
this.apiKeyService = apiKeyService;
this.restApiService = restApiService;
}

@GetMapping("/api/players")
public String getPlayers(HttpServletResponse response, @RequestParam Map<String, String> params) throws JsonProcessingException {
response.setContentType("application/json");
ApiKey apiKey = getApiKeyFromParams(params);
if (apiKey == null) {
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
ObjectMapper objectMapper = new ObjectMapper();
Map<String, String> error = Map.of("error", "Invalid API key");
return objectMapper.writeValueAsString(error);
}

List<Player> players = restApiService.getPlayers(params);
ObjectMapper objectMapper = new ObjectMapper();
ObjectNode root = objectMapper.createObjectNode();
ArrayNode arrayNode = objectMapper.createArrayNode();
for (Player player : players) {
arrayNode.add(player.toJson());
}
root.put("players", arrayNode);
restApiService.logAccess(apiKey, "/api/players", params);
return root.toString();
}

@GetMapping("/api/questions")
public String getQuestions(HttpServletResponse response, @RequestParam Map<String, String> params) throws JsonProcessingException {
response.setContentType("application/json");
ApiKey apiKey = getApiKeyFromParams(params);
if (apiKey == null) {
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
ObjectMapper objectMapper = new ObjectMapper();
Map<String, String> error = Map.of("error", "Invalid API key");
return objectMapper.writeValueAsString(error);
}

ObjectMapper objectMapper = new ObjectMapper();
ObjectNode root = objectMapper.createObjectNode();
ArrayNode arrayNode = objectMapper.createArrayNode();
List<Question> questions = restApiService.getQuestions(params);
for (Question question : questions) {
arrayNode.add(question.toJson());
}
root.set("questions", arrayNode);
restApiService.logAccess(apiKey, "/api/questions", params);
return root.toString();
}

private ApiKey getApiKeyFromParams(Map<String, String> params) {
if (!params.containsKey("apiKey")) {
return null;
}

String apiKey = params.get("apiKey");
return apiKeyService.getApiKey(apiKey);
}
}
16 changes: 15 additions & 1 deletion src/main/java/com/uniovi/entities/Answer.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
package com.uniovi.entities;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.uniovi.interfaces.JsonEntity;
import jakarta.persistence.*;
import lombok.Getter;
import lombok.NoArgsConstructor;
Expand All @@ -9,7 +13,7 @@
@Setter
@Entity
@NoArgsConstructor
public class Answer {
public class Answer implements JsonEntity {

@Id
@GeneratedValue
Expand All @@ -30,4 +34,14 @@ public String toString() {
return text;
}

@Override
public JsonNode toJson() {
ObjectMapper mapper = new ObjectMapper();
ObjectNode obj = mapper.createObjectNode();
obj .put("id", id)
.put("text", text)
.put("correct", correct)
.put("question", question.getId());
return obj;
}
}
29 changes: 29 additions & 0 deletions src/main/java/com/uniovi/entities/ApiKey.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package com.uniovi.entities;

import jakarta.persistence.*;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;

import java.util.HashSet;
import java.util.Set;
import java.util.UUID;

@Entity
@Getter
@Setter
@NoArgsConstructor
public class ApiKey {
@Id
@GeneratedValue
private Long id;

@Column(unique = true)
private String keyToken = UUID.randomUUID().toString();

@OneToOne
private Player player;

@OneToMany(mappedBy = "apiKey")
private Set<RestApiAccessLog> accessLogs = new HashSet<>();
}
107 changes: 105 additions & 2 deletions src/main/java/com/uniovi/entities/Associations.java
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
package com.uniovi.entities;
import java.util.*;

public class Associations {
public static class PlayerRole {
/**
* Add a new association between a player and a role
*
* @param player The player
* @param role The role
* @param role The role
*/
public static void addRole(Player player, Role role) {
role.getPlayers().add(player);
Expand All @@ -14,12 +16,113 @@ public static void addRole(Player player, Role role) {

/**
* Remove an association between a player and a role
*
* @param player The player
* @param role The role
* @param role The role
*/
public static void removeRole(Player player, Role role) {
role.getPlayers().remove(player);
player.getRoles().remove(role);
}
}

public static class PlayerApiKey {
/**
* Add a new association between a player and an API key
*
* @param player The player
* @param apiKey The API key
*/
public static void addApiKey(Player player, ApiKey apiKey) {
apiKey.setPlayer(player);
player.setApiKey(apiKey);
}

/**
* Remove an association between a player and an API key
*
* @param player The player
* @param apiKey The API key
*/
public static void removeApiKey(Player player, ApiKey apiKey) {
apiKey.setPlayer(null);
player.setApiKey(null);
}
}

public static class ApiKeyAccessLog {
/**
* Add a new association between an API key and an access log
*
* @param apiKey The API key
* @param accessLog The access log
*/
public static void addAccessLog(ApiKey apiKey, RestApiAccessLog accessLog) {
accessLog.setApiKey(apiKey);
apiKey.getAccessLogs().add(accessLog);
}

/**
* Remove an association between an API key and an access log
*
* @param apiKey The API key
* @param accessLog The access log
*/
public static void removeAccessLog(ApiKey apiKey, RestApiAccessLog accessLog) {
apiKey.getAccessLogs().remove(accessLog);
accessLog.setApiKey(null);
}
}

public static class PlayerGameSession {
/**
* Add a new association between a player and a game session
*
* @param player The player
* @param gameSession The game session
*/
public static void addGameSession(Player player, GameSession gameSession) {
gameSession.setPlayer(player);
player.getGameSessions().add(gameSession);
}

/**
* Remove an association between a player and a game session
*
* @param player The player
* @param gameSession The game session
*/
public static void removeGameSession(Player player, GameSession gameSession) {
player.getGameSessions().remove(gameSession);
gameSession.setPlayer(null);
}
}

public static class QuestionAnswers {
/**
* Add a new association between a question and an answer
*
* @param question The question
* @param answer The answer
*/
public static void addAnswer(Question question, List<Answer> answer) {
for (Answer a : answer) {
a.setQuestion(question);
}
question.getOptions().addAll(answer);
}

/**
* Remove an association between a question and an answer
*
* @param question The question
* @param answer The answer
*/
public static void removeAnswer(Question question, List<Answer> answer) {
question.getOptions().remove(answer);
for (Answer a : answer) {
a.setQuestion(null);
}
}
}
}
19 changes: 18 additions & 1 deletion src/main/java/com/uniovi/entities/Category.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
package com.uniovi.entities;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.uniovi.interfaces.JsonEntity;
import jakarta.persistence.*;
import lombok.Getter;
import lombok.NoArgsConstructor;
Expand All @@ -12,7 +15,7 @@
@Setter
@Entity
@NoArgsConstructor
public class Category {
public class Category implements JsonEntity {

@Id
@GeneratedValue
Expand All @@ -29,4 +32,18 @@ public Category(String name, String description) {
this.name = name;
this.description = description;
}

@Override
public String toString() {
return name;
}

@Override
public JsonNode toJson() {
ObjectMapper mapper = new ObjectMapper();
return mapper.createObjectNode()
.put("id", id)
.put("name", name)
.put("description", description);
}
}
Loading

0 comments on commit 18e2795

Please sign in to comment.