Skip to content

Commit

Permalink
Merge branch 'release/0.10.4'
Browse files Browse the repository at this point in the history
  • Loading branch information
Brutus5000 committed Dec 17, 2017
2 parents 285fddd + 8259cf5 commit c9d1fc5
Show file tree
Hide file tree
Showing 26 changed files with 676 additions and 84 deletions.
2 changes: 1 addition & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ before_install:
install:
- git clone https://github.com/FAForever/faf-stack.git faf-stack
&& pushd faf-stack
&& git checkout c69c675
&& git checkout 1a37706
&& cp -r config.template config
&& popd
- docker-compose -f faf-stack/docker-compose.yml up -d faf-db
Expand Down
2 changes: 1 addition & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ apply plugin: 'propdeps'
apply plugin: 'idea'

group = 'faforever'
version = '0.10.3'
version = '0.10.4'

sourceCompatibility = 1.8
targetCompatibility = 1.8
Expand Down
87 changes: 87 additions & 0 deletions src/inttest/java/com/faforever/api/data/DomainBlacklistTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
package com.faforever.api.data;

import com.faforever.api.AbstractIntegrationTest;
import org.junit.Test;
import org.springframework.security.test.context.support.WithUserDetails;
import org.springframework.test.context.jdbc.Sql;
import org.springframework.test.context.jdbc.Sql.ExecutionPhase;

import static org.hamcrest.Matchers.hasSize;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;

@Sql(executionPhase = ExecutionPhase.BEFORE_TEST_METHOD, scripts = "classpath:sql/prepDefaultUser.sql")
@Sql(executionPhase = ExecutionPhase.BEFORE_TEST_METHOD, scripts = "classpath:sql/prepDomainBlacklistData.sql")
@Sql(executionPhase = ExecutionPhase.AFTER_TEST_METHOD, scripts = "classpath:sql/cleanDomainBlacklistData.sql")
public class DomainBlacklistTest extends AbstractIntegrationTest {
private static final String NEW_DOMAIN = "{\"data\":{\"type\":\"domainBlacklist\",\"id\":\"google.com\"}}";

@Test
@WithUserDetails(AUTH_USER)
public void emptyResultDomainBlacklistAsUser() throws Exception {
mockMvc.perform(get("/data/domainBlacklist"))
.andExpect(status().isOk())
.andExpect(content().string("{\"data\":[]}"));
}

@Test
@WithUserDetails(AUTH_USER)
public void cannotReadSpecificDomainBlacklistAsUser() throws Exception {
mockMvc.perform(get("/data/domainBlacklist/spam.org"))
.andExpect(status().isForbidden());
}

@Test
@WithUserDetails(AUTH_MODERATOR)
public void canReadDomainBlacklistAsModerator() throws Exception {
mockMvc.perform(get("/data/domainBlacklist"))
.andExpect(status().isOk())
.andExpect(jsonPath("$.data", hasSize(1)));
}

@Test
@WithUserDetails(AUTH_MODERATOR)
public void canReadSpecificDomainBlacklistAsModerator() throws Exception {
mockMvc.perform(get("/data/domainBlacklist/spam.org"))
.andExpect(status().isOk());
}


@Test
@WithUserDetails(AUTH_USER)
public void cannotCreateDomainBlacklistAsUser() throws Exception {
mockMvc.perform(
post("/data/domainBlacklist")
.content(NEW_DOMAIN))
.andExpect(status().isForbidden());
}

@Test
@WithUserDetails(AUTH_MODERATOR)
public void canCreateDomainBlacklistAsModerator() throws Exception {
mockMvc.perform(
post("/data/domainBlacklist")
.content(NEW_DOMAIN))
.andExpect(status().isCreated());
}

@Test
@WithUserDetails(AUTH_USER)
public void cannotDeleteDomainBlacklistAsUser() throws Exception {
mockMvc.perform(
delete("/data/domainBlacklist/spam.org"))
.andExpect(status().isForbidden());
}

@Test
@WithUserDetails(AUTH_MODERATOR)
public void canDeleteDomainBlacklistAsModerator() throws Exception {
mockMvc.perform(
delete("/data/domainBlacklist/spam.org"))
.andExpect(status().isNoContent());
}
}
102 changes: 102 additions & 0 deletions src/inttest/java/com/faforever/api/data/UserNoteTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
package com.faforever.api.data;

import com.faforever.api.AbstractIntegrationTest;
import com.faforever.api.player.PlayerRepository;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.test.context.support.WithUserDetails;
import org.springframework.test.context.jdbc.Sql;
import org.springframework.test.context.jdbc.Sql.ExecutionPhase;

import static org.hamcrest.Matchers.hasSize;
import static org.hamcrest.core.Is.is;
import static org.junit.Assert.assertThat;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;

