Merge branch 'release/5.3.1'

This commit is contained in:
Gravita 2022-10-23 17:05:52 +07:00
commit a5b4282037
16 changed files with 135 additions and 15 deletions

View file

@ -24,7 +24,7 @@
**Основные правила:** **Основные правила:**
1. Все коммиты должны быть на русском языке. 1. Все коммиты должны быть на английском языке.
2. Запрещено использовать прошедшее время. 2. Запрещено использовать прошедшее время.
3. Обязательно должен быть использован префикс. 3. Обязательно должен быть использован префикс.
4. В конце не должно быть лишнего знака препинания. 4. В конце не должно быть лишнего знака препинания.
@ -38,10 +38,10 @@
| Префикс | Значение | Пример | | Префикс | Значение | Пример |
| ------- | -------- | ------ | | ------- | -------- | ------ |
| **[FIX]** | Всё, что касается исправления багов | [FIX] Баг с неудачной авторизацией | | **[FIX]** | Всё, что касается исправления багов | [FIX] Bug with failed authorization |
| **[DOCS]** | Всё, что касается документации | [DOCS] Документирование API авторизации | | **[DOCS]** | Всё, что касается документации | [DOCS] Documenting Authorization API |
| **[FEATURE]** | Всё, что касается новых возможностей | [FEATURE] 2FA при авторизации | | **[FEATURE]** | Всё, что касается новых возможностей | [FEATURE] 2FA on authorization |
| **[STYLE]** | Всё, что касается опечаток и форматирования | [STYLE] Опечатки в модуле авторизации | | **[STYLE]** | Всё, что касается опечаток и форматирования | [STYLE] Typos in the authorization module |
| **[REFACTOR]** | Всё, что касается рефакторинга | [REFACTOR] Переход на EDA в модуле авторизации | | **[REFACTOR]** | Всё, что касается рефакторинга | [REFACTOR] Switching to EDA in the authorization module |
| **[TEST]** | Всё, что касается тестирования | [TEST] Покрытие модуля авторизации тестами | | **[TEST]** | Всё, что касается тестирования | [TEST] Coverage of the authorization module with tests |
| **[ANY]** | Всё, что не подходит к предыдущему. | [ANY] Подключение Travis CI | | **[ANY]** | Всё, что не подходит к предыдущему. | [ANY] Connecting Travis CI |

View file

