mirror of
https://github.com/GravitLauncher/Launcher
synced 2024-11-15 03:31:15 +03:00
[FEATURE] Permissions
This commit is contained in:
parent
e782f0409d
commit
9841ef3157
11 changed files with 166 additions and 23 deletions
|
@ -121,6 +121,7 @@ public final class LaunchServer implements Runnable, AutoCloseable, Reconfigurab
|
|||
// Updates and profiles
|
||||
private volatile Set<ClientProfile> profilesList;
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
public LaunchServer(LaunchServerDirectories directories, LaunchServerEnv env, LaunchServerConfig config, LaunchServerRuntimeConfig runtimeConfig, LaunchServerConfigManager launchServerConfigManager, LaunchServerModulesManager modulesManager, KeyAgreementManager keyAgreementManager, CommandHandler commandHandler, CertificateManager certificateManager) throws IOException {
|
||||
this.dir = directories.dir;
|
||||
this.tmpDir = directories.tmpDir;
|
||||
|
@ -405,6 +406,7 @@ public void restart() {
|
|||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
public void registerObject(String name, Object object) {
|
||||
if (object instanceof Reconfigurable) {
|
||||
reconfigurableManager.registerReconfigurable(name, (Reconfigurable) object);
|
||||
|
@ -414,6 +416,7 @@ public void registerObject(String name, Object object) {
|
|||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
public void unregisterObject(String name, Object object) {
|
||||
if (object instanceof Reconfigurable) {
|
||||
reconfigurableManager.unregisterReconfigurable(name);
|
||||
|
|
|
@ -1,8 +1,11 @@
|
|||
package pro.gravit.launchserver.auth;
|
||||
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import pro.gravit.launchserver.LaunchServer;
|
||||
import pro.gravit.launchserver.auth.core.AuthCoreProvider;
|
||||
import pro.gravit.launchserver.auth.core.AuthSocialProvider;
|
||||
import pro.gravit.launchserver.auth.core.MySQLCoreProvider;
|
||||
import pro.gravit.launchserver.auth.texture.TextureProvider;
|
||||
|
||||
import java.io.IOException;
|
||||
|
@ -11,6 +14,7 @@
|
|||
import java.util.Set;
|
||||
|
||||
public final class AuthProviderPair {
|
||||
private transient final Logger logger = LogManager.getLogger();
|
||||
public boolean isDefault = true;
|
||||
public AuthCoreProvider core;
|
||||
public AuthSocialProvider social;
|
||||
|
@ -19,6 +23,7 @@ public final class AuthProviderPair {
|
|||
public transient String name;
|
||||
public transient Set<String> features;
|
||||
public String displayName;
|
||||
private transient boolean warnOAuthShow = false;
|
||||
|
||||
public AuthProviderPair(AuthCoreProvider core, TextureProvider textureProvider) {
|
||||
this.core = core;
|
||||
|
@ -42,6 +47,15 @@ public static Set<String> getFeatures(Class<?> clazz) {
|
|||
return list;
|
||||
}
|
||||
|
||||
public void internalShowOAuthWarnMessage() {
|
||||
if(!warnOAuthShow) {
|
||||
if(!(core instanceof MySQLCoreProvider)) { // MySQL upgraded later
|
||||
logger.warn("AuthCoreProvider {} ({}) not supported OAuth. Legacy session system may be removed in next release", name, core.getClass().getName());
|
||||
}
|
||||
warnOAuthShow = true;
|
||||
}
|
||||
}
|
||||
|
||||
public static void getFeatures(Class<?> clazz, Set<String> list) {
|
||||
Features features = clazz.getAnnotation(Features.class);
|
||||
if (features != null) {
|
||||
|
|
|
@ -141,8 +141,10 @@ public boolean onJoinServer(String serverID, String username, Client client) {
|
|||
|
||||
@Override
|
||||
public void init(LaunchServer server) {
|
||||
if (provider != null)
|
||||
if (provider != null) {
|
||||
provider.init(server);
|
||||
logger.warn("HWIDProvider deprecated. Please use 'AuthSupportHardware' in AuthCoreProvider");
|
||||
}
|
||||
this.server = server;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,16 +1,17 @@
|
|||
package pro.gravit.launchserver.auth.protect;
|
||||
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import pro.gravit.launcher.profiles.ClientProfile;
|
||||
import pro.gravit.launchserver.LaunchServer;
|
||||
import pro.gravit.launchserver.auth.protect.interfaces.ProfilesProtectHandler;
|
||||
import pro.gravit.launchserver.socket.Client;
|
||||
import pro.gravit.launchserver.socket.response.auth.AuthResponse;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.*;
|
||||
|
||||
public class StdProtectHandler extends ProtectHandler implements ProfilesProtectHandler {
|
||||
private transient final Logger logger = LogManager.getLogger();
|
||||
public Map<String, List<String>> profileWhitelist = new HashMap<>();
|
||||
public List<String> allowUpdates = new ArrayList<>();
|
||||
|
||||
|
@ -24,14 +25,21 @@ public void checkLaunchServerLicense() {
|
|||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init(LaunchServer server) {
|
||||
if(profileWhitelist != null && profileWhitelist.size() > 0) {
|
||||
logger.warn("profileWhitelist deprecated. Please use permission 'launchserver.profile.PROFILE_UUID.show' and 'launchserver.profile.PROFILE_UUID.enter'");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canGetProfile(ClientProfile profile, Client client) {
|
||||
return canChangeProfile(profile, client);
|
||||
return client.isAuth && client.username != null && (!profile.isLimited() || isWhitelisted("launchserver.profile.%s.show", profile, client) );
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canChangeProfile(ClientProfile profile, Client client) {
|
||||
return client.isAuth && client.username != null && isWhitelisted(profile.getTitle(), client.username);
|
||||
return client.isAuth && client.username != null && (!profile.isLimited() || isWhitelisted("launchserver.profile.%s.enter", profile, client) );
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -39,9 +47,19 @@ public boolean canGetUpdates(String updatesDirName, Client client) {
|
|||
return client.profile != null && (client.profile.getDir().equals(updatesDirName) || client.profile.getAssetDir().equals(updatesDirName) || allowUpdates.contains(updatesDirName));
|
||||
}
|
||||
|
||||
public boolean isWhitelisted(String profileTitle, String username) {
|
||||
List<String> allowedUsername = profileWhitelist.get(profileTitle);
|
||||
if (allowedUsername == null) return true;
|
||||
return allowedUsername.contains(username);
|
||||
private boolean isWhitelisted(String property, ClientProfile profile, Client client) {
|
||||
if(client.permissions != null) {
|
||||
String permByUUID = String.format(property, profile.getUUID());
|
||||
if(client.permissions.hasAction(permByUUID)) {
|
||||
return true;
|
||||
}
|
||||
String permByTitle = String.format(property, profile.getTitle().toLowerCase(Locale.ROOT));
|
||||
if(client.permissions.hasAction(permByTitle)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
List<String> allowedUsername = profileWhitelist.get(profile.getTitle());
|
||||
if (allowedUsername != null && allowedUsername.contains(client.username)) return true;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -205,6 +205,9 @@ public AuthReport auth(AuthResponse.AuthContext context, AuthRequest.AuthPasswor
|
|||
* Writing authorization information to the Client object
|
||||
*/
|
||||
public void internalAuth(Client client, AuthResponse.ConnectTypes authType, AuthProviderPair pair, String username, UUID uuid, ClientPermissions permissions, boolean oauth) {
|
||||
if(!oauth) {
|
||||
pair.internalShowOAuthWarnMessage();
|
||||
}
|
||||
client.isAuth = true;
|
||||
client.permissions = permissions;
|
||||
client.auth_id = pair.name;
|
||||
|
|
|
@ -3,10 +3,7 @@
|
|||
import pro.gravit.launcher.serialize.HInput;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.*;
|
||||
|
||||
public class ClientPermissions {
|
||||
public static final ClientPermissions DEFAULT = new ClientPermissions();
|
||||
|
@ -21,7 +18,7 @@ public class ClientPermissions {
|
|||
@LauncherNetworkAPI
|
||||
private List<String> actions;
|
||||
|
||||
private transient List<Pattern> available;
|
||||
private transient List<PermissionPattern> available;
|
||||
|
||||
public ClientPermissions(HInput input) throws IOException {
|
||||
this(input.readLong());
|
||||
|
@ -61,12 +58,12 @@ public synchronized void compile() {
|
|||
}
|
||||
available = new ArrayList<>(actions.size());
|
||||
for (String a : actions) {
|
||||
available.add(Pattern.compile(a));
|
||||
available.add(new PermissionPattern(a));
|
||||
}
|
||||
if (permissions != 0) {
|
||||
if (isPermission(PermissionConsts.ADMIN)) {
|
||||
roles.add("ADMIN");
|
||||
available.add(Pattern.compile(".*"));
|
||||
available.add(new PermissionPattern("*"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -75,8 +72,8 @@ public boolean hasAction(String action) {
|
|||
if (available == null) {
|
||||
compile();
|
||||
}
|
||||
for (Pattern p : available) {
|
||||
if (p.matcher(action).matches()) {
|
||||
for (PermissionPattern p : available) {
|
||||
if (p.match(action)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -98,7 +95,7 @@ public void addAction(String action) {
|
|||
if(available == null) {
|
||||
available = new ArrayList<>(1);
|
||||
}
|
||||
available.add(Pattern.compile(action));
|
||||
available.add(new PermissionPattern(action));
|
||||
}
|
||||
|
||||
public List<String> getRoles() {
|
||||
|
@ -186,4 +183,54 @@ public enum FlagConsts {
|
|||
this.mask = mask;
|
||||
}
|
||||
}
|
||||
|
||||
public static class PermissionPattern {
|
||||
private final String[] parts;
|
||||
private final int priority;
|
||||
|
||||
public PermissionPattern(String pattern) {
|
||||
List<String> prepare = new ArrayList<>();
|
||||
for(int i=0;true;) {
|
||||
int pos = pattern.indexOf("*", i);
|
||||
if(pos >= 0) {
|
||||
prepare.add(pattern.substring(i, pos));
|
||||
i = pos+1;
|
||||
} else {
|
||||
prepare.add(pattern.substring(i));
|
||||
break;
|
||||
}
|
||||
}
|
||||
priority = prepare.size() - 1;
|
||||
parts = prepare.toArray(new String[0]);
|
||||
}
|
||||
|
||||
public int getPriority() {
|
||||
return priority;
|
||||
}
|
||||
|
||||
public boolean match(String str) {
|
||||
if(parts.length == 0) {
|
||||
return true;
|
||||
}
|
||||
if(parts.length == 1) {
|
||||
return parts[0].equals(str);
|
||||
}
|
||||
int offset = 0;
|
||||
if(!str.startsWith(parts[0])) {
|
||||
return false;
|
||||
}
|
||||
if(!str.endsWith(parts[parts.length-1])) {
|
||||
return false;
|
||||
}
|
||||
for(int i=1;i<parts.length-1;++i) {
|
||||
int pos = str.indexOf(parts[i], offset);
|
||||
if(pos >= 0) {
|
||||
offset = pos+1;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -77,6 +77,8 @@ public final class ClientProfile implements Comparable<ClientProfile> {
|
|||
private ProfileDefaultSettings settings = new ProfileDefaultSettings();
|
||||
@LauncherNetworkAPI
|
||||
private boolean updateFastCheck;
|
||||
@LauncherNetworkAPI
|
||||
private boolean limited;
|
||||
// Client launcher
|
||||
@LauncherNetworkAPI
|
||||
private String mainClass;
|
||||
|
@ -441,6 +443,10 @@ public void setRuntimeInClientConfig(RuntimeInClientConfig runtimeInClientConfig
|
|||
this.runtimeInClientConfig = runtimeInClientConfig;
|
||||
}
|
||||
|
||||
public boolean isLimited() {
|
||||
return limited;
|
||||
}
|
||||
|
||||
public enum Version {
|
||||
MC125("1.2.5", 29),
|
||||
MC147("1.4.7", 51),
|
||||
|
|
|
@ -0,0 +1,50 @@
|
|||
package pro.gravit.launcher;
|
||||
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
public class PermissionTest {
|
||||
@Test
|
||||
public void testPermission() {
|
||||
{
|
||||
ClientPermissions permissions = new ClientPermissions();
|
||||
permissions.addAction("*");
|
||||
Assertions.assertTrue(permissions.hasAction("abcd"));
|
||||
Assertions.assertTrue(permissions.hasAction("t.a.c.d.f.*"));
|
||||
Assertions.assertTrue(permissions.hasAction("*"));
|
||||
}
|
||||
{
|
||||
ClientPermissions permissions = new ClientPermissions();
|
||||
permissions.addAction("launchserver.*");
|
||||
Assertions.assertTrue(permissions.hasAction("launchserver.*"));
|
||||
Assertions.assertTrue(permissions.hasAction("launchserver.abcd"));
|
||||
Assertions.assertFalse(permissions.hasAction("default.abcd"));
|
||||
Assertions.assertFalse(permissions.hasAction("nolaunchserver.abcd"));
|
||||
}
|
||||
{
|
||||
ClientPermissions permissions = new ClientPermissions();
|
||||
permissions.addAction("launchserver.*.prop");
|
||||
Assertions.assertTrue(permissions.hasAction("launchserver.ii.prop"));
|
||||
Assertions.assertTrue(permissions.hasAction("launchserver.ia.prop"));
|
||||
Assertions.assertFalse(permissions.hasAction("default.abcd"));
|
||||
Assertions.assertFalse(permissions.hasAction("launchserver.ia"));
|
||||
Assertions.assertFalse(permissions.hasAction("launchserver.ia.prop2"));
|
||||
}
|
||||
{
|
||||
ClientPermissions permissions = new ClientPermissions();
|
||||
permissions.addAction("launchserver.*.def.*.prop");
|
||||
Assertions.assertTrue(permissions.hasAction("launchserver.1.def.2.prop"));
|
||||
Assertions.assertTrue(permissions.hasAction("launchserver.none.def.none.prop"));
|
||||
Assertions.assertTrue(permissions.hasAction("launchserver.def.def.def.prop"));
|
||||
Assertions.assertFalse(permissions.hasAction("launchserver.*.*.prop"));
|
||||
Assertions.assertFalse(permissions.hasAction("launchserver.*.undef.*.prop"));
|
||||
}
|
||||
{
|
||||
ClientPermissions permissions = new ClientPermissions();
|
||||
permissions.addAction("launchserver.*.e.*.i.*.prop");
|
||||
Assertions.assertTrue(permissions.hasAction("launchserver.2.e.3.i.4.prop"));
|
||||
Assertions.assertTrue(permissions.hasAction("launchserver.12212.e.233455.i.2356436346346345345345345.prop"));
|
||||
Assertions.assertFalse(permissions.hasAction("launchserver.prop"));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -7,6 +7,7 @@
|
|||
import java.util.Timer;
|
||||
import java.util.TimerTask;
|
||||
|
||||
@Deprecated
|
||||
public class GarbageManager {
|
||||
private static final Timer timer = new Timer("GarbageTimer");
|
||||
private static final Set<Entry> NEED_GARBARE_COLLECTION = new HashSet<>();
|
||||
|
|
|
@ -8,7 +8,7 @@ public final class Version implements Comparable<Version> {
|
|||
public static final int MINOR = 2;
|
||||
public static final int PATCH = 3;
|
||||
public static final int BUILD = 1;
|
||||
public static final Version.Type RELEASE = Type.DEV;
|
||||
public static final Version.Type RELEASE = Type.BETA;
|
||||
public final int major;
|
||||
public final int minor;
|
||||
public final int patch;
|
||||
|
|
|
@ -20,7 +20,6 @@ public String getUsageDescription() {
|
|||
public void invoke(String... args) {
|
||||
LogHelper.subInfo("Performing full GC");
|
||||
JVMHelper.fullGC();
|
||||
GarbageManager.gc();
|
||||
// Print memory usage
|
||||
long max = JVMHelper.RUNTIME.maxMemory() >> 20;
|
||||
long free = JVMHelper.RUNTIME.freeMemory() >> 20;
|
||||
|
|
Loading…
Reference in a new issue