getReviews() {
return reviews;
}
@OneToOne(fetch = FetchType.LAZY)
@PrimaryKeyJoinColumn
- @UpdatePermission(expression = "Prefab.Role.All")
+ @UpdatePermission(expression = Prefab.ALL)
@BatchSize(size = 1000)
public GameReviewsSummary getReviewsSummary() {
return reviewsSummary;
diff --git a/src/main/java/com/faforever/api/data/domain/GameReview.java b/src/main/java/com/faforever/api/data/domain/GameReview.java
index 45c4862f2..61378d305 100644
--- a/src/main/java/com/faforever/api/data/domain/GameReview.java
+++ b/src/main/java/com/faforever/api/data/domain/GameReview.java
@@ -1,6 +1,7 @@
package com.faforever.api.data.domain;
import com.faforever.api.data.checks.IsEntityOwner;
+import com.faforever.api.data.checks.Prefab;
import com.yahoo.elide.annotation.CreatePermission;
import com.yahoo.elide.annotation.DeletePermission;
import com.yahoo.elide.annotation.Include;
@@ -17,7 +18,7 @@
@Include(rootLevel = true, type = "gameReview")
@Entity
@Table(name = "game_review")
-@CreatePermission(expression = "Prefab.Role.All")
+@CreatePermission(expression = Prefab.ALL)
@DeletePermission(expression = IsEntityOwner.EXPRESSION)
public class GameReview extends Review {
@@ -25,7 +26,7 @@ public class GameReview extends Review {
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "game_id")
- @UpdatePermission(expression = "Prefab.Role.All and Prefab.Common.UpdateOnCreate")
+ @UpdatePermission(expression = Prefab.ALL_AND_UPDATE_ON_CREATE)
public Game getGame() {
return game;
}
diff --git a/src/main/java/com/faforever/api/data/domain/GroupPermission.java b/src/main/java/com/faforever/api/data/domain/GroupPermission.java
new file mode 100644
index 000000000..62545f662
--- /dev/null
+++ b/src/main/java/com/faforever/api/data/domain/GroupPermission.java
@@ -0,0 +1,86 @@
+package com.faforever.api.data.domain;
+
+import com.faforever.api.data.checks.permission.IsModerator;
+import com.yahoo.elide.annotation.Include;
+import com.yahoo.elide.annotation.ReadPermission;
+import lombok.Setter;
+import org.springframework.security.core.GrantedAuthority;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.ManyToMany;
+import javax.persistence.Table;
+import javax.persistence.Transient;
+import java.util.Set;
+
+/**
+ * Naming conventions on permission roles
+ *
+ * General structure: ROLE_{ACTION}_{AREA}
+ *
+ * - {AREA} defines a set of use cases (i.e. BAN)
+ *
- {ACTION} being WRITE, READ or ADMIN
+ *
WRITE grants permission to create / add / upload new data
+ *
READ grants global read permissions
+ *
ADMIN refer to read and write permissions in global context regardless of the ownership
+ *
+ *
+ * For read and write permissions of data personally owned by user see {@link OwnableEntity}
+ */
+@Entity
+@Table(name = "group_permission")
+@Include(rootLevel = true, type = "groupPermission")
+@Setter
+@ReadPermission(expression = IsModerator.EXPRESSION)
+public class GroupPermission extends AbstractEntity implements GrantedAuthority {
+
+ // Any changes to the permissions here need to be added to the dto class as well!
+ public static final String ROLE_READ_AUDIT_LOG = "ROLE_READ_AUDIT_LOG";
+ public static final String ROLE_READ_TEAMKILL_REPORT = "ROLE_READ_TEAMKILL_REPORT";
+ public static final String ROLE_READ_ACCOUNT_PRIVATE_DETAILS = "ROLE_READ_ACCOUNT_PRIVATE_DETAILS";
+ public static final String ROLE_ADMIN_ACCOUNT_NOTE = "ROLE_ADMIN_ACCOUNT_NOTE";
+ public static final String ROLE_ADMIN_MODERATION_REPORT = "ROLE_ADMIN_MODERATION_REPORT";
+ public static final String ROLE_ADMIN_ACCOUNT_BAN = "ROLE_ADMIN_ACCOUNT_BAN";
+ public static final String ROLE_ADMIN_CLAN = "ROLE_ADMIN_CLAN";
+ public static final String ROLE_WRITE_MAP = "ROLE_WRITE_MAP";
+ public static final String ROLE_WRITE_MOD = "ROLE_WRITE_MOD";
+ public static final String ROLE_WRITE_COOP_MISSION = "ROLE_WRITE_COOP_MISSION";
+ public static final String ROLE_WRITE_AVATAR = "ROLE_WRITE_AVATAR";
+ public static final String ROLE_WRITE_MATCHMAKER_POOL = "ROLE_WRITE_MATCHMAKER_POOL";
+ public static final String ROLE_WRITE_MATCHMAKER_MAP = "ROLE_WRITE_MATCHMAKER_MAP";
+ public static final String ROLE_WRITE_EMAIL_DOMAIN_BAN = "ROLE_WRITE_EMAIL_DOMAIN_BAN";
+ public static final String ROLE_ADMIN_VOTE = "ROLE_ADMIN_VOTE";
+ public static final String ROLE_WRITE_USER_GROUP = "ROLE_WRITE_USER_GROUP";
+ public static final String ROLE_READ_USER_GROUP = "ROLE_READ_USER_GROUP";
+ public static final String ROLE_WRITE_TUTORIAL = "ROLE_WRITE_TUTORIAL";
+ public static final String ROLE_WRITE_NEWS_POST = "ROLE_WRITE_NEWS_POST";
+ public static final String ROLE_WRITE_OAUTH_CLIENT = "ROLE_WRITE_OAUTH_CLIENT";
+ public static final String ROLE_ADMIN_MAP = "ROLE_ADMIN_MAP";
+ public static final String ROLE_ADMIN_MOD = "ROLE_ADMIN_MOD";
+ public static final String ROLE_WRITE_MESSAGE = "ROLE_WRITE_MESSAGE";
+
+ private String technicalName;
+ private String nameKey;
+ private Set userGroups;
+
+ @Column(name = "technical_name")
+ public String getTechnicalName() {
+ return technicalName;
+ }
+
+ @Column(name = "name_key")
+ public String getNameKey() {
+ return nameKey;
+ }
+
+ @ManyToMany(mappedBy = "permissions")
+ public Set getUserGroups() {
+ return userGroups;
+ }
+
+ @Override
+ @Transient
+ public String getAuthority() {
+ return "ROLE_" + technicalName;
+ }
+}
diff --git a/src/main/java/com/faforever/api/data/domain/Ladder1v1Map.java b/src/main/java/com/faforever/api/data/domain/Ladder1v1Map.java
index b2640e805..790687a60 100644
--- a/src/main/java/com/faforever/api/data/domain/Ladder1v1Map.java
+++ b/src/main/java/com/faforever/api/data/domain/Ladder1v1Map.java
@@ -1,6 +1,6 @@
package com.faforever.api.data.domain;
-import com.faforever.api.data.checks.permission.HasLadder1v1Update;
+import com.faforever.api.security.elide.permission.WriteMatchmakerMapCheck;
import com.yahoo.elide.annotation.Audit;
import com.yahoo.elide.annotation.Audit.Action;
import com.yahoo.elide.annotation.CreatePermission;
@@ -19,8 +19,8 @@
import javax.persistence.OneToOne;
import javax.persistence.Table;
-@CreatePermission(expression = HasLadder1v1Update.EXPRESSION)
-@DeletePermission(expression = HasLadder1v1Update.EXPRESSION)
+@CreatePermission(expression = WriteMatchmakerMapCheck.EXPRESSION)
+@DeletePermission(expression = WriteMatchmakerMapCheck.EXPRESSION)
@Entity
@Setter
@Table(name = "ladder_map")
@@ -41,7 +41,7 @@ public int getId() {
@OneToOne
@JoinColumn(name = "idmap")
- @UpdatePermission(expression = HasLadder1v1Update.EXPRESSION)
+ @UpdatePermission(expression = WriteMatchmakerMapCheck.EXPRESSION)
public MapVersion getMapVersion() {
return mapVersion;
}
diff --git a/src/main/java/com/faforever/api/data/domain/Login.java b/src/main/java/com/faforever/api/data/domain/Login.java
index 482e93b05..cffd5ee9d 100644
--- a/src/main/java/com/faforever/api/data/domain/Login.java
+++ b/src/main/java/com/faforever/api/data/domain/Login.java
@@ -1,7 +1,11 @@
package com.faforever.api.data.domain;
import com.faforever.api.data.checks.IsEntityOwner;
+import com.faforever.api.data.checks.Prefab;
import com.faforever.api.data.checks.permission.IsModerator;
+import com.faforever.api.security.elide.permission.AdminAccountBanCheck;
+import com.faforever.api.security.elide.permission.AdminAccountNoteCheck;
+import com.faforever.api.security.elide.permission.ReadUserGroupCheck;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.yahoo.elide.annotation.ReadPermission;
import com.yahoo.elide.annotation.UpdatePermission;
@@ -9,9 +13,9 @@
import javax.persistence.Column;
import javax.persistence.FetchType;
+import javax.persistence.ManyToMany;
import javax.persistence.MappedSuperclass;
import javax.persistence.OneToMany;
-import javax.persistence.OneToOne;
import javax.persistence.Transient;
import java.time.OffsetDateTime;
import java.util.HashSet;
@@ -28,7 +32,7 @@ public abstract class Login extends AbstractEntity implements OwnableEntity {
private String userAgent;
private Set bans;
private Set userNotes;
- private LobbyGroup lobbyGroup;
+ private Set userGroups;
private String recentIpAddress;
private OffsetDateTime lastLogin;
@@ -73,13 +77,13 @@ public String getUserAgent() {
@OneToMany(mappedBy = "player", fetch = FetchType.EAGER)
// Permission is managed by BanInfo class
- @UpdatePermission(expression = IsModerator.EXPRESSION)
+ @UpdatePermission(expression = AdminAccountBanCheck.EXPRESSION)
public Set getBans() {
return this.bans;
}
@OneToMany(mappedBy = "player", fetch = FetchType.EAGER)
- @UpdatePermission(expression = IsModerator.EXPRESSION)
+ @UpdatePermission(expression = AdminAccountNoteCheck.EXPRESSION)
public Set getUserNotes() {
return this.userNotes;
}
@@ -94,9 +98,11 @@ public boolean isGlobalBanned() {
return getActiveBans().stream().anyMatch(ban -> ban.getLevel() == BanLevel.GLOBAL);
}
- @OneToOne(mappedBy = "user")
- public LobbyGroup getLobbyGroup() {
- return lobbyGroup;
+ @ReadPermission(expression = IsEntityOwner.EXPRESSION + " OR " + ReadUserGroupCheck.EXPRESSION)
+ @UpdatePermission(expression = Prefab.ALL)
+ @ManyToMany(mappedBy = "members")
+ public Set getUserGroups() {
+ return userGroups;
}
@Override
diff --git a/src/main/java/com/faforever/api/data/domain/MapVersion.java b/src/main/java/com/faforever/api/data/domain/MapVersion.java
index d31d69c44..7bb1c9116 100644
--- a/src/main/java/com/faforever/api/data/domain/MapVersion.java
+++ b/src/main/java/com/faforever/api/data/domain/MapVersion.java
@@ -2,6 +2,7 @@
import com.faforever.api.data.checks.BooleanChange;
import com.faforever.api.data.checks.IsEntityOwner;
+import com.faforever.api.data.checks.Prefab;
import com.faforever.api.data.checks.permission.IsModerator;
import com.faforever.api.data.listeners.MapVersionEnricher;
import com.yahoo.elide.annotation.Audit;
@@ -140,13 +141,13 @@ public String getFolderName() {
}
@OneToMany(mappedBy = "mapVersion")
- @UpdatePermission(expression = "Prefab.Role.All")
+ @UpdatePermission(expression = Prefab.ALL)
public List getReviews() {
return reviews;
}
@OneToOne(mappedBy = "mapVersion")
- @UpdatePermission(expression = "Prefab.Role.All")
+ @UpdatePermission(expression = Prefab.ALL)
public MapVersionReviewsSummary getReviewsSummary() {
return reviewsSummary;
}
diff --git a/src/main/java/com/faforever/api/data/domain/MapVersionReview.java b/src/main/java/com/faforever/api/data/domain/MapVersionReview.java
index 95e4eca76..9a111c856 100644
--- a/src/main/java/com/faforever/api/data/domain/MapVersionReview.java
+++ b/src/main/java/com/faforever/api/data/domain/MapVersionReview.java
@@ -1,6 +1,7 @@
package com.faforever.api.data.domain;
import com.faforever.api.data.checks.IsEntityOwner;
+import com.faforever.api.data.checks.Prefab;
import com.yahoo.elide.annotation.CreatePermission;
import com.yahoo.elide.annotation.DeletePermission;
import com.yahoo.elide.annotation.Include;
@@ -17,7 +18,7 @@
@Include(rootLevel = true, type = "mapVersionReview")
@Entity
@Table(name = "map_version_review")
-@CreatePermission(expression = "Prefab.Role.All")
+@CreatePermission(expression = Prefab.ALL)
@DeletePermission(expression = IsEntityOwner.EXPRESSION)
public class MapVersionReview extends Review {
@@ -25,7 +26,7 @@ public class MapVersionReview extends Review {
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "map_version_id")
- @UpdatePermission(expression = "Prefab.Role.All and Prefab.Common.UpdateOnCreate")
+ @UpdatePermission(expression = Prefab.ALL_AND_UPDATE_ON_CREATE)
public MapVersion getMapVersion() {
return mapVersion;
}
diff --git a/src/main/java/com/faforever/api/data/domain/Message.java b/src/main/java/com/faforever/api/data/domain/Message.java
index c36d0313a..a2a15e33f 100644
--- a/src/main/java/com/faforever/api/data/domain/Message.java
+++ b/src/main/java/com/faforever/api/data/domain/Message.java
@@ -1,5 +1,6 @@
package com.faforever.api.data.domain;
+import com.faforever.api.data.checks.Prefab;
import com.faforever.api.data.checks.permission.IsModerator;
import com.faforever.api.data.listeners.MessageReloadListener;
import com.github.jasminb.jsonapi.annotations.Type;
@@ -29,7 +30,7 @@
@CreatePermission(expression = IsModerator.EXPRESSION)
@Audit(action = Action.DELETE, logStatement = "Message with key `{0}` , ID `{1}`, language `{2}` , region `{3}` and value `{4}` deleted", logExpressions = {"${message.key}", "${message.id}", "${message.language}", "${message.region}", "${message.value}"})
@Audit(action = Action.CREATE, logStatement = "Message with key `{0}` and ID `{1}` created", logExpressions = {"${message.key}", "${message.id}"})
-@ReadPermission(expression = "Prefab.Role.All")
+@ReadPermission(expression = Prefab.ALL)
@EntityListeners(MessageReloadListener.class)
@Type(Message.TYPE_NAME)
public class Message {
diff --git a/src/main/java/com/faforever/api/data/domain/ModVersion.java b/src/main/java/com/faforever/api/data/domain/ModVersion.java
index ded0ad323..4881b2afc 100644
--- a/src/main/java/com/faforever/api/data/domain/ModVersion.java
+++ b/src/main/java/com/faforever/api/data/domain/ModVersion.java
@@ -1,5 +1,6 @@
package com.faforever.api.data.domain;
+import com.faforever.api.data.checks.Prefab;
import com.faforever.api.data.checks.permission.IsModerator;
import com.faforever.api.data.listeners.ModVersionEnricher;
import com.yahoo.elide.annotation.Audit;
@@ -137,13 +138,13 @@ public String getDownloadUrl() {
}
@OneToMany(mappedBy = "modVersion")
- @UpdatePermission(expression = "Prefab.Role.All")
+ @UpdatePermission(expression = Prefab.ALL)
public List getReviews() {
return reviews;
}
@OneToOne(mappedBy = "modVersion")
- @UpdatePermission(expression = "Prefab.Role.All")
+ @UpdatePermission(expression = Prefab.ALL)
public ModVersionReviewsSummary getReviewsSummary() {
return reviewsSummary;
}
diff --git a/src/main/java/com/faforever/api/data/domain/ModVersionReview.java b/src/main/java/com/faforever/api/data/domain/ModVersionReview.java
index 8acd67b04..a843853df 100644
--- a/src/main/java/com/faforever/api/data/domain/ModVersionReview.java
+++ b/src/main/java/com/faforever/api/data/domain/ModVersionReview.java
@@ -1,6 +1,7 @@
package com.faforever.api.data.domain;
import com.faforever.api.data.checks.IsEntityOwner;
+import com.faforever.api.data.checks.Prefab;
import com.yahoo.elide.annotation.CreatePermission;
import com.yahoo.elide.annotation.DeletePermission;
import com.yahoo.elide.annotation.Include;
@@ -17,7 +18,7 @@
@Include(rootLevel = true, type = "modVersionReview")
@Entity
@Table(name = "mod_version_review")
-@CreatePermission(expression = "Prefab.Role.All")
+@CreatePermission(expression = Prefab.ALL)
@DeletePermission(expression = IsEntityOwner.EXPRESSION)
public class ModVersionReview extends Review {
@@ -25,7 +26,7 @@ public class ModVersionReview extends Review {
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "mod_version_id")
- @UpdatePermission(expression = "Prefab.Role.All and Prefab.Common.UpdateOnCreate")
+ @UpdatePermission(expression = Prefab.ALL_AND_UPDATE_ON_CREATE)
public ModVersion getModVersion() {
return modVersion;
}
diff --git a/src/main/java/com/faforever/api/data/domain/ModerationReport.java b/src/main/java/com/faforever/api/data/domain/ModerationReport.java
index 20bd1a6a6..26c6b1f48 100644
--- a/src/main/java/com/faforever/api/data/domain/ModerationReport.java
+++ b/src/main/java/com/faforever/api/data/domain/ModerationReport.java
@@ -3,8 +3,8 @@
import com.faforever.api.data.checks.IsEntityOwner;
import com.faforever.api.data.checks.IsInAwaitingState;
import com.faforever.api.data.checks.Prefab;
-import com.faforever.api.data.checks.permission.IsModerator;
import com.faforever.api.security.FafUserDetails;
+import com.faforever.api.security.elide.permission.AdminModerationReportCheck;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.yahoo.elide.annotation.Audit;
import com.yahoo.elide.annotation.Audit.Action;
@@ -43,7 +43,7 @@
@Setter
@ToString(exclude = {"reportedUsers", "bans"})
@Include(rootLevel = true, type = ModerationReport.TYPE_NAME)
-@ReadPermission(expression = IsEntityOwner.EXPRESSION + " OR " + IsModerator.EXPRESSION)
+@ReadPermission(expression = IsEntityOwner.EXPRESSION + " OR " + AdminModerationReportCheck.EXPRESSION)
@DeletePermission(expression = Prefab.NONE)
@CreatePermission(expression = Prefab.ALL)
@Audit(action = Action.CREATE, logStatement = "Moderation report `{0}` has been reported", logExpressions = "${moderationReport}")
@@ -65,7 +65,7 @@ public class ModerationReport extends AbstractEntity implements OwnableEntity {
@Column(name = "report_status")
@Enumerated(EnumType.STRING)
@CreatePermission(expression = Prefab.NONE)
- @UpdatePermission(expression = IsModerator.EXPRESSION)
+ @UpdatePermission(expression = AdminModerationReportCheck.EXPRESSION)
public ModerationReportStatus getReportStatus() {
return reportStatus;
}
@@ -100,15 +100,15 @@ public Game getGame() {
@Column(name = "moderator_notice")
@CreatePermission(expression = Prefab.NONE)
- @UpdatePermission(expression = IsModerator.EXPRESSION)
+ @UpdatePermission(expression = AdminModerationReportCheck.EXPRESSION)
public String getModeratorNotice() {
return moderatorNotice;
}
@Column(name = "moderator_private_note")
- @ReadPermission(expression = IsModerator.EXPRESSION)
+ @ReadPermission(expression = AdminModerationReportCheck.EXPRESSION)
@CreatePermission(expression = Prefab.NONE)
- @UpdatePermission(expression = IsModerator.EXPRESSION)
+ @UpdatePermission(expression = AdminModerationReportCheck.EXPRESSION)
public String getModeratorPrivateNote() {
return moderatorPrivateNote;
}
@@ -116,7 +116,7 @@ public String getModeratorPrivateNote() {
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "last_moderator", referencedColumnName = "id")
@CreatePermission(expression = Prefab.NONE)
- @UpdatePermission(expression = IsModerator.EXPRESSION)
+ @UpdatePermission(expression = AdminModerationReportCheck.EXPRESSION)
public Player getLastModerator() {
return lastModerator;
}
@@ -138,7 +138,7 @@ public Set getReportedUsers() {
}
@OneToMany(mappedBy = "moderationReport")
- @ReadPermission(expression = IsModerator.EXPRESSION)
+ @ReadPermission(expression = AdminModerationReportCheck.EXPRESSION)
// Permission is managed by BanInfo class
@UpdatePermission(expression = Prefab.ALL)
public Collection getBans() {
@@ -169,7 +169,7 @@ public void updateLastModerator(RequestScope scope) {
final Object caller = scope.getUser().getOpaqueUser();
if (caller instanceof FafUserDetails) {
final FafUserDetails fafUser = (FafUserDetails) caller;
- if (fafUser.hasPermission(IsModerator.EXPRESSION)) {
+ if (fafUser.hasPermission(GroupPermission.ROLE_ADMIN_MODERATION_REPORT)) {
final Player lastModerator = new Player();
lastModerator.setId(fafUser.getId());
this.lastModerator = lastModerator;
diff --git a/src/main/java/com/faforever/api/data/domain/NameRecord.java b/src/main/java/com/faforever/api/data/domain/NameRecord.java
index 91fe101aa..c44006fcc 100644
--- a/src/main/java/com/faforever/api/data/domain/NameRecord.java
+++ b/src/main/java/com/faforever/api/data/domain/NameRecord.java
@@ -1,5 +1,6 @@
package com.faforever.api.data.domain;
+import com.faforever.api.data.checks.Prefab;
import com.yahoo.elide.annotation.DeletePermission;
import com.yahoo.elide.annotation.Include;
import com.yahoo.elide.annotation.UpdatePermission;
@@ -18,8 +19,8 @@
@Entity
@Table(name = "name_history")
@Include(rootLevel = true, type = "nameRecord")
-@DeletePermission(expression = "Prefab.Role.None")
-@UpdatePermission(expression = "Prefab.Role.None")
+@DeletePermission(expression = Prefab.NONE)
+@UpdatePermission(expression = Prefab.NONE)
@Setter
public class NameRecord {
private int id;
diff --git a/src/main/java/com/faforever/api/data/domain/Review.java b/src/main/java/com/faforever/api/data/domain/Review.java
index 65f1689c7..52046e257 100644
--- a/src/main/java/com/faforever/api/data/domain/Review.java
+++ b/src/main/java/com/faforever/api/data/domain/Review.java
@@ -1,6 +1,7 @@
package com.faforever.api.data.domain;
import com.faforever.api.data.checks.IsEntityOwner;
+import com.faforever.api.data.checks.Prefab;
import com.yahoo.elide.annotation.UpdatePermission;
import lombok.Setter;
@@ -36,7 +37,7 @@ public Byte getScore() {
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "user_id")
- @UpdatePermission(expression = "Prefab.Role.All and Prefab.Common.UpdateOnCreate")
+ @UpdatePermission(expression = Prefab.ALL_AND_UPDATE_ON_CREATE)
public Player getPlayer() {
return player;
}
diff --git a/src/main/java/com/faforever/api/data/domain/Teamkill.java b/src/main/java/com/faforever/api/data/domain/Teamkill.java
index 8919345c9..181c94142 100644
--- a/src/main/java/com/faforever/api/data/domain/Teamkill.java
+++ b/src/main/java/com/faforever/api/data/domain/Teamkill.java
@@ -1,6 +1,6 @@
package com.faforever.api.data.domain;
-import com.faforever.api.data.checks.permission.IsModerator;
+import com.faforever.api.security.elide.permission.ReadTeamkillReportCheck;
import com.yahoo.elide.annotation.Include;
import com.yahoo.elide.annotation.ReadPermission;
import lombok.Setter;
@@ -21,7 +21,7 @@
@Table(name = "teamkills")
@Include(rootLevel = true, type = Teamkill.TYPE_NAME)
@Immutable
-@ReadPermission(expression = IsModerator.EXPRESSION)
+@ReadPermission(expression = ReadTeamkillReportCheck.EXPRESSION)
public class Teamkill {
public static final String TYPE_NAME = "teamkill";
diff --git a/src/main/java/com/faforever/api/data/domain/Tutorial.java b/src/main/java/com/faforever/api/data/domain/Tutorial.java
index e9890bd49..9f66a8cd2 100644
--- a/src/main/java/com/faforever/api/data/domain/Tutorial.java
+++ b/src/main/java/com/faforever/api/data/domain/Tutorial.java
@@ -1,7 +1,8 @@
package com.faforever.api.data.domain;
-import com.faforever.api.data.checks.permission.IsModerator;
+import com.faforever.api.data.checks.Prefab;
import com.faforever.api.data.listeners.TutorialEnricherListener;
+import com.faforever.api.security.elide.permission.WriteTutorialCheck;
import com.github.jasminb.jsonapi.annotations.Type;
import com.yahoo.elide.annotation.Audit;
import com.yahoo.elide.annotation.Audit.Action;
@@ -27,12 +28,12 @@
@Table(name = "tutorial")
@Setter
@Include(rootLevel = true, type = Tutorial.TYPE_NAME)
-@DeletePermission(expression = IsModerator.EXPRESSION)
-@UpdatePermission(expression = IsModerator.EXPRESSION)
-@CreatePermission(expression = IsModerator.EXPRESSION)
+@DeletePermission(expression = WriteTutorialCheck.EXPRESSION)
+@UpdatePermission(expression = WriteTutorialCheck.EXPRESSION)
+@CreatePermission(expression = WriteTutorialCheck.EXPRESSION)
@Audit(action = Action.DELETE, logStatement = "Tutorial with name `{0}` and ID `{1}` deleted", logExpressions = {"${tutorial.title}", "${tutorial.id}"})
@Audit(action = Action.CREATE, logStatement = "Tutorial with name `{0}` and ID `{1}` created", logExpressions = {"${tutorial.title}", "${tutorial.id}"})
-@ReadPermission(expression = "Prefab.Role.All")
+@ReadPermission(expression = Prefab.ALL)
@EntityListeners(TutorialEnricherListener.class)
@Type(Tutorial.TYPE_NAME)
public class Tutorial extends AbstractEntity {
diff --git a/src/main/java/com/faforever/api/data/domain/TutorialCategory.java b/src/main/java/com/faforever/api/data/domain/TutorialCategory.java
index 2737b9bec..920e91d9c 100644
--- a/src/main/java/com/faforever/api/data/domain/TutorialCategory.java
+++ b/src/main/java/com/faforever/api/data/domain/TutorialCategory.java
@@ -1,8 +1,9 @@
package com.faforever.api.data.domain;
-import com.faforever.api.data.checks.permission.IsModerator;
+import com.faforever.api.data.checks.Prefab;
import com.faforever.api.data.listeners.TutorialCategoryEnricherListener;
+import com.faforever.api.security.elide.permission.WriteTutorialCheck;
import com.github.jasminb.jsonapi.annotations.Type;
import com.yahoo.elide.annotation.Audit;
import com.yahoo.elide.annotation.Audit.Action;
@@ -31,12 +32,12 @@
@Table(name = "tutorial_category")
@Setter
@Include(rootLevel = true, type = TutorialCategory.TYPE_NAME)
-@DeletePermission(expression = IsModerator.EXPRESSION)
-@UpdatePermission(expression = IsModerator.EXPRESSION)
-@CreatePermission(expression = IsModerator.EXPRESSION)
+@DeletePermission(expression = WriteTutorialCheck.EXPRESSION)
+@UpdatePermission(expression = WriteTutorialCheck.EXPRESSION)
+@CreatePermission(expression = WriteTutorialCheck.EXPRESSION)
@Audit(action = Action.DELETE, logStatement = "Tutorial Category with title `{0}` and ID `{1}` deleted", logExpressions = {"${tutorialCategory.category}", "${tutorialCategory.id}"})
@Audit(action = Action.CREATE, logStatement = "Tutorial Category with title `{0}` and ID `{1}` created", logExpressions = {"${tutorialCategory.category}", "${tutorialCategory.id}"})
-@ReadPermission(expression = "Prefab.Role.All")
+@ReadPermission(expression = Prefab.ALL)
@EntityListeners(TutorialCategoryEnricherListener.class)
@Type(TutorialCategory.TYPE_NAME)
public class TutorialCategory {
diff --git a/src/main/java/com/faforever/api/data/domain/User.java b/src/main/java/com/faforever/api/data/domain/User.java
index d623224fe..620e01b02 100644
--- a/src/main/java/com/faforever/api/data/domain/User.java
+++ b/src/main/java/com/faforever/api/data/domain/User.java
@@ -1,5 +1,6 @@
package com.faforever.api.data.domain;
+import com.faforever.api.data.checks.Prefab;
import com.yahoo.elide.annotation.Include;
import com.yahoo.elide.annotation.ReadPermission;
import lombok.Setter;
@@ -16,7 +17,7 @@ public class User extends Login {
private String password;
@Column(name = "password")
- @ReadPermission(expression = "Prefab.Role.None")
+ @ReadPermission(expression = Prefab.NONE)
public String getPassword() {
return password;
}
diff --git a/src/main/java/com/faforever/api/data/domain/UserGroup.java b/src/main/java/com/faforever/api/data/domain/UserGroup.java
new file mode 100644
index 000000000..2d19cb30f
--- /dev/null
+++ b/src/main/java/com/faforever/api/data/domain/UserGroup.java
@@ -0,0 +1,82 @@
+package com.faforever.api.data.domain;
+
+
+import com.faforever.api.data.checks.UserGroupPublicCheck;
+import com.faforever.api.security.elide.permission.WriteUserGroupCheck;
+import com.yahoo.elide.annotation.CreatePermission;
+import com.yahoo.elide.annotation.Include;
+import com.yahoo.elide.annotation.ReadPermission;
+import com.yahoo.elide.annotation.UpdatePermission;
+import lombok.Setter;
+
+import javax.persistence.CascadeType;
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.JoinColumn;
+import javax.persistence.JoinTable;
+import javax.persistence.ManyToMany;
+import javax.persistence.Table;
+import javax.validation.Valid;
+import javax.validation.constraints.NotNull;
+import java.util.Set;
+
+@Entity
+@Table(name = "user_group")
+@Include(type = "userGroup")
+@UpdatePermission(expression = WriteUserGroupCheck.EXPRESSION)
+@CreatePermission(expression = WriteUserGroupCheck.EXPRESSION)
+@ReadPermission(expression = UserGroupPublicCheck.EXPRESSION + " or " + WriteUserGroupCheck.EXPRESSION)
+@Setter
+public class UserGroup extends AbstractEntity {
+
+ private String technicalName;
+ private String nameKey;
+ private boolean public_;
+ private Set members;
+ private Set permissions;
+
+ @Column(name = "technical_name")
+ public String getTechnicalName() {
+ return technicalName;
+ }
+
+ @Column(name = "name_key")
+ public String getNameKey() {
+ return nameKey;
+ }
+
+ @Column(name = "public")
+ public boolean isPublic() {
+ return public_;
+ }
+
+ public void setPublic(boolean public_) {
+ this.public_ = public_;
+ }
+
+ @JoinTable(name = "user_group_assignment",
+ joinColumns = @JoinColumn(name = "group_id"),
+ inverseJoinColumns = @JoinColumn(name = "user_id")
+ )
+ @ManyToMany(cascade = {
+ CascadeType.PERSIST,
+ CascadeType.MERGE
+ })
+ public @NotNull
+ @Valid Set getMembers() {
+ return members;
+ }
+
+ @JoinTable(name = "group_permission_assignment",
+ joinColumns = @JoinColumn(name = "group_id"),
+ inverseJoinColumns = @JoinColumn(name = "permission_id")
+ )
+ @ManyToMany(cascade = {
+ CascadeType.PERSIST,
+ CascadeType.MERGE
+ })
+ public @NotNull
+ @Valid Set getPermissions() {
+ return permissions;
+ }
+}
diff --git a/src/main/java/com/faforever/api/data/domain/UserNote.java b/src/main/java/com/faforever/api/data/domain/UserNote.java
index b2933d0b2..ff5a953f6 100644
--- a/src/main/java/com/faforever/api/data/domain/UserNote.java
+++ b/src/main/java/com/faforever/api/data/domain/UserNote.java
@@ -1,6 +1,7 @@
package com.faforever.api.data.domain;
-import com.faforever.api.data.checks.permission.IsModerator;
+import com.faforever.api.data.checks.Prefab;
+import com.faforever.api.security.elide.permission.AdminAccountNoteCheck;
import com.yahoo.elide.annotation.Audit;
import com.yahoo.elide.annotation.Audit.Action;
import com.yahoo.elide.annotation.CreatePermission;
@@ -21,10 +22,10 @@
@Entity
@Table(name = "user_notes")
@Include(rootLevel = true, type = "userNote")
-@ReadPermission(expression = IsModerator.EXPRESSION)
-@CreatePermission(expression = IsModerator.EXPRESSION)
-@UpdatePermission(expression = IsModerator.EXPRESSION)
-@DeletePermission(expression = "Prefab.Role.None")
+@ReadPermission(expression = AdminAccountNoteCheck.EXPRESSION)
+@CreatePermission(expression = AdminAccountNoteCheck.EXPRESSION)
+@UpdatePermission(expression = AdminAccountNoteCheck.EXPRESSION)
+@DeletePermission(expression = Prefab.NONE)
@Audit(action = Action.CREATE, logStatement = "Note `{0}` for user `{1}` added (watched=`{2}`) with text: {3}", logExpressions = {"${userNote.id}", "${userNote.player.id}", "${userNote.watched}", "${userNote.note}"})
@Setter
public class UserNote extends AbstractEntity {
diff --git a/src/main/java/com/faforever/api/data/domain/Vote.java b/src/main/java/com/faforever/api/data/domain/Vote.java
index 5bbf98ca0..0c1ff5b37 100644
--- a/src/main/java/com/faforever/api/data/domain/Vote.java
+++ b/src/main/java/com/faforever/api/data/domain/Vote.java
@@ -1,6 +1,7 @@
package com.faforever.api.data.domain;
import com.faforever.api.data.checks.IsEntityOwner;
+import com.faforever.api.data.checks.Prefab;
import com.yahoo.elide.annotation.Include;
import com.yahoo.elide.annotation.ReadPermission;
import com.yahoo.elide.annotation.UpdatePermission;
@@ -21,7 +22,7 @@
@Table(name = "vote")
@Include(type = Vote.TYPE_NAME, rootLevel = true)
@ReadPermission(expression = IsEntityOwner.EXPRESSION)
-@UpdatePermission(expression = "Prefab.Role.None")
+@UpdatePermission(expression = Prefab.NONE)
@EqualsAndHashCode(of = {"player", "votingSubject"}, callSuper = false)
@Setter
public class Vote extends AbstractEntity implements OwnableEntity {
diff --git a/src/main/java/com/faforever/api/data/domain/VotingAnswer.java b/src/main/java/com/faforever/api/data/domain/VotingAnswer.java
index c0416cdc7..2459d03bd 100644
--- a/src/main/java/com/faforever/api/data/domain/VotingAnswer.java
+++ b/src/main/java/com/faforever/api/data/domain/VotingAnswer.java
@@ -1,6 +1,7 @@
package com.faforever.api.data.domain;
import com.faforever.api.data.checks.IsEntityOwner;
+import com.faforever.api.data.checks.Prefab;
import com.yahoo.elide.annotation.Include;
import com.yahoo.elide.annotation.ReadPermission;
import com.yahoo.elide.annotation.UpdatePermission;
@@ -19,7 +20,7 @@
@Table(name = "voting_answer")
@Include(type = VotingAnswer.TYPE_NAME)
@ReadPermission(expression = IsEntityOwner.EXPRESSION)
-@UpdatePermission(expression = "Prefab.Role.None")
+@UpdatePermission(expression = Prefab.NONE)
@EqualsAndHashCode(of = {"vote", "votingChoice"}, callSuper = false)
@Setter
public class VotingAnswer extends AbstractEntity implements OwnableEntity {
diff --git a/src/main/java/com/faforever/api/data/domain/VotingChoice.java b/src/main/java/com/faforever/api/data/domain/VotingChoice.java
index 2c60ddf1c..d6891d4e4 100644
--- a/src/main/java/com/faforever/api/data/domain/VotingChoice.java
+++ b/src/main/java/com/faforever/api/data/domain/VotingChoice.java
@@ -1,7 +1,8 @@
package com.faforever.api.data.domain;
-import com.faforever.api.data.checks.permission.IsModerator;
+import com.faforever.api.data.checks.Prefab;
import com.faforever.api.data.listeners.VotingChoiceEnricher;
+import com.faforever.api.security.elide.permission.AdminVoteCheck;
import com.fasterxml.jackson.annotation.JsonBackReference;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.yahoo.elide.annotation.Audit;
@@ -29,10 +30,10 @@
@Entity
@Table(name = "voting_choice")
-@ReadPermission(expression = "Prefab.Role.All")
-@DeletePermission(expression = IsModerator.EXPRESSION)
-@UpdatePermission(expression = IsModerator.EXPRESSION)
-@CreatePermission(expression = IsModerator.EXPRESSION)
+@ReadPermission(expression = Prefab.ALL)
+@DeletePermission(expression = AdminVoteCheck.EXPRESSION)
+@UpdatePermission(expression = AdminVoteCheck.EXPRESSION)
+@CreatePermission(expression = AdminVoteCheck.EXPRESSION)
@Audit(action = Action.CREATE, logStatement = "Created voting choice with id: {0} ", logExpressions = {"${votingChoice.id}"})
@Audit(action = Action.DELETE, logStatement = "Deleted voting choice with id: {0} ", logExpressions = {"${votingChoice.id}"})
@Audit(action = Action.UPDATE, logStatement = "Updated voting choice with id: {0} ", logExpressions = {"${votingChoice.id}"})
diff --git a/src/main/java/com/faforever/api/data/domain/VotingQuestion.java b/src/main/java/com/faforever/api/data/domain/VotingQuestion.java
index db7fef2fa..62475a92e 100644
--- a/src/main/java/com/faforever/api/data/domain/VotingQuestion.java
+++ b/src/main/java/com/faforever/api/data/domain/VotingQuestion.java
@@ -1,7 +1,8 @@
package com.faforever.api.data.domain;
-import com.faforever.api.data.checks.permission.IsModerator;
+import com.faforever.api.data.checks.Prefab;
import com.faforever.api.data.listeners.VotingQuestionEnricher;
+import com.faforever.api.security.elide.permission.AdminVoteCheck;
import com.fasterxml.jackson.annotation.JsonBackReference;
import com.fasterxml.jackson.annotation.JsonManagedReference;
import com.yahoo.elide.annotation.Audit;
@@ -32,10 +33,10 @@
@Entity
@Table(name = "voting_question")
-@ReadPermission(expression = "Prefab.Role.All")
-@DeletePermission(expression = IsModerator.EXPRESSION)
-@UpdatePermission(expression = IsModerator.EXPRESSION)
-@CreatePermission(expression = IsModerator.EXPRESSION)
+@ReadPermission(expression = Prefab.ALL)
+@DeletePermission(expression = AdminVoteCheck.EXPRESSION)
+@UpdatePermission(expression = AdminVoteCheck.EXPRESSION)
+@CreatePermission(expression = AdminVoteCheck.EXPRESSION)
@Audit(action = Action.CREATE, logStatement = "Created voting question with id:{0}", logExpressions = {"${votingQuestion.id}"})
@Audit(action = Action.DELETE, logStatement = "Deleted voting question with id:{0}", logExpressions = {"${votingQuestion.id}"})
@Audit(action = Action.UPDATE, logStatement = "Updated voting question with id:{0}", logExpressions = {"${votingQuestion.id}"})
@@ -57,14 +58,13 @@ public class VotingQuestion extends AbstractEntity {
private List winners;
private Set votingChoices;
- @UpdatePermission(expression = "Prefab.Common.UpdateOnCreate")
+ @UpdatePermission(expression = Prefab.UPDATE_ON_CREATE)
@Column(name = "alternative_voting")
public Boolean isAlternativeQuestion() {
return alternativeQuestion;
}
@Column(name = "ordinal")
- @UpdatePermission(expression = IsModerator.EXPRESSION)
public Integer getOrdinal() {
return ordinal;
}
@@ -72,7 +72,7 @@ public Integer getOrdinal() {
/**
* Is evaluated when voting ended and revealVote is set to true
*/
- @UpdatePermission(expression = "Prefab.Role.None")
+ @UpdatePermission(expression = Prefab.NONE)
@JoinTable(name = "winner_for_voting_question",
joinColumns = {@JoinColumn(name = "voting_question_id")},
inverseJoinColumns = {@JoinColumn(name = "voting_choice_id")}
diff --git a/src/main/java/com/faforever/api/data/domain/VotingSubject.java b/src/main/java/com/faforever/api/data/domain/VotingSubject.java
index 64bdb7bb2..b7e9b0a3d 100644
--- a/src/main/java/com/faforever/api/data/domain/VotingSubject.java
+++ b/src/main/java/com/faforever/api/data/domain/VotingSubject.java
@@ -1,8 +1,9 @@
package com.faforever.api.data.domain;
-import com.faforever.api.data.checks.permission.IsModerator;
+import com.faforever.api.data.checks.Prefab;
import com.faforever.api.data.listeners.VotingSubjectEnricher;
import com.faforever.api.data.validation.VotingSubjectRevealWinnerCheck;
+import com.faforever.api.security.elide.permission.AdminVoteCheck;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonManagedReference;
import com.yahoo.elide.annotation.Audit;
@@ -31,10 +32,10 @@
@Entity
@Table(name = "voting_subject")
@Include(rootLevel = true, type = VotingSubject.TYPE_NAME)
-@ReadPermission(expression = "Prefab.Role.All")
-@DeletePermission(expression = IsModerator.EXPRESSION)
-@UpdatePermission(expression = IsModerator.EXPRESSION)
-@CreatePermission(expression = IsModerator.EXPRESSION)
+@ReadPermission(expression = Prefab.ALL)
+@DeletePermission(expression = AdminVoteCheck.EXPRESSION)
+@UpdatePermission(expression = AdminVoteCheck.EXPRESSION)
+@CreatePermission(expression = AdminVoteCheck.EXPRESSION)
@Audit(action = Action.CREATE, logStatement = "Created voting subject with id: {0}", logExpressions = {"${votingSubject.id}"})
@Audit(action = Action.DELETE, logStatement = "Deleted voting subject with id: {0}", logExpressions = {"${votingSubject.id}"})
@Audit(action = Action.UPDATE, logStatement = "Updated voting subject with id: {0}", logExpressions = {"${votingSubject.id}"})
diff --git a/src/main/java/com/faforever/api/data/package-info.java b/src/main/java/com/faforever/api/data/package-info.java
index 530493b6a..fb987542c 100644
--- a/src/main/java/com/faforever/api/data/package-info.java
+++ b/src/main/java/com/faforever/api/data/package-info.java
@@ -3,13 +3,14 @@
*/
@SharePermission
// Everybody can read from the api
-@ReadPermission(expression = "Prefab.Role.All")
+@ReadPermission(expression = Prefab.ALL)
// By default restrict all data manipulation operation
-@UpdatePermission(expression = "Prefab.Role.None")
-@CreatePermission(expression = "Prefab.Role.None")
-@DeletePermission(expression = "Prefab.Role.None")
+@UpdatePermission(expression = Prefab.NONE)
+@CreatePermission(expression = Prefab.NONE)
+@DeletePermission(expression = Prefab.NONE)
package com.faforever.api.data;
+import com.faforever.api.data.checks.Prefab;
import com.yahoo.elide.annotation.CreatePermission;
import com.yahoo.elide.annotation.DeletePermission;
import com.yahoo.elide.annotation.ReadPermission;
diff --git a/src/main/java/com/faforever/api/security/FafUserAuthenticationConverter.java b/src/main/java/com/faforever/api/security/FafUserAuthenticationConverter.java
index ff238529a..80bb2332a 100644
--- a/src/main/java/com/faforever/api/security/FafUserAuthenticationConverter.java
+++ b/src/main/java/com/faforever/api/security/FafUserAuthenticationConverter.java
@@ -19,8 +19,8 @@
*/
public class FafUserAuthenticationConverter extends DefaultUserAuthenticationConverter {
- private static final String ID = "user_id";
- private static final String NON_LOCKED = "non_locked";
+ public static final String USER_ID_KEY = "user_id";
+ public static final String NON_LOCKED = "non_locked";
@Override
public Map convertUserAuthentication(Authentication authentication) {
@@ -28,7 +28,7 @@ public class FafUserAuthenticationConverter extends DefaultUserAuthenticationCon
@SuppressWarnings("unchecked")
Map response = (Map) super.convertUserAuthentication(authentication);
- response.put(ID, fafUserDetails.getId());
+ response.put(USER_ID_KEY, fafUserDetails.getId());
response.put(NON_LOCKED, fafUserDetails.isAccountNonLocked());
return response;
@@ -36,11 +36,11 @@ public class FafUserAuthenticationConverter extends DefaultUserAuthenticationCon
@Override
public Authentication extractAuthentication(Map map) {
- if (!map.containsKey(ID)) {
+ if (!map.containsKey(USER_ID_KEY)) {
return null;
}
- int id = (Integer) map.get(ID);
+ int id = (Integer) map.get(USER_ID_KEY);
String username = (String) map.get(USERNAME);
boolean accountNonLocked = Optional.ofNullable((Boolean) map.get(NON_LOCKED)).orElse(true);
Collection extends GrantedAuthority> authorities = getAuthorities(map);
diff --git a/src/main/java/com/faforever/api/security/FafUserDetails.java b/src/main/java/com/faforever/api/security/FafUserDetails.java
index fa2d955d8..16a3981bb 100644
--- a/src/main/java/com/faforever/api/security/FafUserDetails.java
+++ b/src/main/java/com/faforever/api/security/FafUserDetails.java
@@ -1,11 +1,11 @@
package com.faforever.api.security;
-import com.faforever.api.data.domain.LegacyAccessLevel;
import com.faforever.api.data.domain.User;
import lombok.Getter;
import org.springframework.security.core.GrantedAuthority;
import java.util.Collection;
+import java.util.stream.Collectors;
@Getter
public class FafUserDetails extends org.springframework.security.core.userdetails.User {
@@ -22,17 +22,10 @@ public FafUserDetails(int id, String username, String password, boolean accountN
}
public boolean hasPermission(String permission) {
- Collection authorities = this.getAuthorities();
+ Collection authorities = this.getAuthorities().stream()
+ .map(GrantedAuthority::getAuthority)
+ .collect(Collectors.toList());
- if (authorities.contains(LegacyAccessLevel.ROLE_ADMINISTRATOR)) {
- return true;
- }
-
- if (authorities.contains(LegacyAccessLevel.ROLE_MODERATOR)) {
- // We have no admin-only permissions yet
- return true;
- }
-
- return false;
+ return authorities.contains(permission) || authorities.contains(UserRole.ADMINISTRATOR.getAuthority());
}
}
diff --git a/src/main/java/com/faforever/api/security/FafUserDetailsService.java b/src/main/java/com/faforever/api/security/FafUserDetailsService.java
index b76a009b1..e3dd2bfe0 100644
--- a/src/main/java/com/faforever/api/security/FafUserDetailsService.java
+++ b/src/main/java/com/faforever/api/security/FafUserDetailsService.java
@@ -11,6 +11,11 @@
import javax.inject.Inject;
import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Optional;
+import java.util.Set;
+import java.util.stream.Collectors;
/**
* Adapter between Spring's {@link UserDetailsService} and FAF's {@code login} table.
@@ -33,9 +38,29 @@ public UserDetails loadUserByUsername(String usernameOrEmail) throws UsernameNot
ArrayList authorities = new ArrayList<>();
authorities.add(LegacyAccessLevel.ROLE_USER);
- if (user.getLobbyGroup() != null) {
- authorities.add(user.getLobbyGroup().getAccessLevel());
- }
+ authorities.addAll(getUserRoles(user));
+ authorities.addAll(getPermissionRoles(user));
+
return new FafUserDetails(user, authorities);
}
+
+ private Collection getUserRoles(User user) {
+ Set userRoles = new HashSet<>();
+
+ userRoles.add(UserRole.USER);
+
+ user.getUserGroups().stream()
+ .map(userGroup -> UserRole.fromString(userGroup.getTechnicalName()))
+ .filter(Optional::isPresent)
+ .map(Optional::get)
+ .forEach(userRoles::add);
+
+ return userRoles;
+ }
+
+ private Collection getPermissionRoles(User user) {
+ return user.getUserGroups().stream()
+ .flatMap(userGroup -> userGroup.getPermissions().stream())
+ .collect(Collectors.toSet());
+ }
}
diff --git a/src/main/java/com/faforever/api/security/OAuthScope.java b/src/main/java/com/faforever/api/security/OAuthScope.java
index 0d5b7a609..95cbad38c 100644
--- a/src/main/java/com/faforever/api/security/OAuthScope.java
+++ b/src/main/java/com/faforever/api/security/OAuthScope.java
@@ -6,7 +6,7 @@
public enum OAuthScope {
- PUBLIC_PROFILE(OAuthScope._PUBLIC_PROFILE, "Read your public player data"),
+ PUBLIC_PROFILE(OAuthScope._PUBLIC_PROFILE, "Read your public account data"),
CREATE_USER(OAuthScope._CREATE_USER, "Create users"),
READ_ACHIEVEMENTS(OAuthScope._READ_ACHIEVEMENTS, "Read your achievements"),
WRITE_ACHIEVEMENTS(OAuthScope._WRITE_ACHIEVEMENTS, "Write your achievements"),
@@ -17,8 +17,10 @@ public enum OAuthScope {
UPLOAD_AVATAR(OAuthScope._UPLOAD_AVATAR, "Upload avatars"),
WRITE_ACCOUNT_DATA(OAuthScope._WRITE_ACCOUNT_DATA, "Edit account data"),
EDIT_CLAN_DATA(OAuthScope._EDIT_CLAN_DATA, "Edit clan data"),
- VOTE(OAuthScope._VOTE, "Vote");
-
+ VOTE(OAuthScope._VOTE, "Vote"),
+ READ_SENSIBLE_USERDATA(OAuthScope._READ_SENSIBLE_USERDATA, "View sensible user data (email addresses, ip addresses, etc.)"),
+ ADMINISTRATIVE_ACTION(OAuthScope._ADMINISTRATIVE_ACTION, "Administrative actions"),
+ MANAGE_VAULT(OAuthScope._MANAGE_VAULT, "Manage vault");
public static final String _PUBLIC_PROFILE = "public_profile";
public static final String _CREATE_USER = "create_user";
@@ -32,6 +34,9 @@ public enum OAuthScope {
public static final String _WRITE_ACCOUNT_DATA = "write_account_data";
public static final String _EDIT_CLAN_DATA = "edit_clan_data";
public static final String _VOTE = "vote";
+ public static final String _READ_SENSIBLE_USERDATA = "read_sensible_userdata";
+ public static final String _ADMINISTRATIVE_ACTION = "administrative_actions";
+ public static final String _MANAGE_VAULT = "manage_vault";
private static final Map fromString;
diff --git a/src/main/java/com/faforever/api/security/UserRole.java b/src/main/java/com/faforever/api/security/UserRole.java
new file mode 100644
index 000000000..04c90edda
--- /dev/null
+++ b/src/main/java/com/faforever/api/security/UserRole.java
@@ -0,0 +1,37 @@
+package com.faforever.api.security;
+
+import org.springframework.security.core.GrantedAuthority;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Optional;
+
+public enum UserRole implements GrantedAuthority {
+ USER("USER"),
+ MODERATOR("MODERATOR"),
+ ADMINISTRATOR("ADMINISTRATOR");
+
+ private static final Map fromString;
+
+ static {
+ fromString = new HashMap<>();
+ for (UserRole userRole : values()) {
+ fromString.put(userRole.string, userRole);
+ }
+ }
+
+ private final String string;
+
+ UserRole(String string) {
+ this.string = string;
+ }
+
+ public static Optional fromString(String string) {
+ return Optional.ofNullable(fromString.get(string));
+ }
+
+ @Override
+ public String getAuthority() {
+ return "ROLE_" + string;
+ }
+}
diff --git a/src/main/java/com/faforever/api/security/elide/permission/AdminAccountBanCheck.java b/src/main/java/com/faforever/api/security/elide/permission/AdminAccountBanCheck.java
new file mode 100644
index 000000000..b1cc284a1
--- /dev/null
+++ b/src/main/java/com/faforever/api/security/elide/permission/AdminAccountBanCheck.java
@@ -0,0 +1,17 @@
+package com.faforever.api.security.elide.permission;
+
+import com.faforever.api.data.domain.GroupPermission;
+import com.faforever.api.security.OAuthScope;
+import com.yahoo.elide.security.User;
+import lombok.extern.slf4j.Slf4j;
+
+@Slf4j
+public class AdminAccountBanCheck extends FafUserCheck {
+ public static final String EXPRESSION = "AdminAccountBan";
+
+ @Override
+ public boolean ok(User user) {
+ return checkOAuthScopes(OAuthScope.ADMINISTRATIVE_ACTION) &&
+ checkUserPermission(user, GroupPermission.ROLE_ADMIN_ACCOUNT_BAN);
+ }
+}
diff --git a/src/main/java/com/faforever/api/security/elide/permission/AdminAccountNoteCheck.java b/src/main/java/com/faforever/api/security/elide/permission/AdminAccountNoteCheck.java
new file mode 100644
index 000000000..126392b6b
--- /dev/null
+++ b/src/main/java/com/faforever/api/security/elide/permission/AdminAccountNoteCheck.java
@@ -0,0 +1,17 @@
+package com.faforever.api.security.elide.permission;
+
+import com.faforever.api.data.domain.GroupPermission;
+import com.faforever.api.security.OAuthScope;
+import com.yahoo.elide.security.User;
+import lombok.extern.slf4j.Slf4j;
+
+@Slf4j
+public class AdminAccountNoteCheck extends FafUserCheck {
+ public static final String EXPRESSION = "AdminAccountNote";
+
+ @Override
+ public boolean ok(User user) {
+ return checkOAuthScopes(OAuthScope.READ_SENSIBLE_USERDATA) &&
+ checkUserPermission(user, GroupPermission.ROLE_ADMIN_ACCOUNT_NOTE);
+ }
+}
diff --git a/src/main/java/com/faforever/api/security/elide/permission/AdminMapCheck.java b/src/main/java/com/faforever/api/security/elide/permission/AdminMapCheck.java
new file mode 100644
index 000000000..847520f88
--- /dev/null
+++ b/src/main/java/com/faforever/api/security/elide/permission/AdminMapCheck.java
@@ -0,0 +1,17 @@
+package com.faforever.api.security.elide.permission;
+
+import com.faforever.api.data.domain.GroupPermission;
+import com.faforever.api.security.OAuthScope;
+import com.yahoo.elide.security.User;
+import lombok.extern.slf4j.Slf4j;
+
+@Slf4j
+public class AdminMapCheck extends FafUserCheck {
+ public static final String EXPRESSION = "AdminMap";
+
+ @Override
+ public boolean ok(User user) {
+ return checkOAuthScopes(OAuthScope.MANAGE_VAULT) &&
+ checkUserPermission(user, GroupPermission.ROLE_ADMIN_MAP);
+ }
+}
diff --git a/src/main/java/com/faforever/api/security/elide/permission/AdminModCheck.java b/src/main/java/com/faforever/api/security/elide/permission/AdminModCheck.java
new file mode 100644
index 000000000..4fbf7307a
--- /dev/null
+++ b/src/main/java/com/faforever/api/security/elide/permission/AdminModCheck.java
@@ -0,0 +1,17 @@
+package com.faforever.api.security.elide.permission;
+
+import com.faforever.api.data.domain.GroupPermission;
+import com.faforever.api.security.OAuthScope;
+import com.yahoo.elide.security.User;
+import lombok.extern.slf4j.Slf4j;
+
+@Slf4j
+public class AdminModCheck extends FafUserCheck {
+ public static final String EXPRESSION = "AdminMod";
+
+ @Override
+ public boolean ok(User user) {
+ return checkOAuthScopes(OAuthScope.MANAGE_VAULT) &&
+ checkUserPermission(user, GroupPermission.ROLE_ADMIN_MOD);
+ }
+}
diff --git a/src/main/java/com/faforever/api/security/elide/permission/AdminModerationReportCheck.java b/src/main/java/com/faforever/api/security/elide/permission/AdminModerationReportCheck.java
new file mode 100644
index 000000000..6b84a2444
--- /dev/null
+++ b/src/main/java/com/faforever/api/security/elide/permission/AdminModerationReportCheck.java
@@ -0,0 +1,17 @@
+package com.faforever.api.security.elide.permission;
+
+import com.faforever.api.data.domain.GroupPermission;
+import com.faforever.api.security.OAuthScope;
+import com.yahoo.elide.security.User;
+import lombok.extern.slf4j.Slf4j;
+
+@Slf4j
+public class AdminModerationReportCheck extends FafUserCheck {
+ public static final String EXPRESSION = "AdminModerationReport";
+
+ @Override
+ public boolean ok(User user) {
+ return checkOAuthScopes(OAuthScope.ADMINISTRATIVE_ACTION) &&
+ checkUserPermission(user, GroupPermission.ROLE_ADMIN_MODERATION_REPORT);
+ }
+}
diff --git a/src/main/java/com/faforever/api/security/elide/permission/AdminVoteCheck.java b/src/main/java/com/faforever/api/security/elide/permission/AdminVoteCheck.java
new file mode 100644
index 000000000..4b30c2b65
--- /dev/null
+++ b/src/main/java/com/faforever/api/security/elide/permission/AdminVoteCheck.java
@@ -0,0 +1,17 @@
+package com.faforever.api.security.elide.permission;
+
+import com.faforever.api.data.domain.GroupPermission;
+import com.faforever.api.security.OAuthScope;
+import com.yahoo.elide.security.User;
+import lombok.extern.slf4j.Slf4j;
+
+@Slf4j
+public class AdminVoteCheck extends FafUserCheck {
+ public static final String EXPRESSION = "AdminVote";
+
+ @Override
+ public boolean ok(User user) {
+ return checkOAuthScopes(OAuthScope.ADMINISTRATIVE_ACTION) &&
+ checkUserPermission(user, GroupPermission.ROLE_ADMIN_VOTE);
+ }
+}
diff --git a/src/main/java/com/faforever/api/security/elide/permission/FafUserCheck.java b/src/main/java/com/faforever/api/security/elide/permission/FafUserCheck.java
new file mode 100644
index 000000000..4173d9557
--- /dev/null
+++ b/src/main/java/com/faforever/api/security/elide/permission/FafUserCheck.java
@@ -0,0 +1,81 @@
+package com.faforever.api.security.elide.permission;
+
+import com.faforever.api.security.FafUserDetails;
+import com.faforever.api.security.OAuthScope;
+import com.yahoo.elide.security.User;
+import com.yahoo.elide.security.checks.UserCheck;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.core.GrantedAuthority;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.security.oauth2.provider.OAuth2Authentication;
+import org.springframework.security.oauth2.provider.OAuth2Request;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+@Slf4j
+abstract class FafUserCheck extends UserCheck {
+ protected boolean checkOAuthScopes(OAuthScope... scope) {
+ return checkOAuthScopes(Stream.of(scope).map(OAuthScope::getKey).toArray(String[]::new));
+ }
+
+ private boolean checkOAuthScopes(String... scope) {
+ Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
+ if (!(authentication instanceof OAuth2Authentication)) {
+ log.trace("Authentication is no OAuth2Authentication: {}", authentication);
+ return false;
+ }
+
+ OAuth2Authentication oAuth2Authentication = ((OAuth2Authentication) authentication);
+ OAuth2Request oAuth2Request = oAuth2Authentication.getOAuth2Request();
+
+ List missedScopes = new ArrayList<>();
+
+ for (String currentScope : scope) {
+ if (!oAuth2Request.getScope().contains(currentScope)) {
+ missedScopes.add(currentScope);
+ }
+ }
+
+ if (log.isTraceEnabled()) {
+ if (missedScopes.isEmpty()) {
+ log.trace("All requested scopes are granted: {}", String.join(", ", scope));
+ } else {
+ log.trace("Scopes '{}' are not granted in requested scopes: {} for client with id {}", String.join(", ", missedScopes), String.join(", ", oAuth2Request.getScope()), oAuth2Request.getResourceIds());
+ }
+ }
+
+ return missedScopes.isEmpty();
+ }
+
+ protected boolean checkUserPermission(User user, String... userPermissionRole) {
+ if (!(user.getOpaqueUser() instanceof FafUserDetails)) {
+ log.warn("UserCheck applied on wrong User type: {}", user);
+ return false;
+ }
+
+ FafUserDetails userDetails = (FafUserDetails) user.getOpaqueUser();
+
+ Set grantedUserRoles = userDetails.getAuthorities().stream()
+ .map(GrantedAuthority::getAuthority)
+ .collect(Collectors.toSet());
+
+ Set missedScopes = Stream.of(userPermissionRole)
+ .collect(Collectors.toSet());
+ missedScopes.removeAll(grantedUserRoles);
+
+ if (log.isTraceEnabled()) {
+ if (missedScopes.isEmpty()) {
+ log.trace("All requested permissions are granted: {}", String.join(", ", userPermissionRole));
+ } else {
+ log.trace("Permissions '{}' are not granted in requested permissions: {} , for user with id: {}", String.join(", ", missedScopes), String.join(", ", grantedUserRoles), userDetails.getId());
+ }
+ }
+
+ return missedScopes.isEmpty();
+ }
+}
diff --git a/src/main/java/com/faforever/api/security/elide/permission/ReadAccountPrivateDetailsCheck.java b/src/main/java/com/faforever/api/security/elide/permission/ReadAccountPrivateDetailsCheck.java
new file mode 100644
index 000000000..940ecdbf1
--- /dev/null
+++ b/src/main/java/com/faforever/api/security/elide/permission/ReadAccountPrivateDetailsCheck.java
@@ -0,0 +1,17 @@
+package com.faforever.api.security.elide.permission;
+
+import com.faforever.api.data.domain.GroupPermission;
+import com.faforever.api.security.OAuthScope;
+import com.yahoo.elide.security.User;
+import lombok.extern.slf4j.Slf4j;
+
+@Slf4j
+public class ReadAccountPrivateDetailsCheck extends FafUserCheck {
+ public static final String EXPRESSION = "ReadAccountPrivateDetails";
+
+ @Override
+ public boolean ok(User user) {
+ return checkOAuthScopes(OAuthScope.READ_SENSIBLE_USERDATA) &&
+ checkUserPermission(user, GroupPermission.ROLE_READ_ACCOUNT_PRIVATE_DETAILS);
+ }
+}
diff --git a/src/main/java/com/faforever/api/security/elide/permission/ReadTeamkillReportCheck.java b/src/main/java/com/faforever/api/security/elide/permission/ReadTeamkillReportCheck.java
new file mode 100644
index 000000000..074be1384
--- /dev/null
+++ b/src/main/java/com/faforever/api/security/elide/permission/ReadTeamkillReportCheck.java
@@ -0,0 +1,17 @@
+package com.faforever.api.security.elide.permission;
+
+import com.faforever.api.data.domain.GroupPermission;
+import com.faforever.api.security.OAuthScope;
+import com.yahoo.elide.security.User;
+import lombok.extern.slf4j.Slf4j;
+
+@Slf4j
+public class ReadTeamkillReportCheck extends FafUserCheck {
+ public static final String EXPRESSION = "ReadTeamkillReport";
+
+ @Override
+ public boolean ok(User user) {
+ return checkOAuthScopes(OAuthScope.ADMINISTRATIVE_ACTION) &&
+ checkUserPermission(user, GroupPermission.ROLE_READ_TEAMKILL_REPORT);
+ }
+}
diff --git a/src/main/java/com/faforever/api/security/elide/permission/ReadUserGroupCheck.java b/src/main/java/com/faforever/api/security/elide/permission/ReadUserGroupCheck.java
new file mode 100644
index 000000000..2fef9938b
--- /dev/null
+++ b/src/main/java/com/faforever/api/security/elide/permission/ReadUserGroupCheck.java
@@ -0,0 +1,17 @@
+package com.faforever.api.security.elide.permission;
+
+import com.faforever.api.data.domain.GroupPermission;
+import com.faforever.api.security.OAuthScope;
+import com.yahoo.elide.security.User;
+import lombok.extern.slf4j.Slf4j;
+
+@Slf4j
+public class ReadUserGroupCheck extends FafUserCheck {
+ public static final String EXPRESSION = "ReadUserGroup";
+
+ @Override
+ public boolean ok(User user) {
+ return checkOAuthScopes(OAuthScope.READ_SENSIBLE_USERDATA) &&
+ checkUserPermission(user, GroupPermission.ROLE_READ_USER_GROUP);
+ }
+}
diff --git a/src/main/java/com/faforever/api/security/elide/permission/WriteAvatarCheck.java b/src/main/java/com/faforever/api/security/elide/permission/WriteAvatarCheck.java
new file mode 100644
index 000000000..8c2936625
--- /dev/null
+++ b/src/main/java/com/faforever/api/security/elide/permission/WriteAvatarCheck.java
@@ -0,0 +1,16 @@
+package com.faforever.api.security.elide.permission;
+
+import com.faforever.api.data.domain.GroupPermission;
+import com.faforever.api.security.OAuthScope;
+import com.yahoo.elide.security.User;
+
+public class WriteAvatarCheck extends FafUserCheck {
+
+ public static final String EXPRESSION = "WriteAvatar";
+
+ @Override
+ public boolean ok(User user) {
+ return checkOAuthScopes(OAuthScope.ADMINISTRATIVE_ACTION) &&
+ checkUserPermission(user, GroupPermission.ROLE_WRITE_AVATAR);
+ }
+}
diff --git a/src/main/java/com/faforever/api/security/elide/permission/WriteEmailDomainBanCheck.java b/src/main/java/com/faforever/api/security/elide/permission/WriteEmailDomainBanCheck.java
new file mode 100644
index 000000000..a9a1484bd
--- /dev/null
+++ b/src/main/java/com/faforever/api/security/elide/permission/WriteEmailDomainBanCheck.java
@@ -0,0 +1,16 @@
+package com.faforever.api.security.elide.permission;
+
+import com.faforever.api.data.domain.GroupPermission;
+import com.faforever.api.security.OAuthScope;
+import com.yahoo.elide.security.User;
+
+public class WriteEmailDomainBanCheck extends FafUserCheck {
+
+ public static final String EXPRESSION = "WriteEmailDomainBan";
+
+ @Override
+ public boolean ok(User user) {
+ return checkOAuthScopes(OAuthScope.ADMINISTRATIVE_ACTION) &&
+ checkUserPermission(user, GroupPermission.ROLE_WRITE_EMAIL_DOMAIN_BAN);
+ }
+}
diff --git a/src/main/java/com/faforever/api/security/elide/permission/WriteMatchmakerMapCheck.java b/src/main/java/com/faforever/api/security/elide/permission/WriteMatchmakerMapCheck.java
new file mode 100644
index 000000000..19ad75e74
--- /dev/null
+++ b/src/main/java/com/faforever/api/security/elide/permission/WriteMatchmakerMapCheck.java
@@ -0,0 +1,16 @@
+package com.faforever.api.security.elide.permission;
+
+import com.faforever.api.data.domain.GroupPermission;
+import com.faforever.api.security.OAuthScope;
+import com.yahoo.elide.security.User;
+
+public class WriteMatchmakerMapCheck extends FafUserCheck {
+
+ public static final String EXPRESSION = "AdminMatchmakerMap";
+
+ @Override
+ public boolean ok(User user) {
+ return checkOAuthScopes(OAuthScope.ADMINISTRATIVE_ACTION) &&
+ checkUserPermission(user, GroupPermission.ROLE_WRITE_MATCHMAKER_MAP);
+ }
+}
diff --git a/src/main/java/com/faforever/api/security/elide/permission/WriteMatchmakerPoolCheck.java b/src/main/java/com/faforever/api/security/elide/permission/WriteMatchmakerPoolCheck.java
new file mode 100644
index 000000000..fc232326d
--- /dev/null
+++ b/src/main/java/com/faforever/api/security/elide/permission/WriteMatchmakerPoolCheck.java
@@ -0,0 +1,16 @@
+package com.faforever.api.security.elide.permission;
+
+import com.faforever.api.data.domain.GroupPermission;
+import com.faforever.api.security.OAuthScope;
+import com.yahoo.elide.security.User;
+
+public class WriteMatchmakerPoolCheck extends FafUserCheck {
+
+ public static final String EXPRESSION = "AdminMatchmakerPool";
+
+ @Override
+ public boolean ok(User user) {
+ return checkOAuthScopes(OAuthScope.ADMINISTRATIVE_ACTION) &&
+ checkUserPermission(user, GroupPermission.ROLE_WRITE_MATCHMAKER_POOL);
+ }
+}
diff --git a/src/main/java/com/faforever/api/security/elide/permission/WriteMessageCheck.java b/src/main/java/com/faforever/api/security/elide/permission/WriteMessageCheck.java
new file mode 100644
index 000000000..11331930e
--- /dev/null
+++ b/src/main/java/com/faforever/api/security/elide/permission/WriteMessageCheck.java
@@ -0,0 +1,16 @@
+package com.faforever.api.security.elide.permission;
+
+import com.faforever.api.data.domain.GroupPermission;
+import com.faforever.api.security.OAuthScope;
+import com.yahoo.elide.security.User;
+
+public class WriteMessageCheck extends FafUserCheck {
+
+ public static final String EXPRESSION = "WriteMessage";
+
+ @Override
+ public boolean ok(User user) {
+ return checkOAuthScopes(OAuthScope.ADMINISTRATIVE_ACTION) &&
+ checkUserPermission(user, GroupPermission.ROLE_WRITE_MESSAGE);
+ }
+}
diff --git a/src/main/java/com/faforever/api/security/elide/permission/WriteNewsPostCheck.java b/src/main/java/com/faforever/api/security/elide/permission/WriteNewsPostCheck.java
new file mode 100644
index 000000000..3e9a85aa3
--- /dev/null
+++ b/src/main/java/com/faforever/api/security/elide/permission/WriteNewsPostCheck.java
@@ -0,0 +1,16 @@
+package com.faforever.api.security.elide.permission;
+
+import com.faforever.api.data.domain.GroupPermission;
+import com.faforever.api.security.OAuthScope;
+import com.yahoo.elide.security.User;
+
+public class WriteNewsPostCheck extends FafUserCheck {
+
+ public static final String EXPRESSION = "WriteNewsPost";
+
+ @Override
+ public boolean ok(User user) {
+ return checkOAuthScopes(OAuthScope.ADMINISTRATIVE_ACTION) &&
+ checkUserPermission(user, GroupPermission.ROLE_WRITE_NEWS_POST);
+ }
+}
diff --git a/src/main/java/com/faforever/api/security/elide/permission/WriteTutorialCheck.java b/src/main/java/com/faforever/api/security/elide/permission/WriteTutorialCheck.java
new file mode 100644
index 000000000..54d2d2eb8
--- /dev/null
+++ b/src/main/java/com/faforever/api/security/elide/permission/WriteTutorialCheck.java
@@ -0,0 +1,16 @@
+package com.faforever.api.security.elide.permission;
+
+import com.faforever.api.data.domain.GroupPermission;
+import com.faforever.api.security.OAuthScope;
+import com.yahoo.elide.security.User;
+
+public class WriteTutorialCheck extends FafUserCheck {
+
+ public static final String EXPRESSION = "WriteTutorial";
+
+ @Override
+ public boolean ok(User user) {
+ return checkOAuthScopes(OAuthScope.ADMINISTRATIVE_ACTION) &&
+ checkUserPermission(user, GroupPermission.ROLE_WRITE_TUTORIAL);
+ }
+}
diff --git a/src/main/java/com/faforever/api/security/elide/permission/WriteUserGroupCheck.java b/src/main/java/com/faforever/api/security/elide/permission/WriteUserGroupCheck.java
new file mode 100644
index 000000000..6147fa3c8
--- /dev/null
+++ b/src/main/java/com/faforever/api/security/elide/permission/WriteUserGroupCheck.java
@@ -0,0 +1,17 @@
+package com.faforever.api.security.elide.permission;
+
+import com.faforever.api.data.domain.GroupPermission;
+import com.faforever.api.security.OAuthScope;
+import com.yahoo.elide.security.User;
+import lombok.extern.slf4j.Slf4j;
+
+@Slf4j
+public class WriteUserGroupCheck extends FafUserCheck {
+ public static final String EXPRESSION = "WriteUserGroup";
+
+ @Override
+ public boolean ok(User user) {
+ return checkOAuthScopes(OAuthScope.ADMINISTRATIVE_ACTION) &&
+ checkUserPermission(user, GroupPermission.ROLE_WRITE_USER_GROUP);
+ }
+}
diff --git a/src/main/resources/config/application.yml b/src/main/resources/config/application.yml
index 04512b97a..9415d4d98 100644
--- a/src/main/resources/config/application.yml
+++ b/src/main/resources/config/application.yml
@@ -9,7 +9,7 @@ faf-api:
challonge:
key: ${CHALLONGE_KEY:}
database:
- schema-version: ${DATABASE_SCHEMA_VERSION:76}
+ schema-version: ${DATABASE_SCHEMA_VERSION:77}
mautic:
base-url: ${MAUTIC_BASE_URL:false}
client-id: ${MAUTIC_CLIENT_ID:false}