Redo rank calculation to allow ranks that aren't part of the primary inheritance chain. Finishes #33
This commit is contained in:
parent
1b20362f4d
commit
983c428a09
@ -314,8 +314,8 @@ public final class APIv3 extends AbstractVerticle {
|
||||
|
||||
http.get("/staff").blockingHandler(new GETStaff(), false);
|
||||
http.get("/users/:id").handler(new GETUsersId());
|
||||
http.get("/users/:id/compoundedPermissions").handler(new GETUsersIdCompoundedPermissions());
|
||||
http.get("/users/:id/details").blockingHandler(new GETUsersIdDetails(), false);
|
||||
http.get("/users/:id/permissions").handler(new GETUsersIdPermissions());
|
||||
http.get("/users/:id/requiresTotp").handler(new GETUsersIdRequiresTotp());
|
||||
http.get("/users/:id/verifyPassword").blockingHandler(new GETUsersIdVerifyPassword(), false);
|
||||
http.post("/users/:id/changePassword").blockingHandler(new POSTUsersIdChangePassword(), false);
|
||||
@ -343,7 +343,7 @@ public final class APIv3 extends AbstractVerticle {
|
||||
ctx.response().setStatusCode(code);
|
||||
|
||||
if (!ctx.request().path().contains("dumps")) {
|
||||
//log.info(gson.toJson(response));
|
||||
log.info(gson.toJson(response));
|
||||
}
|
||||
|
||||
ctx.response().end(gson.toJson(response));
|
||||
|
@ -7,6 +7,7 @@ import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.hash.Hashing;
|
||||
import com.google.common.primitives.Ints;
|
||||
import com.mongodb.async.SingleResultCallback;
|
||||
import com.mongodb.async.client.MongoCollection;
|
||||
import com.mongodb.client.result.UpdateResult;
|
||||
@ -34,6 +35,7 @@ import java.time.Instant;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Entity
|
||||
@AllArgsConstructor
|
||||
@ -250,10 +252,12 @@ public final class User {
|
||||
}
|
||||
|
||||
Map<String, Object> result = new HashMap<>();
|
||||
List<Rank> ranks = getRanksScoped(serverGroup, grants);
|
||||
|
||||
result.put("user", this);
|
||||
result.put("access", accessInfo);
|
||||
result.put("rank", getHighestRankScoped(serverGroup, grants).getId());
|
||||
result.put("bestRank", ranks.get(0).getId());
|
||||
result.put("ranks", ranks.stream().map(Rank::getId).collect(Collectors.toList()));
|
||||
result.put("totpSetup", getTotpSecret() != null);
|
||||
|
||||
if (activeMute != null) {
|
||||
@ -472,7 +476,7 @@ public final class User {
|
||||
}
|
||||
|
||||
public void hasPermissionAnywhere(String permission, SingleResultCallback<Boolean> callback) {
|
||||
getGlobalPermissions((permissions, error) -> {
|
||||
getCompoundedPermissions((permissions, error) -> {
|
||||
if (error != null) {
|
||||
callback.onResult(null, error);
|
||||
} else {
|
||||
@ -482,58 +486,79 @@ public final class User {
|
||||
});
|
||||
}
|
||||
|
||||
public void getGlobalPermissions(SingleResultCallback<Map<String, Boolean>> callback) {
|
||||
public void getCompoundedPermissions(SingleResultCallback<Map<String, Boolean>> callback) {
|
||||
Grant.findByUser(this, (grants, error) -> {
|
||||
if (error != null) {
|
||||
callback.onResult(null, error);
|
||||
} else {
|
||||
Map<String, Boolean> globalPermissions = PermissionUtils.getDefaultPermissions(getHighestRankScoped(null, grants));
|
||||
|
||||
for (Map.Entry<ServerGroup, Rank> serverGroupEntry : getHighestRanks(grants).entrySet()) {
|
||||
ServerGroup serverGroup = serverGroupEntry.getKey();
|
||||
Rank rank = serverGroupEntry.getValue();
|
||||
Map<String, Boolean> globalPermissions = new HashMap<>();
|
||||
|
||||
for (Rank globalRank : getRanksScoped(null, grants)) {
|
||||
globalPermissions = PermissionUtils.mergePermissions(
|
||||
globalPermissions,
|
||||
serverGroup.calculateScopedPermissions(rank)
|
||||
PermissionUtils.getDefaultPermissions(globalRank)
|
||||
);
|
||||
}
|
||||
|
||||
for (ServerGroup serverGroup : ServerGroup.findAll()) {
|
||||
for (Rank scopedRank : getRanksScoped(serverGroup, grants)) {
|
||||
globalPermissions = PermissionUtils.mergePermissions(
|
||||
globalPermissions,
|
||||
serverGroup.calculateScopedPermissions(scopedRank)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
callback.onResult(ImmutableMap.copyOf(globalPermissions), null);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private Map<ServerGroup, Rank> getHighestRanks(List<Grant> grants) {
|
||||
Map<ServerGroup, Rank> highestRanks = new HashMap<>();
|
||||
|
||||
for (ServerGroup serverGroup : ServerGroup.findAll()) {
|
||||
highestRanks.put(serverGroup, getHighestRankScoped(serverGroup, grants));
|
||||
}
|
||||
|
||||
return highestRanks;
|
||||
}
|
||||
|
||||
private Rank getHighestRankScoped(ServerGroup serverGroup, Iterable<Grant> grants) {
|
||||
Rank highest = null;
|
||||
private List<Rank> getRanksScoped(ServerGroup serverGroup, Iterable<Grant> grants) {
|
||||
List<Rank> grantedRanks = new LinkedList<>();
|
||||
|
||||
for (Grant grant : grants) {
|
||||
if (!grant.isActive() || (serverGroup != null && !grant.appliesOn(serverGroup))) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Rank rank = Rank.findById(grant.getRank());
|
||||
Rank grantedRank = Rank.findById(grant.getRank());
|
||||
grantedRanks.add(grantedRank);
|
||||
}
|
||||
|
||||
if (highest == null || rank.getWeight() > highest.getWeight()) {
|
||||
highest = rank;
|
||||
if (grantedRanks.isEmpty()) {
|
||||
grantedRanks.add(Rank.findById("default"));
|
||||
return grantedRanks;
|
||||
}
|
||||
|
||||
Iterator<Rank> iterator = grantedRanks.iterator();
|
||||
|
||||
// This is to remove redundant ranks. Say they have mod, mod-plus, admin, and youtuber,
|
||||
// we should remove mod and mod-plus as it'll be made redundant by the higher ranked admin.
|
||||
while (iterator.hasNext()) {
|
||||
Rank rank = iterator.next();
|
||||
|
||||
// Check all other ranks for inherited collision
|
||||
for (Rank otherRank : grantedRanks) {
|
||||
if (otherRank == rank) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Rank parent = otherRank;
|
||||
|
||||
// Iterate up the inheritance tree to detect rank redundancies.
|
||||
while (parent.getInheritsFromId() != null) {
|
||||
if (parent == rank) {
|
||||
iterator.remove();
|
||||
}
|
||||
|
||||
parent = Rank.findById(otherRank.getInheritsFromId());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (highest != null) {
|
||||
return highest;
|
||||
} else {
|
||||
return Rank.findById("default");
|
||||
}
|
||||
grantedRanks.sort((a, b) -> Ints.compare(b.getWeight(), a.getWeight()));
|
||||
return grantedRanks;
|
||||
}
|
||||
|
||||
public void insert(SingleResultCallback<Void> callback) {
|
||||
|
@ -6,7 +6,7 @@ import net.frozenorb.apiv3.APIv3;
|
||||
import net.frozenorb.apiv3.model.User;
|
||||
import net.frozenorb.apiv3.util.ErrorUtils;
|
||||
|
||||
public final class GETUsersIdPermissions implements Handler<RoutingContext> {
|
||||
public final class GETUsersIdCompoundedPermissions implements Handler<RoutingContext> {
|
||||
|
||||
public void handle(RoutingContext ctx) {
|
||||
User.findById(ctx.request().getParam("id"), (user, error) -> {
|
||||
@ -15,7 +15,7 @@ public final class GETUsersIdPermissions implements Handler<RoutingContext> {
|
||||
} else if (user == null) {
|
||||
ErrorUtils.respondNotFound(ctx, "User", ctx.request().getParam("id"));
|
||||
} else {
|
||||
user.getGlobalPermissions((permissions, error2) -> {
|
||||
user.getCompoundedPermissions((permissions, error2) -> {
|
||||
if (error2 != null) {
|
||||
ErrorUtils.respondInternalError(ctx, error2);
|
||||
} else {
|
Loading…
Reference in New Issue
Block a user