@Sql(executionPhase = ExecutionPhase.BEFORE_TEST_METHOD, scripts = "classpath:sql/prepDefaultUser.sql")
@Sql(executionPhase = ExecutionPhase.BEFORE_TEST_METHOD, scripts = "classpath:sql/prepUserNoteData.sql")
@Sql(executionPhase = ExecutionPhase.AFTER_TEST_METHOD, scripts = "classpath:sql/cleanUserNoteData.sql")
public class UserNoteTest extends AbstractIntegrationTest {
/*
{
"data": {
"type": "userNote",
"attributes": {
"watched": false,
"note": "This note will be posted"
},
"relationships": {
"author": {
"data": {
"type": "player",
"id": "1"
}
},
"player": {
"data": {
"type": "player",
"id": "3"
}
}
}
}
}
*/
private static final String testPost = "{\"data\":{\"type\":\"userNote\",\"attributes\":{\"watched\":false,\"note\":\"This note will be posted\"},\"relationships\":{\"author\":{\"data\":{\"type\":\"player\",\"id\":\"1\"}},\"player\":{\"data\":{\"type\":\"player\",\"id\":\"3\"}}}}}";
@Autowired
PlayerRepository playerRepository;

@Test
@WithUserDetails(AUTH_USER)
public void emptyResultUserNoteAsUser() throws Exception {
mockMvc.perform(get("/data/userNote"))
.andExpect(status().isOk())
.andExpect(content().string("{\"data\":[]}"));
}

@Test
@WithUserDetails(AUTH_USER)
public void cannotReadSpecificUserNoteAsUser() throws Exception {
mockMvc.perform(get("/data/userNote/1"))
.andExpect(status().isForbidden());
}

@Test
@WithUserDetails(AUTH_USER)
public void cannotCreateUserNoteAsUser() throws Exception {
mockMvc.perform(post("/data/userNote")
.content(testPost))
.andExpect(status().isForbidden());
}

@Test
@WithUserDetails(AUTH_MODERATOR)
public void canReadUserNoteAsModerator() throws Exception {
mockMvc.perform(get("/data/userNote"))
.andExpect(status().isOk())
.andExpect(jsonPath("$.data", hasSize(1)));
}

@Test
@WithUserDetails(AUTH_MODERATOR)
public void canReadSpecificUserNoteAsModerator() throws Exception {
mockMvc.perform(get("/data/userNote/1"))
.andExpect(status().isOk());
}

@Test
@WithUserDetails(AUTH_MODERATOR)
public void canCreateUserNoteAsModerator() throws Exception {
assertThat(playerRepository.getOne(3).getUserNotes().size(), is(0));

mockMvc.perform(post("/data/userNote")
.content(testPost))
.andExpect(status().isCreated());

assertThat(playerRepository.getOne(3).getUserNotes().size(), is(1));
}
}
64 changes: 64 additions & 0 deletions src/inttest/java/com/faforever/api/user/UserControllerTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,70 @@ public void changePasswordWithWrongPassword() throws Exception {
assertApiError(mvcResult, ErrorCode.PASSWORD_CHANGE_FAILED_WRONG_PASSWORD);
}

@Test
@WithUserDetails(AUTH_USER)
public void changeEmailWithSuccess() throws Exception {
MultiValueMap<String, String> params = new HttpHeaders();
params.add("currentPassword", AUTH_USER);
params.add("newEmail", NEW_EMAIL);

mockMvc.perform(
post("/users/changeEmail")
.with(getOAuthToken(OAuthScope._WRITE_ACCOUNT_DATA))
.params(params))
.andExpect(status().isOk());

User user = userRepository.findOneByLoginIgnoreCase(AUTH_USER).get();
assertEquals(user.getEmail(), NEW_EMAIL);
}

@Test
@WithUserDetails(AUTH_USER)
public void changeEmailWithWrongScope() throws Exception {
MultiValueMap<String, String> params = new HttpHeaders();
params.add("currentPassword", AUTH_USER);
params.add("newEmail", NEW_EMAIL);

mockMvc.perform(
post("/users/changeEmail")
.params(params))
.andExpect(status().isForbidden());
}

@Test
@WithUserDetails(AUTH_USER)
public void changeEmailWithWrongPassword() throws Exception {
MultiValueMap<String, String> params = new HttpHeaders();
params.add("currentPassword", "wrongPassword");
params.add("newEmail", NEW_EMAIL);

MvcResult mvcResult = mockMvc.perform(
post("/users/changeEmail")
.with(getOAuthToken(OAuthScope._WRITE_ACCOUNT_DATA))
.params(params))
.andExpect(status().is4xxClientError())
.andReturn();

assertApiError(mvcResult, ErrorCode.EMAIL_CHANGE_FAILED_WRONG_PASSWORD);
}

@Test
@WithUserDetails(AUTH_USER)
public void changeEmailWithInvalidEmail() throws Exception {
MultiValueMap<String, String> params = new HttpHeaders();
params.add("currentPassword", AUTH_USER);
params.add("newEmail", "invalid-email");

MvcResult mvcResult = mockMvc.perform(
post("/users/changeEmail")
.with(getOAuthToken(OAuthScope._WRITE_ACCOUNT_DATA))
.params(params))
.andExpect(status().is4xxClientError())
.andReturn();

assertApiError(mvcResult, ErrorCode.EMAIL_INVALID);
}

