package net.frozenorb.apiv3.models; import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; import lombok.Getter; import lombok.Setter; import net.frozenorb.apiv3.APIv3; import net.frozenorb.apiv3.serialization.ExcludeFromReplies; import net.frozenorb.apiv3.utils.TimeUtils; import org.bson.Document; import org.mindrot.jbcrypt.BCrypt; import org.mongodb.morphia.annotations.Entity; import org.mongodb.morphia.annotations.Id; import java.util.*; @Entity(value = "users", noClassnameStored = true) public final class User { @Getter @Id private UUID id; @Getter private String lastUsername; @Getter @ExcludeFromReplies private Map aliases; @Getter @ExcludeFromReplies private String otpCode; @Getter @ExcludeFromReplies @Setter private String emailToken; @Getter @ExcludeFromReplies @Setter private Date emailTokenSet; @Getter @ExcludeFromReplies private String password; @Getter @Setter private String email; @Getter private int phoneNumber; @Getter private String lastSeenOn; @Getter private Date lastSeenAt; @Getter private Date firstSeen; public static User byId(String id) { try { return byId(UUID.fromString(id)); } catch (Exception ex) { throw new IllegalArgumentException("Invalid UUID string " + id, ex); } } public static User byId(UUID id) { return APIv3.getDatastore().createQuery(User.class).field("id").equal(id).get(); } public static User byEmailToken(String name) { return APIv3.getDatastore().createQuery(User.class).field("emailToken").equal(name).get(); } @Deprecated public static User byLastUsername(String lastUsername) { return APIv3.getDatastore().createQuery(User.class).field("lastUsername").equal(lastUsername).get(); } public User() {} // For Morphia public User(UUID id, String lastUsername) { this.id = id; this.lastUsername = lastUsername; this.aliases = new HashMap<>(); this.otpCode = null; this.password = null; this.email = null; this.phoneNumber = -1; this.lastSeenOn = null; this.lastSeenAt = new Date(); this.firstSeen = new Date(); aliases.put(lastUsername, new Date()); } public boolean hasPermissionScoped(String permission, ServerGroup scope) { Map permissions = scope.calculatePermissions(getHighestRank(scope)); return permissions.containsKey(permission) && permissions.get(permission); } // TODO public boolean hasPermissionAnywhere(String permission) { Map permissions = /*scope.calculatePermissions(getHighestRank(scope));*/ ImmutableMap.of(); return permissions.containsKey(permission) && permissions.get(permission); } public List getGrants() { return APIv3.getDatastore().createQuery(Grant.class).field("target").equal(id).asList(); } public List getIPLog() { return APIv3.getDatastore().createQuery(IPLogEntry.class).field("user").equal(id).asList(); } public IPLogEntry getIPLogEntry(String ip) { IPLogEntry existing = APIv3.getDatastore().createQuery(IPLogEntry.class).field("user").equal(id).field("ip").equal(ip).get(); if (existing == null) { existing = new IPLogEntry(this, ip); APIv3.getDatastore().save(existing); } return existing; } public List getPunishments() { return APIv3.getDatastore().createQuery(Punishment.class).field("target").equal(id).asList(); } public List getPunishments(Collection types) { return APIv3.getDatastore().createQuery(Punishment.class).field("target").equal(id).field("type").in(types).asList(); } public UserMetaEntry getMeta(ServerGroup group) { return APIv3.getDatastore().createQuery(UserMetaEntry.class).field("user").equal(id).field("serverGroup").equalIgnoreCase(group.getId()).get(); } public void saveMeta(ServerGroup group, Document data) { UserMetaEntry entry = getMeta(group); if (entry == null) { APIv3.getDatastore().save(new UserMetaEntry(this, group, data)); } else { entry.setData(data); APIv3.getDatastore().save(entry); } } public void seenOnServer(Server server) { this.lastSeenOn = server.getId(); this.lastSeenAt = new Date(); } public void setPassword(char[] unencrypted) { this.password = BCrypt.hashpw(new String(unencrypted), BCrypt.gensalt()); } public boolean checkPassword(char[] unencrypted) { return BCrypt.checkpw(new String(unencrypted), password); } public Rank getHighestRank(ServerGroup serverGroup) { Rank highest = null; for (Grant grant : getGrants()) { if (!grant.isActive() || (serverGroup != null && !grant.appliesOn(serverGroup))) { continue; } Rank rank = Rank.byId(grant.getRank()); if (highest == null || rank.getWeight() > highest.getWeight()) { highest = rank; } } if (highest != null) { return highest; } else { return Rank.byId("default"); } } public Rank getHighestRank() { return getHighestRank(null); } public Map getLoginInfo(Server server) { String accessDenialReason = null; for (Punishment punishment : getPunishments(ImmutableSet.of( Punishment.PunishmentType.BLACKLIST, Punishment.PunishmentType.BAN ))) { if (!punishment.isActive()) { continue; } if (punishment.getType() == Punishment.PunishmentType.BLACKLIST) { accessDenialReason = "Your account has been blacklisted from the MineHQ Network. \n\nThis type of punishment cannot be appealed."; } else { accessDenialReason = "Your account has been suspended from the MineHQ Network. \n\n"; if (punishment.getExpiresAt() != null) { accessDenialReason += "Expires in " + TimeUtils.formatIntoDetailedString(TimeUtils.getSecondsBetween(punishment.getExpiresAt(), new Date())); } else { accessDenialReason += "Appeal at MineHQ.com/appeal"; } } } ServerGroup actorGroup = ServerGroup.byId(server.getGroup()); Rank rank = getHighestRank(actorGroup); Map rankPermissions = actorGroup.calculatePermissions(rank); return ImmutableMap.of( "user", this, "access", ImmutableMap.of( "allowed", accessDenialReason == null, "reason", accessDenialReason == null ? "Public server" : accessDenialReason ), "rank", rank, "permissions", rankPermissions ); } }