@ -3,9 +3,12 @@
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
import pro.gravit.launcher.Launcher; import pro.gravit.launcher.Launcher;
import pro.gravit.launcher.events.RequestEvent;
import pro.gravit.launcher.events.request.ProfilesRequestEvent;
import pro.gravit.launcher.managers.ConfigManager; import pro.gravit.launcher.managers.ConfigManager;
import pro.gravit.launcher.modules.events.ClosePhase; import pro.gravit.launcher.modules.events.ClosePhase;
import pro.gravit.launcher.profiles.ClientProfile; import pro.gravit.launcher.profiles.ClientProfile;
import pro.gravit.launcher.request.Request;
import pro.gravit.launchserver.auth.AuthProviderPair; import pro.gravit.launchserver.auth.AuthProviderPair;
import pro.gravit.launchserver.auth.core.RejectAuthCoreProvider; import pro.gravit.launchserver.auth.core.RejectAuthCoreProvider;
import pro.gravit.launchserver.binary.EXEL4JLauncherBinary; import pro.gravit.launchserver.binary.EXEL4JLauncherBinary;
@ -19,7 +22,9 @@
import pro.gravit.launchserver.manangers.hook.AuthHookManager; import pro.gravit.launchserver.manangers.hook.AuthHookManager;
import pro.gravit.launchserver.modules.events.*; import pro.gravit.launchserver.modules.events.*;
import pro.gravit.launchserver.modules.impl.LaunchServerModulesManager; import pro.gravit.launchserver.modules.impl.LaunchServerModulesManager;
import pro.gravit.launchserver.socket.Client;
import pro.gravit.launchserver.socket.handlers.NettyServerSocketHandler; import pro.gravit.launchserver.socket.handlers.NettyServerSocketHandler;
import pro.gravit.launchserver.socket.response.auth.ProfilesResponse;
import pro.gravit.launchserver.socket.response.auth.RestoreResponse; import pro.gravit.launchserver.socket.response.auth.RestoreResponse;
import pro.gravit.utils.command.Command; import pro.gravit.utils.command.Command;
import pro.gravit.utils.command.CommandHandler; import pro.gravit.utils.command.CommandHandler;
@ -374,6 +379,24 @@ public void syncProfilesDir() throws IOException {
// Sort and set new profiles // Sort and set new profiles
newProfies.sort(Comparator.comparing(a -> a)); newProfies.sort(Comparator.comparing(a -> a));
profilesList = Set.copyOf(newProfies); profilesList = Set.copyOf(newProfies);
if(config.netty.sendProfileUpdatesEvent) {
sendUpdateProfilesEvent();
}
}
private void sendUpdateProfilesEvent() {
if(nettyServerSocketHandler == null || nettyServerSocketHandler.nettyServer == null || nettyServerSocketHandler.nettyServer.service == null) {
return;
}
nettyServerSocketHandler.nettyServer.service.forEachActiveChannels((ch, handler) -> {
Client client = handler.getClient();
if(client == null || !client.isAuth) {
return;
}
ProfilesRequestEvent event = new ProfilesRequestEvent(ProfilesResponse.getListVisibleProfiles(this, client));
event.requestUUID = RequestEvent.eventUUID;
handler.service.sendObject(ch, event);
});
} }
public void syncUpdatesDir(Collection<String> dirs) throws IOException { public void syncUpdatesDir(Collection<String> dirs) throws IOException {

View file

@ -13,6 +13,7 @@
import pro.gravit.launchserver.auth.AuthException; import pro.gravit.launchserver.auth.AuthException;
import pro.gravit.launchserver.auth.core.interfaces.UserHardware; import pro.gravit.launchserver.auth.core.interfaces.UserHardware;
import pro.gravit.launchserver.auth.core.interfaces.provider.AuthSupportHardware; import pro.gravit.launchserver.auth.core.interfaces.provider.AuthSupportHardware;
import pro.gravit.launchserver.auth.core.interfaces.provider.AuthSupportRemoteClientAccess;
import pro.gravit.launchserver.auth.core.interfaces.user.UserSupportHardware; import pro.gravit.launchserver.auth.core.interfaces.user.UserSupportHardware;
import pro.gravit.launchserver.auth.core.interfaces.user.UserSupportProperties; import pro.gravit.launchserver.auth.core.interfaces.user.UserSupportProperties;
import pro.gravit.launchserver.auth.core.interfaces.user.UserSupportTextures; import pro.gravit.launchserver.auth.core.interfaces.user.UserSupportTextures;
@ -25,7 +26,7 @@
import java.io.IOException; import java.io.IOException;
import java.util.*; import java.util.*;
public class HttpAuthCoreProvider extends AuthCoreProvider implements AuthSupportHardware { public class HttpAuthCoreProvider extends AuthCoreProvider implements AuthSupportHardware, AuthSupportRemoteClientAccess {
private transient final Logger logger = LogManager.getLogger(); private transient final Logger logger = LogManager.getLogger();
private transient HttpRequester requester; private transient HttpRequester requester;
public String bearerToken; public String bearerToken;
@ -49,6 +50,8 @@ public class HttpAuthCoreProvider extends AuthCoreProvider implements AuthSuppor
public String getUsersByHardwareInfoUrl; public String getUsersByHardwareInfoUrl;
public String banHardwareUrl; public String banHardwareUrl;
public String unbanHardwareUrl; public String unbanHardwareUrl;
public String apiUrl;
public List<String> apiFeatures;
@Override @Override
public User getUserByUsername(String username) { public User getUserByUsername(String username) {
@ -267,6 +270,16 @@ public void unbanHardware(UserHardware hardware) {
} }
} }
@Override
public String getClientApiUrl() {
return apiUrl;
}
@Override
public List<String> getClientApiFeatures() {
return apiFeatures;
}
public record HttpAuthReport(String minecraftAccessToken, String oauthAccessToken, public record HttpAuthReport(String minecraftAccessToken, String oauthAccessToken,
String oauthRefreshToken, long oauthExpire, String oauthRefreshToken, long oauthExpire,
HttpUserSession session) { HttpUserSession session) {

View file

@ -0,0 +1,8 @@
package pro.gravit.launchserver.auth.core.interfaces.provider;
import java.util.List;
public interface AuthSupportRemoteClientAccess {
String getClientApiUrl();
List<String> getClientApiFeatures();
}

View file

@ -0,0 +1,17 @@
package pro.gravit.launchserver.auth.password;
import org.bouncycastle.crypto.generators.OpenBSDBCrypt;
import pro.gravit.utils.helper.SecurityHelper;
public class BCryptPasswordVerifier extends PasswordVerifier {
public int cost = 10;
@Override
public boolean check(String encryptedPassword, String password) {
return OpenBSDBCrypt.checkPassword(encryptedPassword, password.toCharArray());
}
@Override
public String encrypt(String password) {
return OpenBSDBCrypt.generate(password.toCharArray(), SecurityHelper.randomBytes(16), cost);
}
}

View file

@ -12,6 +12,7 @@ public static void registerProviders() {
providers.register("digest", DigestPasswordVerifier.class); providers.register("digest", DigestPasswordVerifier.class);
providers.register("doubleDigest", DoubleDigestPasswordVerifier.class); providers.register("doubleDigest", DoubleDigestPasswordVerifier.class);
providers.register("json", JsonPasswordVerifier.class); providers.register("json", JsonPasswordVerifier.class);
providers.register("bcrypt", BCryptPasswordVerifier.class);
providers.register("accept", AcceptPasswordVerifier.class); providers.register("accept", AcceptPasswordVerifier.class);
providers.register("reject", RejectPasswordVerifier.class); providers.register("reject", RejectPasswordVerifier.class);
registeredProviders = true; registeredProviders = true;

View file

@ -281,6 +281,7 @@ public static class NettyConfig {
public boolean ipForwarding; public boolean ipForwarding;
public boolean disableWebApiInterface; public boolean disableWebApiInterface;
public boolean showHiddenFiles; public boolean showHiddenFiles;
public boolean sendProfileUpdatesEvent = true;
public String launcherURL; public String launcherURL;
public String downloadURL; public String downloadURL;
public String launcherEXEURL; public String launcherEXEURL;

View file

@ -3,6 +3,7 @@
import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelHandlerContext;
import pro.gravit.launcher.events.request.GetAvailabilityAuthRequestEvent; import pro.gravit.launcher.events.request.GetAvailabilityAuthRequestEvent;
import pro.gravit.launchserver.auth.AuthProviderPair; import pro.gravit.launchserver.auth.AuthProviderPair;
import pro.gravit.launchserver.auth.core.interfaces.provider.AuthSupportRemoteClientAccess;
import pro.gravit.launchserver.socket.Client; import pro.gravit.launchserver.socket.Client;
import pro.gravit.launchserver.socket.response.SimpleResponse; import pro.gravit.launchserver.socket.response.SimpleResponse;
@ -19,8 +20,14 @@ public String getType() {
public void execute(ChannelHandlerContext ctx, Client client) { public void execute(ChannelHandlerContext ctx, Client client) {
List<GetAvailabilityAuthRequestEvent.AuthAvailability> list = new ArrayList<>(); List<GetAvailabilityAuthRequestEvent.AuthAvailability> list = new ArrayList<>();
for (AuthProviderPair pair : server.config.auth.values()) { for (AuthProviderPair pair : server.config.auth.values()) {
list.add(new GetAvailabilityAuthRequestEvent.AuthAvailability(pair.name, pair.displayName, var rca = pair.isSupport(AuthSupportRemoteClientAccess.class);
pair.core.getDetails(client))); if(rca != null) {
list.add(new GetAvailabilityAuthRequestEvent.AuthAvailability(pair.name, pair.displayName,
pair.core.getDetails(client), rca.getClientApiUrl(), rca.getClientApiFeatures()));
} else {
list.add(new GetAvailabilityAuthRequestEvent.AuthAvailability(pair.name, pair.displayName,
pair.core.getDetails(client)));
}
} }
sendResult(new GetAvailabilityAuthRequestEvent(list)); sendResult(new GetAvailabilityAuthRequestEvent(list));
} }

View file

@ -3,6 +3,7 @@
import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelHandlerContext;
import pro.gravit.launcher.events.request.ProfilesRequestEvent; import pro.gravit.launcher.events.request.ProfilesRequestEvent;
import pro.gravit.launcher.profiles.ClientProfile; import pro.gravit.launcher.profiles.ClientProfile;
import pro.gravit.launchserver.LaunchServer;
import pro.gravit.launchserver.auth.protect.interfaces.ProfilesProtectHandler; import pro.gravit.launchserver.auth.protect.interfaces.ProfilesProtectHandler;
import pro.gravit.launchserver.socket.Client; import pro.gravit.launchserver.socket.Client;
import pro.gravit.launchserver.socket.response.SimpleResponse; import pro.gravit.launchserver.socket.response.SimpleResponse;
@ -23,7 +24,10 @@ public void execute(ChannelHandlerContext ctx, Client client) {
sendError("Access denied"); sendError("Access denied");
return; return;
} }
sendResult(new ProfilesRequestEvent(getListVisibleProfiles(server, client)));
}
public static List<ClientProfile> getListVisibleProfiles(LaunchServer server, Client client) {
List<ClientProfile> profileList; List<ClientProfile> profileList;
Set<ClientProfile> serverProfiles = server.getProfiles(); Set<ClientProfile> serverProfiles = server.getProfiles();
if (server.config.protectHandler instanceof ProfilesProtectHandler protectHandler) { if (server.config.protectHandler instanceof ProfilesProtectHandler protectHandler) {
@ -36,6 +40,6 @@ public void execute(ChannelHandlerContext ctx, Client client) {
} else { } else {
profileList = List.copyOf(serverProfiles); profileList = List.copyOf(serverProfiles);
} }
sendResult(new ProfilesRequestEvent(profileList)); return profileList;
} }
} }

View file

@ -45,11 +45,23 @@ public static class AuthAvailability {
public String name; public String name;
@LauncherNetworkAPI @LauncherNetworkAPI
public String displayName; public String displayName;
@LauncherNetworkAPI
public String apiUrl;
@LauncherNetworkAPI
public List<String> apiFeatures;
public AuthAvailability(String name, String displayName, List<AuthAvailabilityDetails> details) { public AuthAvailability(String name, String displayName, List<AuthAvailabilityDetails> details) {
this.name = name; this.name = name;
this.displayName = displayName; this.displayName = displayName;
this.details = details; this.details = details;
} }
public AuthAvailability(String name, String displayName, List<AuthAvailabilityDetails> details, String apiUrl, List<String> apiFeatures) {
this.details = details;
this.name = name;
this.displayName = displayName;
this.apiUrl = apiUrl;
this.apiFeatures = apiFeatures;
}
} }
} }

View file

@ -69,6 +69,10 @@ public long size() {
return size; return size;
} }
public byte[] getDigest() {
return digest;
}
@Override @Override
public void write(HOutput output) throws IOException { public void write(HOutput output) throws IOException {
output.writeVarLong(size); output.writeVarLong(size);

View file

@ -6,7 +6,7 @@ public final class Version implements Comparable<Version> {
public static final int MAJOR = 5; public static final int MAJOR = 5;
public static final int MINOR = 3; public static final int MINOR = 3;
public static final int PATCH = 0; public static final int PATCH = 1;
public static final int BUILD = 1; public static final int BUILD = 1;
public static final Version.Type RELEASE = Type.STABLE; public static final Version.Type RELEASE = Type.STABLE;
public final int major; public final int major;

View file

@ -20,6 +20,7 @@ public class InstallAuthlib {
modifierMap.put("META-INF/libraries.list", new LibrariesLstModifier()); modifierMap.put("META-INF/libraries.list", new LibrariesLstModifier());
modifierMap.put("patch.properties", new PatchPropertiesModifier()); modifierMap.put("patch.properties", new PatchPropertiesModifier());
modifierMap.put("META-INF/download-context", new DownloadContextModifier()); modifierMap.put("META-INF/download-context", new DownloadContextModifier());
modifierMap.put("META-INF/patches.list", new PatchesLstModifier());
} }
public void run(String... args) throws Exception { public void run(String... args) throws Exception {
boolean deleteAuthlibAfterInstall = false; boolean deleteAuthlibAfterInstall = false;

View file

@ -0,0 +1,29 @@
package pro.gravit.launcher.server.authlib;
import pro.gravit.utils.helper.LogHelper;
import pro.gravit.utils.helper.SecurityHelper;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
public class PatchesLstModifier implements LibrariesHashFileModifier {
@Override
public byte[] apply(byte[] data, InstallAuthlib.InstallAuthlibContext context) throws IOException {
String[] lines = new String(data).split("\n");
for(int i=0;i<lines.length;++i) {
if(lines[i].contains("paper-")) {
String[] separated = lines[i].split("\t");
Path path = context.workdir.resolve("versions").resolve(separated[6]);
if(Files.notExists(path)) {
LogHelper.warning("Unable to find %s. Maybe you should start the server at least once?", path);
return data;
}
separated[3] = SecurityHelper.toHex(SecurityHelper.digest(SecurityHelper.DigestAlgorithm.SHA256, path));
lines[i] = String.join("\t", separated);
}
}
return String.join("\n", lines).getBytes(StandardCharsets.UTF_8);
}
}

View file

@ -5,7 +5,7 @@
id 'org.openjfx.javafxplugin' version '0.0.10' apply false id 'org.openjfx.javafxplugin' version '0.0.10' apply false
} }
group = 'pro.gravit.launcher' group = 'pro.gravit.launcher'
version = '5.3.0' version = '5.3.1'
apply from: 'props.gradle' apply from: 'props.gradle'

@ -1 +1 @@
Subproject commit eb3145d3e75ff3557fe9f9fc87dd5ea0737ff3a2 Subproject commit 8677bc30c7e6c5f168131dbee63a1c10f2ea0394