@Test
@WithAnonymousUser
public void resetPasswordWithUsername() throws Exception {
Expand Down
1 change: 1 addition & 0 deletions src/inttest/resources/sql/cleanDomainBlacklistData.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
DELETE FROM email_domain_blacklist;
1 change: 1 addition & 0 deletions src/inttest/resources/sql/cleanUserNoteData.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
DELETE FROM user_notes;
1 change: 1 addition & 0 deletions src/inttest/resources/sql/prepDefaultUser.sql
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ DELETE FROM teamkills;
DELETE FROM ladder_division_score;
DELETE FROM ladder_division;
DELETE FROM lobby_admin;
DELETE FROM user_notes;
DELETE FROM login;

INSERT INTO oauth_clients (id, name, client_secret, client_type, redirect_uris, default_redirect_uri, default_scope)
Expand Down
2 changes: 2 additions & 0 deletions src/inttest/resources/sql/prepDomainBlacklistData.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
DELETE FROM email_domain_blacklist;
INSERT INTO email_domain_blacklist VALUES ('spam.org');
8 changes: 8 additions & 0 deletions src/inttest/resources/sql/prepUserNoteData.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
DELETE FROM ban_revoke;
DELETE FROM ban;

INSERT INTO login (id, login, email, password) VALUES
(4, 'BANNED', 'banned@faforever.com', 'not relevant');

INSERT INTO user_notes (id, user_id, author, watched, note) VALUES
(1, 4, 1, 0, 'Test user note');
Original file line number Diff line number Diff line change
Expand Up @@ -39,11 +39,11 @@ public Docket newsApi() {

private ApiInfo apiInfo() {
return new ApiInfoBuilder()
.title("Forged Alliance Forever API (Prototype)")
.description("A prototype of a Java-based API for Forged Alliance Forever")
.contact(new Contact("Downlord", "https://github.com/micheljung", "downlord@faforever.com"))
.title("Forged Alliance Forever API")
.description("The official API for Forged Alliance Forever")
.contact(new Contact("Downlord", "https://github.com/FAForever/faf-java-api", "downlord@faforever.com"))
.license("MIT")
.licenseUrl("https://github.com/micheljung/faf-java-api/blob/develop/LICENSE")
.licenseUrl("https://github.com/FAForever/faf-java-api/blob/develop/LICENSE")
.version(fafApiProperties.getVersion())
.build();
}
Expand All @@ -58,6 +58,7 @@ private Predicate<String> paths() {
regex("/events/.*"),
regex("/users/.*"),
regex("/mods/.*"),
regex("/maps/.*"));
regex("/maps/.*"),
regex("/leaderboards/.*"));
}
}
15 changes: 14 additions & 1 deletion src/main/java/com/faforever/api/data/domain/DomainBlacklist.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
package com.faforever.api.data.domain;

import com.faforever.api.data.checks.permission.IsModerator;
import com.yahoo.elide.annotation.Audit;
import com.yahoo.elide.annotation.Audit.Action;
import com.yahoo.elide.annotation.CreatePermission;
import com.yahoo.elide.annotation.DeletePermission;
import com.yahoo.elide.annotation.Include;
import com.yahoo.elide.annotation.ReadPermission;
import com.yahoo.elide.annotation.UpdatePermission;
import lombok.EqualsAndHashCode;
import lombok.Setter;

Expand All @@ -12,7 +19,13 @@
@Entity
@Setter
@Table(name = "email_domain_blacklist")
@Include(type = "domainBlacklist")
@Include(type = "domainBlacklist", rootLevel = true)
@ReadPermission(expression = IsModerator.EXPRESSION)
@UpdatePermission(expression = IsModerator.EXPRESSION)
@CreatePermission(expression = IsModerator.EXPRESSION)
@DeletePermission(expression = IsModerator.EXPRESSION)
@Audit(action = Action.CREATE, logStatement = "Email domain `{0}` added to blacklist", logExpressions = "${domainBlacklist.domain}")
@Audit(action = Action.DELETE, logStatement = "Email domain `{0}` removed from blacklist", logExpressions = "${domainBlacklist.domain}")
@EqualsAndHashCode
public class DomainBlacklist {
private String domain;
Expand Down
16 changes: 6 additions & 10 deletions src/main/java/com/faforever/api/data/domain/Game.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.OneToOne;
import javax.persistence.Table;
import javax.persistence.Transient;
import java.time.OffsetDateTime;
Expand All @@ -43,8 +44,7 @@ public class Game {
private List<GamePlayerStats> playerStats;
private String replayUrl;
private List<GameReview> reviews;
private int numberOfReviews;
private float averageReviewScore;
private GameReviewsSummary reviewsSummary;

@Id
@Column(name = "id")
Expand Down Expand Up @@ -114,13 +114,9 @@ public List<GameReview> getReviews() {
return reviews;
}

@Column(name = "reviews")
public int getNumberOfReviews() {
return numberOfReviews;
}

@Column(name = "average_review_score")
public float getAverageReviewScore() {
return averageReviewScore;
@OneToOne(mappedBy = "game")
@UpdatePermission(expression = "Prefab.Role.All")
public GameReviewsSummary getReviewsSummary() {
return reviewsSummary;
}
}

0 comments on commit c9d1fc5

Please sign in to comment.