Compare commits

..

No commits in common. "2ed4abf9b0c8ed9a1911350cf87a083af3c0c149" and "4be299f6ca8e47750ba522dc9d79f89c0fe08e94" have entirely different histories.

13 changed files with 108 additions and 236 deletions

View file

@ -80,6 +80,7 @@ public final class LaunchServer implements Runnable, AutoCloseable, Reconfigurab
/**
* The path to the folder with profiles
*/
public final Path profilesDir;
public final Path tmpDir;
public final Path modulesDir;
public final Path launcherModulesDir;
@ -118,6 +119,8 @@ public final class LaunchServer implements Runnable, AutoCloseable, Reconfigurab
private final Logger logger = LogManager.getLogger();
public final int shardId;
public LaunchServerConfig config;
// Updates and profiles
private volatile Set<ClientProfile> profilesList;
public LaunchServer(LaunchServerDirectories directories, LaunchServerEnv env, LaunchServerConfig config, LaunchServerRuntimeConfig runtimeConfig, LaunchServerConfigManager launchServerConfigManager, LaunchServerModulesManager modulesManager, KeyAgreementManager keyAgreementManager, CommandHandler commandHandler, CertificateManager certificateManager, int shardId) throws IOException {
this.dir = directories.dir;
@ -126,6 +129,7 @@ public LaunchServer(LaunchServerDirectories directories, LaunchServerEnv env, La
this.config = config;
this.launchServerConfigManager = launchServerConfigManager;
this.modulesManager = modulesManager;
this.profilesDir = directories.profilesDir;
this.updatesDir = directories.updatesDir;
this.keyAgreementManager = keyAgreementManager;
this.commandHandler = commandHandler;
@ -322,14 +326,12 @@ public void close() throws Exception {
logger.info("LaunchServer stopped");
}
@Deprecated
public Set<ClientProfile> getProfiles() {
return config.profileProvider.getProfiles();
return profilesList;
}
@Deprecated
public void setProfiles(Set<ClientProfile> profilesList) {
throw new UnsupportedOperationException();
this.profilesList = Collections.unmodifiableSet(profilesList);
}
public void rebindNettyServerSocket() {
@ -356,6 +358,8 @@ public void run() {
CommonHelper.newThread("Profiles and updates sync", true, () -> {
try {
// Sync profiles dir
if (!IOHelper.isDir(profilesDir))
Files.createDirectory(profilesDir);
syncProfilesDir();
// Sync updates dir
@ -398,7 +402,12 @@ public void syncLauncherBinaries() throws IOException {
public void syncProfilesDir() throws IOException {
logger.info("Syncing profiles dir");
config.profileProvider.sync();
List<ClientProfile> newProfies = new LinkedList<>();
IOHelper.walk(profilesDir, new ProfilesFileVisitor(newProfies), false);
// Sort and set new profiles
newProfies.sort(Comparator.comparing(a -> a));
profilesList = Set.copyOf(newProfies);
if (config.netty.sendProfileUpdatesEvent) {
sendUpdateProfilesEvent();
}
@ -413,7 +422,7 @@ private void sendUpdateProfilesEvent() {
if (client == null || !client.isAuth) {
return;
}
ProfilesRequestEvent event = new ProfilesRequestEvent(config.profileProvider.getProfiles(client));
ProfilesRequestEvent event = new ProfilesRequestEvent(ProfilesResponse.getListVisibleProfiles(this, client));
event.requestUUID = RequestEvent.eventUUID;
handler.service.sendObject(ch, event);
});
@ -459,11 +468,38 @@ public interface LaunchServerConfigManager {
void writeRuntimeConfig(LaunchServerRuntimeConfig config) throws IOException;
}
private static final class ProfilesFileVisitor extends SimpleFileVisitor<Path> {
private final Collection<ClientProfile> result;
private final Logger logger = LogManager.getLogger();
private ProfilesFileVisitor(Collection<ClientProfile> result) {
this.result = result;
}
@Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
logger.info("Syncing '{}' profile", IOHelper.getFileName(file));
// Read profile
ClientProfile profile;
try (BufferedReader reader = IOHelper.newReader(file)) {
profile = Launcher.gsonManager.gson.fromJson(reader, ClientProfile.class);
}
profile.verify();
profile.setProfileFilePath(file);
// Add SIGNED profile to result list
result.add(profile);
return super.visitFile(file, attrs);
}
}
public static class LaunchServerDirectories {
public static final String UPDATES_NAME = "updates",
public static final String UPDATES_NAME = "updates", PROFILES_NAME = "profiles",
TRUSTSTORE_NAME = "truststore", LAUNCHERLIBRARIES_NAME = "launcher-libraries",
LAUNCHERLIBRARIESCOMPILE_NAME = "launcher-libraries-compile", LAUNCHERPACK_NAME = "launcher-pack", KEY_NAME = ".keys", MODULES = "modules", LAUNCHER_MODULES = "launcher-modules", LIBRARIES = "libraries";
public Path updatesDir;
public Path profilesDir;
public Path librariesDir;
public Path launcherLibrariesDir;
public Path launcherLibrariesCompileDir;
@ -477,6 +513,7 @@ public static class LaunchServerDirectories {
public void collect() {
if (updatesDir == null) updatesDir = getPath(UPDATES_NAME);
if (profilesDir == null) profilesDir = getPath(PROFILES_NAME);
if (trustStore == null) trustStore = getPath(TRUSTSTORE_NAME);
if (launcherLibrariesDir == null) launcherLibrariesDir = getPath(LAUNCHERLIBRARIES_NAME);
if (launcherLibrariesCompileDir == null)

View file

@ -13,7 +13,6 @@
import pro.gravit.launchserver.auth.core.AuthCoreProvider;
import pro.gravit.launchserver.auth.mix.MixProvider;
import pro.gravit.launchserver.auth.password.PasswordVerifier;
import pro.gravit.launchserver.auth.profiles.ProfileProvider;
import pro.gravit.launchserver.auth.protect.ProtectHandler;
import pro.gravit.launchserver.auth.texture.TextureProvider;
import pro.gravit.launchserver.components.Component;
@ -179,7 +178,6 @@ public static void registerAll() {
OptionalAction.registerProviders();
OptionalTrigger.registerProviders();
MixProvider.registerProviders();
ProfileProvider.registerProviders();
}
private static void printExperimentalBranch() {

View file

@ -1,109 +0,0 @@
package pro.gravit.launchserver.auth.profiles;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import pro.gravit.launcher.base.Launcher;
import pro.gravit.launcher.base.profiles.ClientProfile;
import pro.gravit.utils.helper.IOHelper;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.nio.file.*;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.*;
public class LocalProfileProvider extends ProfileProvider {
public String profilesDir = "profiles";
private transient volatile Map<Path, ClientProfile> profilesMap;
private transient volatile Set<ClientProfile> profilesList; // Cache
@Override
public void sync() throws IOException {
Path profilesDirPath = Path.of(profilesDir);
if (!IOHelper.isDir(profilesDirPath))
Files.createDirectory(profilesDirPath);
Map<Path, ClientProfile> newProfiles = new HashMap<>();
IOHelper.walk(profilesDirPath, new ProfilesFileVisitor(newProfiles), false);
Set<ClientProfile> newProfilesList = new HashSet<>(newProfiles.values());
profilesMap = newProfiles;
profilesList = newProfilesList;
}
@Override
public Set<ClientProfile> getProfiles() {
return profilesList;
}
@Override
public void addProfile(ClientProfile profile) throws IOException {
Path profilesDirPath = Path.of(profilesDir);
ClientProfile oldProfile;
Path target = null;
for(var e : profilesMap.entrySet()) {
if(e.getValue().getUUID().equals(profile.getUUID())) {
target = e.getKey();
}
}
if(target == null) {
target = IOHelper.resolveIncremental(profilesDirPath,
profile.getTitle(), "json");
oldProfile = profilesMap.get(target);
if(oldProfile != null && !oldProfile.getUUID().equals(profile.getUUID())) {
throw new FileAlreadyExistsException(target.toString());
}
}
try (BufferedWriter writer = IOHelper.newWriter(target)) {
Launcher.gsonManager.configGson.toJson(profile, writer);
}
addProfile(target, profile);
}
@Override
public void deleteProfile(ClientProfile profile) throws IOException {
for(var e : profilesMap.entrySet()) {
if(e.getValue().getUUID().equals(profile.getUUID())) {
Files.deleteIfExists(e.getKey());
profilesMap.remove(e.getKey());
profilesList.remove(e.getValue());
break;
}
}
}
private void addProfile(Path path, ClientProfile profile) {
for(var e : profilesMap.entrySet()) {
if(e.getValue().getUUID().equals(profile.getUUID())) {
profilesMap.remove(e.getKey());
profilesList.remove(e.getValue());
break;
}
}
profilesMap.put(path, profile);
profilesList.add(profile);
}
private static final class ProfilesFileVisitor extends SimpleFileVisitor<Path> {
private final Map<Path, ClientProfile> result;
private final Logger logger = LogManager.getLogger();
private ProfilesFileVisitor(Map<Path, ClientProfile> result) {
this.result = result;
}
@Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
logger.info("Syncing '{}' profile", IOHelper.getFileName(file));
// Read profile
ClientProfile profile;
try (BufferedReader reader = IOHelper.newReader(file)) {
profile = Launcher.gsonManager.gson.fromJson(reader, ClientProfile.class);
}
profile.verify();
// Add SIGNED profile to result list
result.put(file.toAbsolutePath(), profile);
return super.visitFile(file, attrs);
}
}
}

View file

@ -1,76 +0,0 @@
package pro.gravit.launchserver.auth.profiles;
import pro.gravit.launcher.base.profiles.ClientProfile;
import pro.gravit.launchserver.LaunchServer;
import pro.gravit.launchserver.auth.protect.interfaces.ProfilesProtectHandler;
import pro.gravit.launchserver.socket.Client;
import pro.gravit.utils.ProviderMap;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.UUID;
public abstract class ProfileProvider {
public static final ProviderMap<ProfileProvider> providers = new ProviderMap<>("ProfileProvider");
private static boolean registredProviders = false;
protected transient LaunchServer server;
public static void registerProviders() {
if (!registredProviders) {
providers.register("local", LocalProfileProvider.class);
registredProviders = true;
}
}
public void init(LaunchServer server) {
this.server = server;
}
public abstract void sync() throws IOException;
public abstract Set<ClientProfile> getProfiles();
public abstract void addProfile(ClientProfile profile) throws IOException;
public abstract void deleteProfile(ClientProfile profile) throws IOException;
public void close() {
}
public ClientProfile getProfile(UUID uuid) {
for(var e : getProfiles()) {
if(e.getUUID().equals(uuid)) {
return e;
}
}
return null;
}
public ClientProfile getProfile(String title) {
for(var e : getProfiles()) {
if(e.getTitle().equals(title)) {
return e;
}
}
return null;
}
public List<ClientProfile> getProfiles(Client client) {
List<ClientProfile> profileList;
Set<ClientProfile> serverProfiles = getProfiles();
if (server.config.protectHandler instanceof ProfilesProtectHandler protectHandler) {
profileList = new ArrayList<>(4);
for (ClientProfile profile : serverProfiles) {
if (protectHandler.canGetProfile(profile, client)) {
profileList.add(profile);
}
}
} else {
profileList = List.copyOf(serverProfiles);
}
return profileList;
}
}

View file

@ -97,7 +97,10 @@ public void invoke(String... args) throws IOException, CommandException {
isMirrorClientDownload = true;
}
}
server.config.profileProvider.addProfile(clientProfile);
try (BufferedWriter writer = IOHelper.newWriter(IOHelper.resolveIncremental(server.profilesDir,
dirName, "json"))) {
Launcher.gsonManager.configGson.toJson(clientProfile, writer);
}
// Finished
server.syncProfilesDir();

View file

@ -7,7 +7,6 @@
import pro.gravit.launcher.base.profiles.ClientProfileBuilder;
import pro.gravit.launchserver.LaunchServer;
import pro.gravit.launchserver.command.Command;
import pro.gravit.utils.helper.CommonHelper;
import pro.gravit.utils.helper.IOHelper;
import java.io.IOException;
@ -27,7 +26,7 @@ public CloneProfileCommand(LaunchServer server) {
@Override
public String getArgsDescription() {
return "[profile title/uuid] [new profile title]";
return "[profile file name] [new profile title]";
}
@Override
@ -38,12 +37,13 @@ public String getUsageDescription() {
@Override
public void invoke(String... args) throws Exception {
verifyArgs(args, 2);
var profilePath = server.profilesDir.resolve(args[0].concat(".json"));
if(!Files.exists(profilePath)) {
logger.error("File {} not found", profilePath);
}
ClientProfile profile;
try {
UUID uuid = UUID.fromString(args[0]);
profile = server.config.profileProvider.getProfile(uuid);
} catch (IllegalArgumentException ex) {
profile = server.config.profileProvider.getProfile(args[0]);
try(Reader reader = IOHelper.newReader(profilePath)) {
profile = Launcher.gsonManager.gson.fromJson(reader, ClientProfile.class);
}
var builder = new ClientProfileBuilder(profile);
builder.setTitle(args[1]);
@ -65,7 +65,10 @@ public void invoke(String... args) throws Exception {
}
builder.setDir(args[1]);
profile = builder.createClientProfile();
server.config.profileProvider.addProfile(profile);
var targetPath = server.profilesDir.resolve(args[1].concat(".json"));
try(Writer writer = IOHelper.newWriter(targetPath)) {
Launcher.gsonManager.gson.toJson(profile, writer);
}
logger.info("Profile {} cloned from {}", args[1], args[0]);
server.syncProfilesDir();
server.syncUpdatesDir(List.of(args[1]));

View file

@ -8,7 +8,6 @@
import pro.gravit.utils.helper.IOHelper;
import java.nio.file.Files;
import java.util.UUID;
public class DeleteProfileCommand extends Command {
private final transient Logger logger = LogManager.getLogger(ListProfilesCommand.class);
@ -29,12 +28,12 @@ public String getUsageDescription() {
@Override
public void invoke(String... args) throws Exception {
verifyArgs(args, 1);
ClientProfile profile;
try {
UUID uuid = UUID.fromString(args[0]);
profile = server.config.profileProvider.getProfile(uuid);
} catch (IllegalArgumentException ex) {
profile = server.config.profileProvider.getProfile(args[0]);
ClientProfile profile = null;
for(var p : server.getProfiles()) {
if(p.getUUID().toString().equals(args[0]) || p.getTitle().equals(args[0])) {
profile = p;
break;
}
}
if(profile == null) {
logger.error("Profile {} not found", args[0]);
@ -45,9 +44,13 @@ public void invoke(String... args) throws Exception {
if(!showApplyDialog("Continue?")) {
return;
}
logger.info("Delete {} ({})", profile.getTitle(), profile.getUUID());
server.config.profileProvider.deleteProfile(profile);
logger.info("Delete {}", clientDir);
IOHelper.deleteDir(clientDir, true);
var profileFile = profile.getProfileFilePath();
if(profileFile == null) {
profileFile = server.profilesDir.resolve(profile.getTitle().concat(".json"));
}
logger.info("Delete {}", profileFile);
Files.deleteIfExists(profileFile);
}
}

View file

@ -37,7 +37,9 @@ public void invoke(String... args) throws Exception {
logger.info("Detected option {}", option);
}
ClientProfile profile = MakeProfileHelper.makeProfile(version, args[0], options);
server.config.profileProvider.addProfile(profile);
try (Writer writer = IOHelper.newWriter(server.profilesDir.resolve(args[0].concat(".json")))) {
Launcher.gsonManager.configGson.toJson(profile, writer);
}
logger.info("Profile {} created", args[0]);
server.syncProfilesDir();
}

View file

@ -22,6 +22,20 @@ public SaveProfilesCommand(LaunchServer server) {
super(server);
}
public static void saveProfile(ClientProfile profile, Path path) throws IOException {
if (profile.getServers().isEmpty()) {
ClientProfile.ServerProfile serverProfile = new ClientProfile.ServerProfile();
serverProfile.isDefault = true;
serverProfile.name = profile.getTitle();
serverProfile.serverAddress = profile.getServerAddress();
serverProfile.serverPort = profile.getServerPort();
profile.getServers().add(serverProfile);
}
try (Writer w = IOHelper.newWriter(path)) {
Launcher.gsonManager.configGson.toJson(profile, w);
}
}
@Override
public String getArgsDescription() {
return "[profile names...]";
@ -37,14 +51,17 @@ public void invoke(String... args) throws Exception {
verifyArgs(args, 1);
if (args.length > 0) {
for (String profileName : args) {
ClientProfile profile;
try {
UUID uuid = UUID.fromString(profileName);
profile = server.config.profileProvider.getProfile(uuid);
} catch (IllegalArgumentException ex) {
profile = server.config.profileProvider.getProfile(profileName);
Path profilePath = server.profilesDir.resolve(profileName.concat(".json"));
if (!Files.exists(profilePath)) {
logger.error("Profile {} not found", profilePath.toString());
return;
}
server.config.profileProvider.addProfile(profile);
ClientProfile profile;
try (Reader reader = IOHelper.newReader(profilePath)) {
profile = Launcher.gsonManager.configGson.fromJson(reader, ClientProfile.class);
}
saveProfile(profile, profilePath);
logger.info("Profile {} save successful", profilePath.toString());
}
server.syncProfilesDir();
}

View file

@ -9,8 +9,6 @@
import pro.gravit.launchserver.LaunchServer;
import pro.gravit.launchserver.auth.AuthProviderPair;
import pro.gravit.launchserver.auth.core.RejectAuthCoreProvider;
import pro.gravit.launchserver.auth.profiles.LocalProfileProvider;
import pro.gravit.launchserver.auth.profiles.ProfileProvider;
import pro.gravit.launchserver.auth.protect.ProtectHandler;
import pro.gravit.launchserver.auth.protect.StdProtectHandler;
import pro.gravit.launchserver.auth.texture.RequestTextureProvider;
@ -38,7 +36,6 @@ public final class LaunchServerConfig {
// Handlers & Providers
public ProtectHandler protectHandler;
public Map<String, Component> components;
public ProfileProvider profileProvider = new LocalProfileProvider();
public NettyConfig netty;
public LauncherConf launcher;
public JarSignerConf sign;
@ -88,7 +85,6 @@ public static LaunchServerConfig getDefault(LaunchServer.LaunchServerEnv env) {
newConfig.components.put("authLimiter", authLimiterComponent);
ProGuardComponent proGuardComponent = new ProGuardComponent();
newConfig.components.put("proguard", proGuardComponent);
newConfig.profileProvider = new LocalProfileProvider();
return newConfig;
}
@ -170,10 +166,6 @@ public void init(LaunchServer.ReloadType type) {
server.registerObject("protectHandler", protectHandler);
protectHandler.init(server);
}
if(profileProvider != null) {
server.registerObject("profileProvider", profileProvider);
profileProvider.init(server);
}
if (components != null) {
components.forEach((k, v) -> server.registerObject("component.".concat(k), v));
}
@ -214,10 +206,6 @@ public void close(LaunchServer.ReloadType type) {
server.unregisterObject("protectHandler", protectHandler);
protectHandler.close();
}
if(profileProvider != null) {
server.unregisterObject("profileProvider", profileProvider);
profileProvider.close();
}
}
public static class JarSignerConf {

View file

@ -14,7 +14,6 @@
import pro.gravit.launchserver.auth.core.AuthCoreProvider;
import pro.gravit.launchserver.auth.mix.MixProvider;
import pro.gravit.launchserver.auth.password.PasswordVerifier;
import pro.gravit.launchserver.auth.profiles.ProfileProvider;
import pro.gravit.launchserver.auth.protect.ProtectHandler;
import pro.gravit.launchserver.auth.texture.TextureProvider;
import pro.gravit.launchserver.components.Component;
@ -47,7 +46,6 @@ public void registerAdapters(GsonBuilder builder) {
builder.registerTypeAdapter(OptionalAction.class, new UniversalJsonAdapter<>(OptionalAction.providers));
builder.registerTypeAdapter(OptionalTrigger.class, new UniversalJsonAdapter<>(OptionalTrigger.providers));
builder.registerTypeAdapter(MixProvider.class, new UniversalJsonAdapter<>(MixProvider.providers));
builder.registerTypeAdapter(ProfileProvider.class, new UniversalJsonAdapter<>(ProfileProvider.providers));
modulesManager.invokeEvent(new PreGsonPhase(builder));
//ClientWebSocketService.appendTypeAdapters(builder);
}

View file

@ -13,7 +13,6 @@
import java.util.Set;
public class ProfilesResponse extends SimpleResponse {
@Deprecated
public static List<ClientProfile> getListVisibleProfiles(LaunchServer server, Client client) {
List<ClientProfile> profileList;
Set<ClientProfile> serverProfiles = server.getProfiles();
@ -41,6 +40,6 @@ public void execute(ChannelHandlerContext ctx, Client client) {
sendError("Access denied");
return;
}
sendResult(new ProfilesRequestEvent(server.config.profileProvider.getProfiles(client)));
sendResult(new ProfilesRequestEvent(getListVisibleProfiles(server, client)));
}
}

View file

@ -18,6 +18,7 @@
public final class ClientProfile implements Comparable<ClientProfile> {
private static final FileNameMatcher ASSET_MATCHER = new FileNameMatcher(
new String[0], new String[]{"indexes", "objects"}, new String[0]);
private transient Path profileFilePath;
@LauncherNetworkAPI
private String title;
@LauncherNetworkAPI
@ -391,6 +392,14 @@ public List<CompatibilityFlags> getFlags() {
return flags;
}
public Path getProfileFilePath() {
return profileFilePath;
}
public void setProfileFilePath(Path profileFilePath) {
this.profileFilePath = profileFilePath;
}
public enum ClassLoaderConfig {
AGENT, LAUNCHER, MODULE, SYSTEM_ARGS
}