mirror of
https://github.com/TuxCoding/FastLogin.git
synced 2025-12-24 15:48:07 +01:00
Compare commits
3 Commits
1.11
...
tcpshield_
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6fd1e5e79c | ||
|
|
213bacfab9 | ||
|
|
232e9ac137 |
7
.github/ISSUE_TEMPLATE/bug_report.yaml
vendored
7
.github/ISSUE_TEMPLATE/bug_report.yaml
vendored
@@ -48,19 +48,18 @@ body:
|
||||
- type: dropdown
|
||||
attributes:
|
||||
label: Platform
|
||||
description: Server software - choose your proxy software if you have multiple servers
|
||||
description:
|
||||
options:
|
||||
- Spigot
|
||||
- BungeeCord
|
||||
- Velocity
|
||||
validations:
|
||||
required: true
|
||||
- type: checkboxes
|
||||
attributes:
|
||||
label: Relevance
|
||||
description: Check list for previous tickets
|
||||
description:
|
||||
options:
|
||||
- label: I tried the latest build (build refers to development builds not necessary a release version)
|
||||
- label: I tried the latest build
|
||||
required: true
|
||||
- label: |
|
||||
I checked for existing tickets -
|
||||
|
||||
3
.github/ISSUE_TEMPLATE/config.yml
vendored
3
.github/ISSUE_TEMPLATE/config.yml
vendored
@@ -7,6 +7,5 @@
|
||||
contact_links:
|
||||
- name: 📌 Questions
|
||||
url: https://github.com/games647/FastLogin/discussions
|
||||
about:
|
||||
You want to ask something - general questions. Example includes how to set it up or how it is working internally
|
||||
about: You want to ask something
|
||||
|
||||
|
||||
23
.github/workflows/codeql-analysis.yml
vendored
23
.github/workflows/codeql-analysis.yml
vendored
@@ -1,6 +1,6 @@
|
||||
# GitHub automatic code security scanning using CodeQL
|
||||
|
||||
# Human-readable name in the actions tab
|
||||
# Human readable name in the actions tab
|
||||
name: "CodeQL"
|
||||
|
||||
on:
|
||||
@@ -33,35 +33,26 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v3
|
||||
|
||||
# Setup Java
|
||||
- name: Set up JDK
|
||||
uses: actions/setup-java@v3
|
||||
with:
|
||||
distribution: 'adopt'
|
||||
# Use Java 16, because it's minimum required version by Geyser
|
||||
java-version: 16
|
||||
cache: 'maven'
|
||||
uses: actions/checkout@v2
|
||||
|
||||
# Initializes the CodeQL tools for scanning.
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@v2
|
||||
uses: github/codeql-action/init@v1
|
||||
with:
|
||||
languages: ${{ matrix.language }}
|
||||
|
||||
# Cache build process too like in the maven config
|
||||
- uses: actions/cache@v3.0.1
|
||||
- uses: actions/cache@v2.1.4
|
||||
with:
|
||||
path: ~/.m2/repository
|
||||
key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-maven-
|
||||
|
||||
# Auto build attempts to build any compiled languages (C/C++, C#, or Java).
|
||||
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
|
||||
# If this step fails, then you should remove it and run the build manually (see below)
|
||||
- name: Autobuild
|
||||
uses: github/codeql-action/autobuild@v2
|
||||
uses: github/codeql-action/autobuild@v1
|
||||
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@v2
|
||||
uses: github/codeql-action/analyze@v1
|
||||
|
||||
27
.github/workflows/maven.yml
vendored
27
.github/workflows/maven.yml
vendored
@@ -1,7 +1,7 @@
|
||||
# Automatically build, run unit and integration tests to detect errors early (CI provided by GitHub)
|
||||
# including making pull requests review easier
|
||||
|
||||
# Human-readable name in the actions tab
|
||||
# Human readable name in the actions tab
|
||||
name: Java CI
|
||||
|
||||
# Build on every pull request regardless of the branch
|
||||
@@ -18,22 +18,33 @@ jobs:
|
||||
# job id
|
||||
build_and_test:
|
||||
|
||||
# Environment image - always use the newest OS
|
||||
# Environment image - always newest OS
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
# Run steps
|
||||
steps:
|
||||
# Pull changes
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v2.3.4
|
||||
|
||||
# Cache artifacts - however this has the downside that we don't get notified of
|
||||
# artifact resolution failures like invalid repository
|
||||
# Nevertheless the repositories should be more stable and it makes no sense to pull
|
||||
# a same version every time
|
||||
# A dry run would make more sense
|
||||
- uses: actions/cache@v2.1.4
|
||||
with:
|
||||
path: ~/.m2/repository
|
||||
key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-maven-
|
||||
|
||||
# Setup Java
|
||||
- name: Set up JDK
|
||||
uses: actions/setup-java@v3
|
||||
uses: actions/setup-java@v2.1.0
|
||||
with:
|
||||
distribution: 'temurin'
|
||||
# Use Java 16, because it's minimum required version by Geyser
|
||||
java-version: 16
|
||||
cache: 'maven'
|
||||
distribution: 'adopt'
|
||||
# Use Java 11, because it's minimum required version
|
||||
java-version: 11
|
||||
|
||||
# Build and test (included in package)
|
||||
- name: Build with Maven and test
|
||||
|
||||
2
LICENSE
2
LICENSE
@@ -1,6 +1,6 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2015-2022 games647 and contributors
|
||||
Copyright (c) 2015-2021 games647 and contributors
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
|
||||
63
README.md
63
README.md
@@ -12,7 +12,7 @@ So they don't need to enter passwords. This is also called auto login (auto-logi
|
||||
* Forge/Sponge message support
|
||||
* Premium UUID support
|
||||
* Forward skins
|
||||
* Detect username changed and will update the existing database record
|
||||
* Detect user name changed and will update the existing database record
|
||||
* BungeeCord support
|
||||
* Auto register new premium players
|
||||
* Plugin: ProtocolSupport is supported and can be used as an alternative to ProtocolLib
|
||||
@@ -23,14 +23,14 @@ So they don't need to enter passwords. This is also called auto login (auto-logi
|
||||
|
||||
## Issues
|
||||
|
||||
Please use issues for bug reports, suggestions, questions and more. Please check for existing issues. Existing issues
|
||||
Please use issues for bug reports, suggestions, questions and more. Please check for existing issues. Existing issues
|
||||
can be voted up by adding up vote to the original post. Closing issues means that they are marked as resolved. Comments
|
||||
are still allowed and it could be re-opened.
|
||||
|
||||
## Development builds
|
||||
|
||||
Development builds contain the latest changes from the Source-Code. They are bleeding edge and could introduce new bugs,
|
||||
but also include features, enhancements and bug fixes that are not yet in a released version. If you click on the left
|
||||
but also include features, enhancements and bug fixes that are not yet in a released version. If you click on the left
|
||||
side on `Changes`, you can see iterative change sets leading to a specific build.
|
||||
|
||||
You can download them from here: https://ci.codemc.org/job/Games647/job/FastLogin/
|
||||
@@ -51,22 +51,21 @@ You can download them from here: https://ci.codemc.org/job/Games647/job/FastLogi
|
||||
|
||||
## Placeholder
|
||||
|
||||
This plugin supports `PlaceholderAPI` on `Spigot`. It exports the following variable
|
||||
`%fastlogin_status%`. In BungeeCord environments, the status of a player will be delivered with a delay after the player
|
||||
This plugin supports `PlaceholderAPI` on `Spigot`. It exports the following variable
|
||||
`%fastlogin_status%`. In BungeeCord environments, the status of a player will be delivered with a delay after the player
|
||||
already successful joined the server. This takes about a couple of milliseconds. In this case the value
|
||||
will be `Unknown`.
|
||||
will be `Unknown`.
|
||||
|
||||
Possible values: `Premium`, `Cracked`, `Unknown`
|
||||
Possible values: `Premium`, `Cracked`, `Unknown`
|
||||
|
||||
## Requirements
|
||||
|
||||
* Plugin:
|
||||
* [ProtocolLib](https://www.spigotmc.org/resources/protocollib.1997/) or
|
||||
* [ProtocolSupport](https://www.spigotmc.org/resources/protocolsupport.7201/)
|
||||
* [Spigot](https://www.spigotmc.org) 1.8.8+
|
||||
* Java 8+
|
||||
* Server software in offlinemode:
|
||||
* Spigot (or a fork e.g. Paper) 1.8.8+
|
||||
* Protocol plugin:
|
||||
* [ProtocolLib](https://www.spigotmc.org/resources/protocollib.1997/) or
|
||||
* [ProtocolSupport](https://www.spigotmc.org/resources/protocolsupport.7201/)
|
||||
* Latest BungeeCord (or a fork e.g. Waterfall)
|
||||
* Run Spigot (or a fork e.g. Paper) and/or BungeeCord (or a fork e.g. Waterfall) in offline mode
|
||||
* An auth plugin.
|
||||
|
||||
### Supported auth plugins
|
||||
@@ -103,28 +102,20 @@ This plugin performs network requests to:
|
||||
### Spigot/Paper
|
||||
|
||||
1. Download and install ProtocolLib/ProtocolSupport
|
||||
2. Download and install FastLogin (or `FastLoginBukkit` for newer versions)
|
||||
3. Set your server in offline mode by setting the value `onlinemode` in your server.properties to false
|
||||
2. Download and install FastLogin (or FastLoginBukkit for newer versions)
|
||||
3. Set your server in offline mode by setting the value onlinemode in your server.properties to false
|
||||
|
||||
### BungeeCord/Waterfall or Velocity
|
||||
### BungeeCord/Waterfall
|
||||
|
||||
Install the plugin on both platforms, that is proxy (BungeeCord or Velocity) and backend server (Spigot).
|
||||
|
||||
1. Activate proxy support in the server configuration
|
||||
* This is often found in `spigot.yml` or `paper.yml`
|
||||
2. Restart the backend server
|
||||
3. Now there is `allowed-proxies.txt` file in the FastLogin folder of the restarted server
|
||||
* BungeeCord: Put your `stats-id` from the BungeeCord config into this file
|
||||
* Velocity: On plugin startup the plugin generates a `proxyId.txt` inside the plugins folder of the proxy
|
||||
4. Activate ip forwarding in your proxy config
|
||||
5. Check your database settings in the config of FastLogin on your proxy
|
||||
* The proxies only ship with a limited set of drivers where Spigot supports more. Therefore, these are supported:
|
||||
* BungeeCord: `com.mysql.jdbc.Driver` for MySQL/MariaDB
|
||||
* Velocity: `fastlogin.mariadb.jdbc.Driver` for MySQL/MariaDB
|
||||
* Note the embedded file storage SQLite is not available
|
||||
* MySQL/MariaDB requires an external database server running. Check your server provider if there is one available
|
||||
or install one.
|
||||
6. Set proxy and Spigot in offline mode by setting the value `onlinemode` in your `config.yml` to false
|
||||
7. You should *always* firewall your Spigot server that it's only accessible through your proxy
|
||||
* This is also the case without this plugin
|
||||
* https://www.spigotmc.org/wiki/bungeecord-installation/#post-installation
|
||||
1. Activate BungeeCord in the Spigot configuration
|
||||
2. Restart your server
|
||||
3. Now there is `allowed-proxies.txt` file in the FastLogin folder
|
||||
Put your stats id from the BungeeCord config into this file
|
||||
4. Activate ipForward in your BungeeCord config
|
||||
5. Download and Install FastLogin (or FastLoginBungee in newer versions) on BungeeCord AND Spigot
|
||||
(on the servers where your login plugin is or where player should be able to execute the commands of FastLogin)
|
||||
6. Check your database settings in the config of FastLogin on BungeeCord
|
||||
7. Set proxy and Spigot in offline mode by setting the value onlinemode in your config.yml to false
|
||||
8. You should *always* firewall your Spigot server that it's only accessible through BungeeCord
|
||||
* https://www.spigotmc.org/wiki/bungeecord-installation/#post-installation
|
||||
* BungeeCord doesn't support SQLite per default, so you should change the configuration to MySQL or MariaDB
|
||||
|
||||
127
bukkit/pom.xml
127
bukkit/pom.xml
@@ -4,7 +4,7 @@
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2015-2022 games647 and contributors
|
||||
Copyright (c) 2015-2021 <Your name and contributors>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
@@ -36,7 +36,7 @@
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
<!--This has to be in lowercase because it's used by plugin.yml-->
|
||||
<!--This have to be in lowercase because it's used by plugin.yml-->
|
||||
<artifactId>fastlogin.bukkit</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
@@ -47,7 +47,7 @@
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-shade-plugin</artifactId>
|
||||
<version>3.3.0</version>
|
||||
<version>3.2.4</version>
|
||||
<configuration>
|
||||
<createDependencyReducedPom>false</createDependencyReducedPom>
|
||||
<shadedArtifactAttached>false</shadedArtifactAttached>
|
||||
@@ -68,33 +68,11 @@
|
||||
<pattern>com.google.gson</pattern>
|
||||
<shadedPattern>fastlogin.gson</shadedPattern>
|
||||
</relocation>
|
||||
<relocation>
|
||||
<pattern>com.google.common</pattern>
|
||||
<shadedPattern>fastlogin.guava</shadedPattern>
|
||||
<excludes>
|
||||
<exclude>com.google.common.collect.Multimap</exclude>
|
||||
</excludes>
|
||||
</relocation>
|
||||
<relocation>
|
||||
<pattern>io.papermc.lib</pattern>
|
||||
<shadedPattern>fastlogin.paperlib</shadedPattern>
|
||||
</relocation>
|
||||
</relocations>
|
||||
<!-- Rename the service file too to let SLF4J api find our own relocated jdk logger -->
|
||||
<!-- Located in META-INF/services -->
|
||||
<transformers>
|
||||
<transformer implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer"/>
|
||||
</transformers>
|
||||
<minimizeJar>true</minimizeJar>
|
||||
<filters>
|
||||
<filter>
|
||||
<artifact>*:*</artifact>
|
||||
<excludes>
|
||||
<exclude>META-INF/MANIFEST.MF</exclude>
|
||||
<exclude>**/module-info.class</exclude>
|
||||
</excludes>
|
||||
</filter>
|
||||
</filters>
|
||||
</configuration>
|
||||
<executions>
|
||||
<execution>
|
||||
@@ -128,6 +106,12 @@
|
||||
<repository>
|
||||
<id>codemc-releases</id>
|
||||
<url>https://repo.codemc.io/repository/maven-public/</url>
|
||||
</repository>
|
||||
|
||||
<!-- GitHub automatic maven builds -->
|
||||
<repository>
|
||||
<id>jitpack.io</id>
|
||||
<url>https://jitpack.io</url>
|
||||
<snapshots>
|
||||
<enabled>false</enabled>
|
||||
</snapshots>
|
||||
@@ -142,13 +126,10 @@
|
||||
</snapshots>
|
||||
</repository>
|
||||
|
||||
<!-- GitHub automatic maven builds -->
|
||||
<!-- Floodgate -->
|
||||
<repository>
|
||||
<id>jitpack.io</id>
|
||||
<url>https://jitpack.io</url>
|
||||
<snapshots>
|
||||
<enabled>false</enabled>
|
||||
</snapshots>
|
||||
<id>nukkitx-snapshot</id>
|
||||
<url>https://repo.nukkitx.com/maven-snapshots/</url>
|
||||
</repository>
|
||||
</repositories>
|
||||
|
||||
@@ -160,33 +141,27 @@
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- PaperSpigot API for correcting user cache usage -->
|
||||
<!-- PaperSpigot API for correcting usercache usage -->
|
||||
<dependency>
|
||||
<groupId>io.papermc.paper</groupId>
|
||||
<groupId>com.destroystokyo.paper</groupId>
|
||||
<artifactId>paper-api</artifactId>
|
||||
<version>1.18-R0.1-SNAPSHOT</version>
|
||||
<version>1.16.5-R0.1-SNAPSHOT</version>
|
||||
<scope>provided</scope>
|
||||
<!-- Use our own newer api version -->
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-api</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
|
||||
<!-- PaperLib for checking if server uses PaperSpigot -->
|
||||
<dependency>
|
||||
<groupId>io.papermc</groupId>
|
||||
<artifactId>paperlib</artifactId>
|
||||
<version>1.0.7</version>
|
||||
<version>1.0.6</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
|
||||
<!--Library for listening and sending Minecraft packets-->
|
||||
<dependency>
|
||||
<groupId>com.comphenix.protocol</groupId>
|
||||
<artifactId>ProtocolLib</artifactId>
|
||||
<version>4.8.0</version>
|
||||
<version>4.6.0</version>
|
||||
<scope>provided</scope>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
@@ -211,51 +186,11 @@
|
||||
</exclusions>
|
||||
</dependency>
|
||||
|
||||
<!--Floodgate for Xbox Live Authentication-->
|
||||
<dependency>
|
||||
<groupId>org.geysermc.floodgate</groupId>
|
||||
<artifactId>api</artifactId>
|
||||
<version>2.0-SNAPSHOT</version>
|
||||
<scope>provided</scope>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>io.netty</groupId>
|
||||
<artifactId>*</artifactId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<groupId>org.geysermc.cumulus</groupId>
|
||||
<artifactId>*</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
|
||||
<!-- Bedrock player bridge -->
|
||||
<dependency>
|
||||
<groupId>org.geysermc</groupId>
|
||||
<artifactId>core</artifactId>
|
||||
<version>${geyser.version}</version>
|
||||
<scope>provided</scope>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>*</groupId>
|
||||
<artifactId>*</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
|
||||
<!-- We need the API, but it was excluded above -->
|
||||
<dependency>
|
||||
<groupId>org.geysermc</groupId>
|
||||
<artifactId>geyser-api</artifactId>
|
||||
<version>${geyser.version}</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<!--Provide premium placeholders-->
|
||||
<dependency>
|
||||
<groupId>me.clip</groupId>
|
||||
<artifactId>placeholderapi</artifactId>
|
||||
<version>2.11.1</version>
|
||||
<version>2.10.8</version>
|
||||
<scope>provided</scope>
|
||||
<optional>true</optional>
|
||||
<exclusions>
|
||||
@@ -266,6 +201,14 @@
|
||||
</exclusions>
|
||||
</dependency>
|
||||
|
||||
<!--Floodgate for Xbox Live Authentication-->
|
||||
<dependency>
|
||||
<groupId>org.geysermc.floodgate</groupId>
|
||||
<artifactId>api</artifactId>
|
||||
<version>2.0-SNAPSHOT</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<!--Login Plugins-->
|
||||
<dependency>
|
||||
<groupId>fr.xephi</groupId>
|
||||
@@ -284,7 +227,7 @@
|
||||
<dependency>
|
||||
<groupId>com.lenis0012.bukkit</groupId>
|
||||
<artifactId>loginsecurity</artifactId>
|
||||
<version>3.1</version>
|
||||
<version>3.0.2</version>
|
||||
<scope>provided</scope>
|
||||
<optional>true</optional>
|
||||
<exclusions>
|
||||
@@ -351,5 +294,19 @@
|
||||
<scope>system</scope>
|
||||
<systemPath>${project.basedir}/lib/UltraAuth v2.1.2.jar</systemPath>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.github.Mohist-Community.SodionAuth</groupId>
|
||||
<artifactId>SodionAuth-Bukkit</artifactId>
|
||||
<version>2bdfdc854b</version>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>com.github.Mohist-Community.SodionAuth</groupId>
|
||||
<artifactId>SodionAuth-Libs</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
<optional>true</optional>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2015-2022 games647 and contributors
|
||||
* Copyright (c) 2015-2021 <Your name and contributors>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
@@ -69,11 +69,11 @@ public class BukkitLoginSession extends LoginSession {
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the verify-token the server sent to the client.
|
||||
* Gets the verify token the server sent to the client.
|
||||
*
|
||||
* Empty if it's a BungeeCord connection
|
||||
*
|
||||
* @return verify token from the server
|
||||
* @return the verify token from the server
|
||||
*/
|
||||
public synchronized byte[] getVerifyToken() {
|
||||
return verifyToken.clone();
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2015-2022 games647 and contributors
|
||||
* Copyright (c) 2015-2021 <Your name and contributors>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
@@ -28,6 +28,7 @@ package com.github.games647.fastlogin.bukkit;
|
||||
import com.github.games647.fastlogin.core.AsyncScheduler;
|
||||
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.ThreadFactory;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
@@ -37,8 +38,8 @@ public class BukkitScheduler extends AsyncScheduler {
|
||||
|
||||
private final Executor syncExecutor;
|
||||
|
||||
public BukkitScheduler(Plugin plugin, Logger logger) {
|
||||
super(logger, command -> Bukkit.getScheduler().runTaskAsynchronously(plugin, command));
|
||||
public BukkitScheduler(Plugin plugin, Logger logger, ThreadFactory threadFactory) {
|
||||
super(logger, threadFactory);
|
||||
|
||||
syncExecutor = r -> Bukkit.getScheduler().runTask(plugin, r);
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2015-2022 games647 and contributors
|
||||
* Copyright (c) 2015-2021 <Your name and contributors>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
@@ -88,9 +88,9 @@ public class BungeeManager {
|
||||
|
||||
public void initialize() {
|
||||
try {
|
||||
enabled = detectProxy();
|
||||
enabled = detectBungeeCord();
|
||||
} catch (Exception ex) {
|
||||
plugin.getLog().warn("Cannot check proxy support. Fallback to non-proxy mode", ex);
|
||||
plugin.getLog().warn("Cannot check bungeecord support. Fallback to non-bungee mode", ex);
|
||||
}
|
||||
|
||||
if (enabled) {
|
||||
@@ -99,21 +99,16 @@ public class BungeeManager {
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isProxySupported(String className, String fieldName) {
|
||||
private boolean detectBungeeCord() throws Exception {
|
||||
try {
|
||||
return Class.forName(className).getDeclaredField(fieldName).getBoolean(null);
|
||||
enabled = Class.forName("org.spigotmc.SpigotConfig").getDeclaredField("bungee").getBoolean(null);
|
||||
return enabled;
|
||||
} catch (ClassNotFoundException notFoundEx) {
|
||||
//ignore server has no proxy support
|
||||
} catch (NoSuchFieldException | IllegalAccessException noSuchFieldException) {
|
||||
plugin.getLog().warn("Cannot access proxy field", noSuchFieldException);
|
||||
//ignore server has no bungee support
|
||||
return false;
|
||||
} catch (Exception ex) {
|
||||
throw ex;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean detectProxy() {
|
||||
return isProxySupported("org.spigotmc.SpigotConfig", "bungee")
|
||||
|| isProxySupported("com.destroystokyo.paper.PaperConfig", "velocitySupport");
|
||||
}
|
||||
|
||||
private void registerPluginChannels() {
|
||||
@@ -167,7 +162,7 @@ public class BungeeManager {
|
||||
/**
|
||||
* Mark the event to be fired including the task delay.
|
||||
*
|
||||
* @param player joining player
|
||||
* @param player
|
||||
*/
|
||||
public synchronized void markJoinEventFired(Player player) {
|
||||
firedJoinEvents.add(player.getUniqueId());
|
||||
@@ -181,7 +176,7 @@ public class BungeeManager {
|
||||
* session. If not fired, we can start a new force login task. This will still match the requirement that we wait
|
||||
* a certain time after the player join event fired.
|
||||
*
|
||||
* @param player joining player
|
||||
* @param player
|
||||
* @return event fired including delay
|
||||
*/
|
||||
public synchronized boolean didJoinEventFired(Player player) {
|
||||
@@ -191,7 +186,7 @@ public class BungeeManager {
|
||||
/**
|
||||
* Player quit clean up
|
||||
*
|
||||
* @param player joining player
|
||||
* @param player
|
||||
*/
|
||||
public synchronized void cleanup(Player player) {
|
||||
firedJoinEvents.remove(player.getUniqueId());
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2015-2022 games647 and contributors
|
||||
* Copyright (c) 2015-2021 <Your name and contributors>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
@@ -25,20 +25,17 @@
|
||||
*/
|
||||
package com.github.games647.fastlogin.bukkit;
|
||||
|
||||
import com.destroystokyo.paper.event.player.PlayerHandshakeEvent;
|
||||
import com.github.games647.fastlogin.bukkit.command.CrackedCommand;
|
||||
import com.github.games647.fastlogin.bukkit.command.PremiumCommand;
|
||||
import com.github.games647.fastlogin.bukkit.listener.ConnectionListener;
|
||||
import com.github.games647.fastlogin.bukkit.listener.PaperCacheListener;
|
||||
import com.github.games647.fastlogin.bukkit.listener.protocollib.ManualNameChange;
|
||||
import com.github.games647.fastlogin.bukkit.listener.protocollib.ProtocolLibListener;
|
||||
import com.github.games647.fastlogin.bukkit.listener.protocollib.SkinApplyListener;
|
||||
import com.github.games647.fastlogin.bukkit.listener.protocolsupport.ProtocolSupportListener;
|
||||
import com.github.games647.fastlogin.bukkit.task.DelayedAuthHook;
|
||||
import com.github.games647.fastlogin.core.CommonUtil;
|
||||
import com.github.games647.fastlogin.core.PremiumStatus;
|
||||
import com.github.games647.fastlogin.core.hooks.bedrock.BedrockService;
|
||||
import com.github.games647.fastlogin.core.hooks.bedrock.FloodgateService;
|
||||
import com.github.games647.fastlogin.core.hooks.bedrock.GeyserService;
|
||||
import com.github.games647.fastlogin.core.shared.FastLoginCore;
|
||||
import com.github.games647.fastlogin.core.shared.PlatformPlugin;
|
||||
|
||||
@@ -46,8 +43,8 @@ import io.papermc.lib.PaperLib;
|
||||
|
||||
import java.net.InetSocketAddress;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
@@ -55,10 +52,10 @@ import java.util.concurrent.ConcurrentMap;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.plugin.PluginManager;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
import org.geysermc.floodgate.api.FloodgateApi;
|
||||
import org.geysermc.geyser.GeyserImpl;
|
||||
import org.slf4j.Logger;
|
||||
|
||||
/**
|
||||
@@ -70,19 +67,16 @@ public class FastLoginBukkit extends JavaPlugin implements PlatformPlugin<Comman
|
||||
private final ConcurrentMap<String, BukkitLoginSession> loginSession = CommonUtil.buildCache(1, -1);
|
||||
private final Map<UUID, PremiumStatus> premiumPlayers = new ConcurrentHashMap<>();
|
||||
private final Logger logger;
|
||||
|
||||
private final BukkitScheduler scheduler;
|
||||
private boolean serverStarted;
|
||||
private BungeeManager bungeeManager;
|
||||
private final BukkitScheduler scheduler;
|
||||
private FastLoginCore<Player, CommandSender, FastLoginBukkit> core;
|
||||
private FloodgateService floodgateService;
|
||||
private GeyserService geyserService;
|
||||
|
||||
private PremiumPlaceholder premiumPlaceholder;
|
||||
|
||||
public FastLoginBukkit() {
|
||||
this.logger = CommonUtil.initializeLoggerService(getLogger());
|
||||
this.scheduler = new BukkitScheduler(this, logger);
|
||||
this.logger = CommonUtil.createLoggerFromJDK(getLogger());
|
||||
this.scheduler = new BukkitScheduler(this, logger, getThreadFactory());
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -91,19 +85,31 @@ public class FastLoginBukkit extends JavaPlugin implements PlatformPlugin<Comman
|
||||
core.load();
|
||||
|
||||
if (getServer().getOnlineMode()) {
|
||||
//we need to require offline to prevent a loginSession request for an offline player
|
||||
//we need to require offline to prevent a loginSession request for a offline player
|
||||
logger.error("Server has to be in offline mode");
|
||||
setEnabled(false);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!initializeFloodgate()) {
|
||||
// Check Floodgate config values
|
||||
if (!isValidFloodgateConfigString("autoLoginFloodgate")
|
||||
|| !isValidFloodgateConfigString("allowFloodgateNameConflict")) {
|
||||
setEnabled(false);
|
||||
return;
|
||||
}
|
||||
|
||||
bungeeManager = new BungeeManager(this);
|
||||
bungeeManager.initialize();
|
||||
|
||||
getServer().getPluginManager().registerEvents(new Listener() {
|
||||
|
||||
@EventHandler
|
||||
void onHandshake(PlayerHandshakeEvent handshakeEvent) {
|
||||
handshakeEvent.setCancelled(false);
|
||||
handshakeEvent.setSocketAddressHostname("192.168.0.1");
|
||||
}
|
||||
}, this);
|
||||
|
||||
PluginManager pluginManager = getServer().getPluginManager();
|
||||
if (bungeeManager.isEnabled()) {
|
||||
markInitialized();
|
||||
@@ -118,21 +124,6 @@ public class FastLoginBukkit extends JavaPlugin implements PlatformPlugin<Comman
|
||||
} else if (pluginManager.isPluginEnabled("ProtocolLib")) {
|
||||
ProtocolLibListener.register(this, core.getRateLimiter());
|
||||
|
||||
if (isPluginInstalled("floodgate")) {
|
||||
if (getConfig().getBoolean("floodgatePrefixWorkaround")){
|
||||
ManualNameChange.register(this, floodgateService);
|
||||
logger.info("Floodgate prefix injection workaround has been enabled.");
|
||||
logger.info("If you have problems joining the server, try disabling it in the configuration.");
|
||||
} else {
|
||||
logger.warn("We have detected that you are runnging FastLogin alongside Floodgate and ProtocolLib.");
|
||||
logger.warn("Currently there is an issue with FastLogin that prevents Floodgate name prefixes from showing up "
|
||||
+ "when it is together used with ProtocolLib.");
|
||||
logger.warn("If you would like to use Floodgate name prefixes, you can enable an experimental workaround by changing "
|
||||
+ "the value 'floodgatePrefixWorkaround' to true in config.yml.");
|
||||
logger.warn("For more information visit https://github.com/games647/FastLogin/issues/493");
|
||||
}
|
||||
}
|
||||
|
||||
//if server is using paper - we need to set the skin at pre login anyway, so no need for this listener
|
||||
if (!PaperLib.isPaper() && getConfig().getBoolean("forwardSkin")) {
|
||||
pluginManager.registerEvents(new SkinApplyListener(this), this);
|
||||
@@ -149,14 +140,14 @@ public class FastLoginBukkit extends JavaPlugin implements PlatformPlugin<Comman
|
||||
|
||||
pluginManager.registerEvents(new ConnectionListener(this), this);
|
||||
|
||||
//if server is using paper - we need to add one more listener to correct the user cache usage
|
||||
//if server is using paper - we need to add one more listener to correct the usercache usage
|
||||
if (PaperLib.isPaper()) {
|
||||
pluginManager.registerEvents(new PaperCacheListener(this), this);
|
||||
}
|
||||
|
||||
//register commands using a unique name
|
||||
Optional.ofNullable(getCommand("premium")).ifPresent(c -> c.setExecutor(new PremiumCommand(this)));
|
||||
Optional.ofNullable(getCommand("cracked")).ifPresent(c -> c.setExecutor(new CrackedCommand(this)));
|
||||
getCommand("premium").setExecutor(new PremiumCommand(this));
|
||||
getCommand("cracked").setExecutor(new CrackedCommand(this));
|
||||
|
||||
if (pluginManager.isPluginEnabled("PlaceholderAPI")) {
|
||||
premiumPlaceholder = new PremiumPlaceholder(this);
|
||||
@@ -166,22 +157,6 @@ public class FastLoginBukkit extends JavaPlugin implements PlatformPlugin<Comman
|
||||
dependencyWarnings();
|
||||
}
|
||||
|
||||
private boolean initializeFloodgate() {
|
||||
if (getServer().getPluginManager().getPlugin("Geyser-Spigot") != null) {
|
||||
geyserService = new GeyserService(GeyserImpl.getInstance(), core);
|
||||
}
|
||||
|
||||
if (getServer().getPluginManager().getPlugin("floodgate") != null) {
|
||||
floodgateService = new FloodgateService(FloodgateApi.getInstance(), core);
|
||||
|
||||
// Check Floodgate config values and return
|
||||
return floodgateService.isValidFloodgateConfigString("autoLoginFloodgate")
|
||||
&& floodgateService.isValidFloodgateConfigString("allowFloodgateNameConflict");
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDisable() {
|
||||
loginSession.clear();
|
||||
@@ -191,10 +166,7 @@ public class FastLoginBukkit extends JavaPlugin implements PlatformPlugin<Comman
|
||||
core.close();
|
||||
}
|
||||
|
||||
if (bungeeManager != null) {
|
||||
bungeeManager.cleanup();
|
||||
}
|
||||
|
||||
bungeeManager.cleanup();
|
||||
if (premiumPlaceholder != null && getServer().getPluginManager().isPluginEnabled("PlaceholderAPI")) {
|
||||
try {
|
||||
premiumPlaceholder.unregister();
|
||||
@@ -218,22 +190,23 @@ public class FastLoginBukkit extends JavaPlugin implements PlatformPlugin<Comman
|
||||
return loginSession;
|
||||
}
|
||||
|
||||
public BukkitLoginSession getSession(InetSocketAddress address) {
|
||||
String id = getSessionId(address);
|
||||
return loginSession.get(id);
|
||||
public BukkitLoginSession getSession(InetSocketAddress addr) {
|
||||
String id = getSessionId(addr);
|
||||
BukkitLoginSession session = loginSession.get(id);
|
||||
return session;
|
||||
}
|
||||
|
||||
public String getSessionId(InetSocketAddress address) {
|
||||
return address.getAddress().getHostAddress() + ':' + address.getPort();
|
||||
public String getSessionId(InetSocketAddress addr) {
|
||||
return addr.getAddress().getHostAddress() + ':' + addr.getPort();
|
||||
}
|
||||
|
||||
public void putSession(InetSocketAddress address, BukkitLoginSession session) {
|
||||
String id = getSessionId(address);
|
||||
public void putSession(InetSocketAddress addr, BukkitLoginSession session) {
|
||||
String id = getSessionId(addr);
|
||||
loginSession.put(id, session);
|
||||
}
|
||||
|
||||
public void removeSession(InetSocketAddress address) {
|
||||
String id = getSessionId(address);
|
||||
public void removeSession(InetSocketAddress addr) {
|
||||
String id = getSessionId(addr);
|
||||
loginSession.remove(id);
|
||||
}
|
||||
|
||||
@@ -244,7 +217,7 @@ public class FastLoginBukkit extends JavaPlugin implements PlatformPlugin<Comman
|
||||
/**
|
||||
* Fetches the premium status of an online player.
|
||||
*
|
||||
* @param onlinePlayer player that is currently online player (play state)
|
||||
* @param onlinePlayer
|
||||
* @return the online status or unknown if an error happened, the player isn't online or BungeeCord doesn't send
|
||||
* us the status message yet (This means you cannot check the login status on the PlayerJoinEvent).
|
||||
*/
|
||||
@@ -290,31 +263,40 @@ public class FastLoginBukkit extends JavaPlugin implements PlatformPlugin<Comman
|
||||
receiver.sendMessage(message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a plugin is installed on the server
|
||||
* @param name the name of the plugin
|
||||
* @return true if the plugin is installed
|
||||
*/
|
||||
@Override
|
||||
public boolean isPluginInstalled(String name) {
|
||||
// the plugin may be enabled after FastLogin, so isPluginEnabled() won't work here
|
||||
return Bukkit.getServer().getPluginManager().getPlugin(name) != null;
|
||||
}
|
||||
|
||||
public FloodgateService getFloodgateService() {
|
||||
return floodgateService;
|
||||
}
|
||||
|
||||
public GeyserService getGeyserService() {
|
||||
return geyserService;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BedrockService<?> getBedrockService() {
|
||||
if (floodgateService != null) {
|
||||
return floodgateService;
|
||||
/**
|
||||
* Checks if a config entry (related to Floodgate) is valid. <br>
|
||||
* Writes to Log if the value is invalid.
|
||||
* <p>
|
||||
* This should be used for:
|
||||
* <ul>
|
||||
* <li>allowFloodgateNameConflict
|
||||
* <li>autoLoginFloodgate
|
||||
* <li>autoRegisterFloodgate
|
||||
* </ul>
|
||||
* </p>
|
||||
*
|
||||
* @param key the key of the entry in config.yml
|
||||
* @return <b>true</b> if the entry's value is "true", "false", or "linked"
|
||||
*/
|
||||
private boolean isValidFloodgateConfigString(String key) {
|
||||
String value = core.getConfig().get(key).toString().toLowerCase(Locale.ENGLISH);
|
||||
if (!value.equals("true") && !value.equals("linked") && !value.equals("false") && !value.equals("no-conflict")) {
|
||||
logger.error("Invalid value detected for {} in FastLogin/config.yml.", key);
|
||||
return false;
|
||||
}
|
||||
return geyserService;
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a plugin is installed on the server
|
||||
*
|
||||
* @param name the name of the plugin
|
||||
* @return true if the plugin is installed
|
||||
*/
|
||||
@Override
|
||||
public boolean isPluginInstalled(String name) {
|
||||
// the plugin may be enabled after FastLogin, so isPluginEnabled() won't work here
|
||||
return Bukkit.getServer().getPluginManager().getPlugin(name) != null;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -328,6 +310,13 @@ public class FastLoginBukkit extends JavaPlugin implements PlatformPlugin<Comman
|
||||
+ "Floodgate 2.0 from https://ci.opencollab.dev/job/GeyserMC/job/Floodgate/job/dev%252F2.0/");
|
||||
logger.warn("Don't forget to update Geyser to a supported version as well from "
|
||||
+ "https://ci.opencollab.dev/job/GeyserMC/job/Geyser/job/floodgate-2.0/");
|
||||
}
|
||||
} else if (isPluginInstalled("floodgate") && isPluginInstalled("ProtocolLib")) {
|
||||
logger.warn("We have detected that you are running FastLogin alongside Floodgate and ProtocolLib.");
|
||||
logger.warn("Currently there is an issue with FastLogin that prevents Floodgate's name prefixes from " +
|
||||
"showing up when it is together used with ProtocolLib.");
|
||||
logger.warn("If you would like to use Floodgate name prefixes, you can replace ProtocolLib with " +
|
||||
"ProtocolSupport which does not have this issue.");
|
||||
logger.warn("For more information visit https://github.com/games647/FastLogin/issues/493");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2015-2022 games647 and contributors
|
||||
* Copyright (c) 2015-2021 <Your name and contributors>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
@@ -28,7 +28,6 @@ package com.github.games647.fastlogin.bukkit;
|
||||
import me.clip.placeholderapi.expansion.PlaceholderExpansion;
|
||||
|
||||
import org.bukkit.OfflinePlayer;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class PremiumPlaceholder extends PlaceholderExpansion {
|
||||
|
||||
@@ -41,7 +40,7 @@ public class PremiumPlaceholder extends PlaceholderExpansion {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onRequest(OfflinePlayer player, @NotNull String identifier) {
|
||||
public String onRequest(OfflinePlayer player, String identifier) {
|
||||
// player is null if offline
|
||||
if (player != null && PLACEHOLDER_VARIABLE.equals(identifier)) {
|
||||
return plugin.getStatus(player.getUniqueId()).getReadableName();
|
||||
@@ -51,7 +50,7 @@ public class PremiumPlaceholder extends PlaceholderExpansion {
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull String getIdentifier() {
|
||||
public String getIdentifier() {
|
||||
return plugin.getName();
|
||||
}
|
||||
|
||||
@@ -61,12 +60,12 @@ public class PremiumPlaceholder extends PlaceholderExpansion {
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull String getAuthor() {
|
||||
public String getAuthor() {
|
||||
return String.join(", ", plugin.getDescription().getAuthors());
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull String getVersion() {
|
||||
public String getVersion() {
|
||||
return plugin.getDescription().getVersion();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2015-2022 games647 and contributors
|
||||
* Copyright (c) 2015-2021 <Your name and contributors>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
@@ -31,7 +31,6 @@ import com.github.games647.fastlogin.core.StoredProfile;
|
||||
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import static com.github.games647.fastlogin.core.shared.event.FastLoginPremiumToggleEvent.PremiumToggleReason;
|
||||
|
||||
@@ -42,7 +41,7 @@ public class CrackedCommand extends ToggleCommand {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, String[] args) {
|
||||
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
|
||||
if (args.length == 0) {
|
||||
onCrackedSelf(sender, command, args);
|
||||
} else {
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2015-2022 games647 and contributors
|
||||
* Copyright (c) 2015-2021 <Your name and contributors>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
@@ -28,18 +28,17 @@ package com.github.games647.fastlogin.bukkit.command;
|
||||
import com.github.games647.fastlogin.bukkit.FastLoginBukkit;
|
||||
import com.github.games647.fastlogin.bukkit.event.BukkitFastLoginPremiumToggleEvent;
|
||||
import com.github.games647.fastlogin.core.StoredProfile;
|
||||
import com.github.games647.fastlogin.core.shared.event.FastLoginPremiumToggleEvent.PremiumToggleReason;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
import com.github.games647.fastlogin.core.shared.event.FastLoginPremiumToggleEvent.PremiumToggleReason;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* Let users activate fast login by command. This only be accessible if
|
||||
* the user has access to its account. So we can make sure that not another
|
||||
* the user has access to it's account. So we can make sure that not another
|
||||
* person with a paid account and the same username can steal their account.
|
||||
*/
|
||||
public class PremiumCommand extends ToggleCommand {
|
||||
@@ -49,7 +48,7 @@ public class PremiumCommand extends ToggleCommand {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, String[] args) {
|
||||
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
|
||||
if (args.length == 0) {
|
||||
onPremiumSelf(sender, command, args);
|
||||
} else {
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2015-2022 games647 and contributors
|
||||
* Copyright (c) 2015-2021 <Your name and contributors>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
@@ -47,12 +47,12 @@ public abstract class ToggleCommand implements CommandExecutor {
|
||||
}
|
||||
|
||||
protected boolean hasOtherPermission(CommandSender sender, Command cmd) {
|
||||
if (sender.hasPermission(cmd.getPermission() + ".other")) {
|
||||
return true;
|
||||
if (!sender.hasPermission(cmd.getPermission() + ".other")) {
|
||||
plugin.getCore().sendLocaleMessage("no-permission", sender);
|
||||
return false;
|
||||
}
|
||||
|
||||
plugin.getCore().sendLocaleMessage("no-permission", sender);
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
protected boolean forwardBungeeCommand(CommandSender sender, String target, boolean activate) {
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2015-2022 games647 and contributors
|
||||
* Copyright (c) 2015-2021 <Your name and contributors>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
@@ -31,7 +31,6 @@ import com.github.games647.fastlogin.core.shared.event.FastLoginAutoLoginEvent;
|
||||
import org.bukkit.event.Cancellable;
|
||||
import org.bukkit.event.Event;
|
||||
import org.bukkit.event.HandlerList;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class BukkitFastLoginAutoLoginEvent extends Event implements FastLoginAutoLoginEvent, Cancellable {
|
||||
|
||||
@@ -68,7 +67,7 @@ public class BukkitFastLoginAutoLoginEvent extends Event implements FastLoginAut
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull HandlerList getHandlers() {
|
||||
public HandlerList getHandlers() {
|
||||
return handlers;
|
||||
}
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2015-2022 games647 and contributors
|
||||
* Copyright (c) 2015-2021 <Your name and contributors>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
@@ -30,7 +30,6 @@ import com.github.games647.fastlogin.core.shared.LoginSource;
|
||||
import com.github.games647.fastlogin.core.shared.event.FastLoginPreLoginEvent;
|
||||
import org.bukkit.event.Event;
|
||||
import org.bukkit.event.HandlerList;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class BukkitFastLoginPreLoginEvent extends Event implements FastLoginPreLoginEvent {
|
||||
|
||||
@@ -63,7 +62,7 @@ public class BukkitFastLoginPreLoginEvent extends Event implements FastLoginPreL
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull HandlerList getHandlers() {
|
||||
public HandlerList getHandlers() {
|
||||
return handlers;
|
||||
}
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2015-2022 games647 and contributors
|
||||
* Copyright (c) 2015-2021 <Your name and contributors>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
@@ -29,7 +29,6 @@ import com.github.games647.fastlogin.core.StoredProfile;
|
||||
import com.github.games647.fastlogin.core.shared.event.FastLoginPremiumToggleEvent;
|
||||
import org.bukkit.event.Event;
|
||||
import org.bukkit.event.HandlerList;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class BukkitFastLoginPremiumToggleEvent extends Event implements FastLoginPremiumToggleEvent {
|
||||
|
||||
@@ -54,7 +53,7 @@ public class BukkitFastLoginPremiumToggleEvent extends Event implements FastLogi
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull HandlerList getHandlers() {
|
||||
public HandlerList getHandlers() {
|
||||
return handlers;
|
||||
}
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2015-2022 games647 and contributors
|
||||
* Copyright (c) 2015-2021 <Your name and contributors>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
@@ -28,18 +28,20 @@ package com.github.games647.fastlogin.bukkit.hook;
|
||||
import com.github.games647.fastlogin.bukkit.BukkitLoginSession;
|
||||
import com.github.games647.fastlogin.bukkit.FastLoginBukkit;
|
||||
import com.github.games647.fastlogin.core.hooks.AuthPlugin;
|
||||
|
||||
import fr.xephi.authme.api.v3.AuthMeApi;
|
||||
import fr.xephi.authme.events.RestoreSessionEvent;
|
||||
import fr.xephi.authme.process.Management;
|
||||
import fr.xephi.authme.process.register.executors.ApiPasswordRegisterParams;
|
||||
import fr.xephi.authme.process.register.executors.RegistrationMethod;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.Listener;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
|
||||
/**
|
||||
* GitHub: https://github.com/Xephi/AuthMeReloaded/
|
||||
* <p>
|
||||
@@ -75,7 +77,7 @@ public class AuthMeHook implements AuthPlugin<Player>, Listener {
|
||||
public void onSessionRestore(RestoreSessionEvent restoreSessionEvent) {
|
||||
Player player = restoreSessionEvent.getPlayer();
|
||||
|
||||
BukkitLoginSession session = plugin.getSession(player.getAddress());
|
||||
BukkitLoginSession session = plugin.getSession(player.spigot().getRawAddress());
|
||||
if (session != null && session.isVerified()) {
|
||||
restoreSessionEvent.setCancelled(true);
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2015-2022 games647 and contributors
|
||||
* Copyright (c) 2015-2021 <Your name and contributors>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
@@ -121,11 +121,11 @@ public class CrazyLoginHook implements AuthPlugin<Player> {
|
||||
public boolean forceRegister(Player player, String password) {
|
||||
CrazyLoginDataDatabase crazyDatabase = crazyLoginPlugin.getCrazyDatabase();
|
||||
|
||||
//this executes a sql query and accesses only thread safe collections, so we can run it async
|
||||
//this executes a sql query and accesses only thread safe collections so we can run it async
|
||||
LoginPlayerData playerData = crazyLoginPlugin.getPlayerData(player.getName());
|
||||
if (playerData == null) {
|
||||
//create a fake account - this will be saved to the database with the password=FAILEDLOADING
|
||||
//user cannot log in with that password unless the admin uses plain text
|
||||
//user cannot login with that password unless the admin uses plain text
|
||||
//this automatically marks the player as logged in
|
||||
crazyDatabase.save(new LoginPlayerData(player));
|
||||
return forceLogin(player);
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2015-2022 games647 and contributors
|
||||
* Copyright (c) 2015-2021 <Your name and contributors>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2015-2022 games647 and contributors
|
||||
* Copyright (c) 2015-2021 <Your name and contributors>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
|
||||
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2015-2021 <Your name and contributors>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
package com.github.games647.fastlogin.bukkit.hook;
|
||||
|
||||
import com.github.games647.fastlogin.bukkit.FastLoginBukkit;
|
||||
import com.github.games647.fastlogin.core.hooks.AuthPlugin;
|
||||
import org.bukkit.entity.Player;
|
||||
import red.mohist.sodionauth.bukkit.implementation.BukkitPlayer;
|
||||
import red.mohist.sodionauth.core.SodionAuthApi;
|
||||
import red.mohist.sodionauth.core.exception.AuthenticatedException;
|
||||
|
||||
/**
|
||||
* GitHub: https://github.com/Mohist-Community/SodionAuth
|
||||
* <p>
|
||||
* Project page: https://gitea.e-loli.com/SodionAuth/SodionAuth
|
||||
* <p>
|
||||
* Bukkit: Unknown
|
||||
* <p>
|
||||
* Spigot: https://www.spigotmc.org/resources/sodionauth.76944/
|
||||
*/
|
||||
public class SodionAuthHook implements AuthPlugin<Player> {
|
||||
|
||||
private final FastLoginBukkit plugin;
|
||||
|
||||
public SodionAuthHook(FastLoginBukkit plugin) {
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean forceLogin(Player player) {
|
||||
try {
|
||||
SodionAuthApi.login(new BukkitPlayer(player));
|
||||
} catch (AuthenticatedException e) {
|
||||
plugin.getLog().warn(ALREADY_AUTHENTICATED, player);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean forceRegister(Player player, String password) {
|
||||
try{
|
||||
return SodionAuthApi.register(new BukkitPlayer(player), password);
|
||||
} catch (UnsupportedOperationException e){
|
||||
plugin.getLog().warn("Currently SodionAuth is not accepting forceRegister, " +
|
||||
"It may be caused by unsupported AuthBackend");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isRegistered(String playerName) {
|
||||
return SodionAuthApi.isRegistered(playerName);
|
||||
}
|
||||
}
|
||||
@@ -3,7 +3,7 @@
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2015-2022 games647 and contributors
|
||||
* Copyright (c) 2015-2021 <Your name and contributors>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2015-2022 games647 and contributors
|
||||
* Copyright (c) 2015-2021 <Your name and contributors>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2015-2022 games647 and contributors
|
||||
* Copyright (c) 2015-2021 <Your name and contributors>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
@@ -41,7 +41,6 @@ import java.util.UUID;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.plugin.messaging.PluginMessageListener;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* Responsible for receiving messages from a BungeeCord instance.
|
||||
@@ -58,7 +57,7 @@ public class BungeeListener implements PluginMessageListener {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPluginMessageReceived(@NotNull String channel, Player player, byte[] message) {
|
||||
public void onPluginMessageReceived(String channel, Player player, byte[] message) {
|
||||
ByteArrayDataInput dataInput = ByteStreams.newDataInput(message);
|
||||
|
||||
LoginActionMessage loginMessage = new LoginActionMessage();
|
||||
@@ -68,7 +67,7 @@ public class BungeeListener implements PluginMessageListener {
|
||||
|
||||
Player targetPlayer = player;
|
||||
if (!loginMessage.getPlayerName().equals(player.getName())) {
|
||||
targetPlayer = Bukkit.getPlayerExact(loginMessage.getPlayerName());
|
||||
targetPlayer = Bukkit.getPlayerExact(loginMessage.getPlayerName());;
|
||||
}
|
||||
|
||||
if (targetPlayer == null) {
|
||||
@@ -127,9 +126,9 @@ public class BungeeListener implements PluginMessageListener {
|
||||
|
||||
private void startLoginTaskIfReady(Player player, BukkitLoginSession session) {
|
||||
session.setVerified(true);
|
||||
plugin.putSession(player.getAddress(), session);
|
||||
plugin.putSession(player.spigot().getRawAddress(), session);
|
||||
|
||||
// only start a new login task if the join event fired earlier. This event then didn't
|
||||
// only start a new login task if the join event fired earlier. This event then didn
|
||||
boolean result = plugin.getBungeeManager().didJoinEventFired(player);
|
||||
plugin.getLog().info("Delaying force login until join event fired?: {}", result);
|
||||
if (result) {
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2015-2022 games647 and contributors
|
||||
* Copyright (c) 2015-2021 <Your name and contributors>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
@@ -29,7 +29,6 @@ import com.github.games647.fastlogin.bukkit.BukkitLoginSession;
|
||||
import com.github.games647.fastlogin.bukkit.FastLoginBukkit;
|
||||
import com.github.games647.fastlogin.bukkit.task.FloodgateAuthTask;
|
||||
import com.github.games647.fastlogin.bukkit.task.ForceLoginTask;
|
||||
import com.github.games647.fastlogin.core.hooks.bedrock.FloodgateService;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Player;
|
||||
@@ -39,12 +38,12 @@ import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.player.PlayerJoinEvent;
|
||||
import org.bukkit.event.player.PlayerLoginEvent;
|
||||
import org.bukkit.event.player.PlayerLoginEvent.Result;
|
||||
import org.bukkit.event.player.PlayerQuitEvent;
|
||||
import org.bukkit.metadata.Metadatable;
|
||||
import org.geysermc.floodgate.api.FloodgateApi;
|
||||
import org.geysermc.floodgate.api.player.FloodgatePlayer;
|
||||
import org.bukkit.event.player.PlayerQuitEvent;
|
||||
|
||||
/**
|
||||
* This listener tells authentication plugins weather the player has a premium account. So the
|
||||
* This listener tells authentication plugins if the player has a premium account and we checked it successfully. So the
|
||||
* plugin can skip authentication.
|
||||
*/
|
||||
public class ConnectionListener implements Listener {
|
||||
@@ -70,43 +69,37 @@ public class ConnectionListener implements Listener {
|
||||
Player player = joinEvent.getPlayer();
|
||||
|
||||
Bukkit.getScheduler().runTaskLater(plugin, () -> {
|
||||
delayForceLogin(player);
|
||||
// session exists so the player is ready for force login
|
||||
// cases: Paper (firing BungeeCord message before PlayerJoinEvent) or not running BungeeCord and already
|
||||
// having the login session from the login process
|
||||
BukkitLoginSession session = plugin.getSession(player.spigot().getRawAddress());
|
||||
|
||||
boolean isFloodgateLogin = false;
|
||||
if (Bukkit.getServer().getPluginManager().isPluginEnabled("floodgate")) {
|
||||
FloodgatePlayer floodgatePlayer = FloodgateApi.getInstance().getPlayer(player.getUniqueId());
|
||||
if (floodgatePlayer != null) {
|
||||
isFloodgateLogin = true;
|
||||
Runnable floodgateAuthTask = new FloodgateAuthTask(plugin.getCore(), player, floodgatePlayer);
|
||||
Bukkit.getScheduler().runTaskAsynchronously(plugin, floodgateAuthTask);
|
||||
}
|
||||
}
|
||||
|
||||
if (!isFloodgateLogin) {
|
||||
if (session == null) {
|
||||
String sessionId = plugin.getSessionId(player.spigot().getRawAddress());
|
||||
plugin.getLog().info("No on-going login session for player: {} with ID {}", player, sessionId);
|
||||
} else {
|
||||
Runnable forceLoginTask = new ForceLoginTask(plugin.getCore(), player, session);
|
||||
Bukkit.getScheduler().runTaskAsynchronously(plugin, forceLoginTask);
|
||||
}
|
||||
}
|
||||
|
||||
plugin.getBungeeManager().markJoinEventFired(player);
|
||||
// delay the login process to let auth plugins initialize the player
|
||||
// Magic number however as there is no direct event from those plugins
|
||||
}, DELAY_LOGIN);
|
||||
}
|
||||
|
||||
private void delayForceLogin(Player player) {
|
||||
// session exists so the player is ready for force login
|
||||
// cases: Paper (firing BungeeCord message before PlayerJoinEvent) or not running BungeeCord and already
|
||||
// having the login session from the login process
|
||||
BukkitLoginSession session = plugin.getSession(player.getAddress());
|
||||
|
||||
if (session == null) {
|
||||
// Floodgate players usually don't have a session at this point
|
||||
// exception: if force login by bungee message had been delayed
|
||||
FloodgateService floodgateService = plugin.getFloodgateService();
|
||||
if (floodgateService != null) {
|
||||
FloodgatePlayer floodgatePlayer = floodgateService.getBedrockPlayer(player.getUniqueId());
|
||||
if (floodgatePlayer != null) {
|
||||
Runnable floodgateAuthTask = new FloodgateAuthTask(plugin.getCore(), player, floodgatePlayer);
|
||||
Bukkit.getScheduler().runTaskAsynchronously(plugin, floodgateAuthTask);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
String sessionId = plugin.getSessionId(player.getAddress());
|
||||
plugin.getLog().info("No on-going login session for player: {} with ID {}. ", player, sessionId);
|
||||
plugin.getLog().info("Setups using Minecraft proxies will start delayed " +
|
||||
"when the command from the proxy is received");
|
||||
} else {
|
||||
Runnable forceLoginTask = new ForceLoginTask(plugin.getCore(), player, session);
|
||||
Bukkit.getScheduler().runTaskAsynchronously(plugin, forceLoginTask);
|
||||
}
|
||||
|
||||
plugin.getBungeeManager().markJoinEventFired(player);
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onPlayerQuit(PlayerQuitEvent quitEvent) {
|
||||
Player player = quitEvent.getPlayer();
|
||||
@@ -117,7 +110,7 @@ public class ConnectionListener implements Listener {
|
||||
plugin.getBungeeManager().cleanup(player);
|
||||
}
|
||||
|
||||
private void removeBlockedStatus(Metadatable player) {
|
||||
private void removeBlockedStatus(Player player) {
|
||||
player.removeMetadata(plugin.getName(), plugin);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2015-2022 games647 and contributors
|
||||
* Copyright (c) 2015-2021 <Your name and contributors>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
@@ -44,8 +44,8 @@ public class PaperCacheListener implements Listener {
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.HIGHEST)
|
||||
//if paper is used - player skin must be set at pre login, otherwise user cache is used
|
||||
// user cache makes premium name change basically impossible
|
||||
//if paper is used - player skin must be set at pre login, otherwise usercache is used
|
||||
//using usercache makes premium name change basically impossible
|
||||
public void onAsyncPlayerPreLogin(AsyncPlayerPreLoginEvent event) {
|
||||
if (event.getLoginResult() != Result.ALLOWED) {
|
||||
return;
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2015-2022 games647 and contributors
|
||||
* Copyright (c) 2015-2021 <Your name and contributors>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
@@ -35,7 +35,6 @@ import java.security.NoSuchAlgorithmException;
|
||||
import java.security.PrivateKey;
|
||||
import java.security.PublicKey;
|
||||
import java.util.Random;
|
||||
|
||||
import javax.crypto.Cipher;
|
||||
import javax.crypto.SecretKey;
|
||||
import javax.crypto.spec.SecretKeySpec;
|
||||
@@ -56,7 +55,7 @@ public class EncryptionUtil {
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate an RSA key pair
|
||||
* Generate a RSA key pair
|
||||
*
|
||||
* @return The RSA key pair.
|
||||
*/
|
||||
|
||||
@@ -1,85 +0,0 @@
|
||||
/*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2015-2022 games647 and contributors
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
package com.github.games647.fastlogin.bukkit.listener.protocollib;
|
||||
|
||||
import com.comphenix.protocol.events.PacketAdapter;
|
||||
import com.comphenix.protocol.events.PacketContainer;
|
||||
import com.comphenix.protocol.events.PacketEvent;
|
||||
import com.comphenix.protocol.wrappers.WrappedGameProfile;
|
||||
import com.github.games647.fastlogin.bukkit.FastLoginBukkit;
|
||||
import com.github.games647.fastlogin.core.hooks.bedrock.FloodgateService;
|
||||
|
||||
import org.geysermc.floodgate.api.FloodgateApi;
|
||||
|
||||
import static com.comphenix.protocol.PacketType.Login.Client.START;
|
||||
|
||||
import com.comphenix.protocol.ProtocolLibrary;
|
||||
|
||||
/**
|
||||
* Manually inject Floodgate player name prefixes.
|
||||
* <br>
|
||||
* This is used as a workaround, because Floodgate fails to inject
|
||||
* the prefixes when it's used together with ProtocolLib and FastLogin.
|
||||
* <br>
|
||||
* For more information visit: https://github.com/games647/FastLogin/issues/493
|
||||
*/
|
||||
public class ManualNameChange extends PacketAdapter {
|
||||
|
||||
private final FloodgateService floodgate;
|
||||
|
||||
public ManualNameChange(FastLoginBukkit plugin, FloodgateService floodgate) {
|
||||
super(params()
|
||||
.plugin(plugin)
|
||||
.types(START));
|
||||
|
||||
this.plugin = plugin;
|
||||
this.floodgate = floodgate;
|
||||
}
|
||||
|
||||
public static void register(FastLoginBukkit plugin, FloodgateService floodgate) {
|
||||
// they will be created with a static builder, because otherwise it will throw a NoClassDefFoundError
|
||||
ProtocolLibrary.getProtocolManager()
|
||||
.getAsynchronousManager()
|
||||
.registerAsyncHandler(new ManualNameChange(plugin, floodgate))
|
||||
.start();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPacketReceiving(PacketEvent packetEvent) {
|
||||
PacketContainer packet = packetEvent.getPacket();
|
||||
WrappedGameProfile originalProfile = packet.getGameProfiles().read(0);
|
||||
|
||||
if (floodgate.getBedrockPlayer(originalProfile.getName()) == null) {
|
||||
//not a Floodgate player, no need to add a prefix
|
||||
return;
|
||||
}
|
||||
|
||||
packet.setMeta("original_name", originalProfile.getName());
|
||||
String prefixedName = FloodgateApi.getInstance().getPlayerPrefix() + originalProfile.getName();
|
||||
WrappedGameProfile updatedProfile = originalProfile.withName(prefixedName);
|
||||
packet.getGameProfiles().write(0, updatedProfile);
|
||||
}
|
||||
}
|
||||
@@ -3,7 +3,7 @@
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2015-2022 games647 and contributors
|
||||
* Copyright (c) 2015-2021 <Your name and contributors>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
@@ -54,7 +54,7 @@ public class NameCheckTask extends JoinManagement<Player, CommandSender, Protoco
|
||||
|
||||
public NameCheckTask(FastLoginBukkit plugin, Random random, Player player, PacketEvent packetEvent,
|
||||
String username, PublicKey publicKey) {
|
||||
super(plugin.getCore(), plugin.getCore().getAuthPluginHook(), plugin.getBedrockService());
|
||||
super(plugin.getCore(), plugin.getCore().getAuthPluginHook());
|
||||
|
||||
this.plugin = plugin;
|
||||
this.packetEvent = packetEvent;
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2015-2022 games647 and contributors
|
||||
* Copyright (c) 2015-2021 <Your name and contributors>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
@@ -124,12 +124,6 @@ public class ProtocolLibListener extends PacketAdapter {
|
||||
PacketContainer packet = packetEvent.getPacket();
|
||||
|
||||
String username = packet.getGameProfiles().read(0).getName();
|
||||
|
||||
if (packetEvent.getPacket().getMeta("original_name").isPresent()) {
|
||||
//username has been injected by ManualNameChange.java
|
||||
username = (String) packetEvent.getPacket().getMeta("original_name").get();
|
||||
}
|
||||
|
||||
plugin.getLog().trace("GameProfile {} with {} connecting", sessionKey, username);
|
||||
|
||||
packetEvent.getAsyncMarker().incrementProcessingDelay();
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2015-2022 games647 and contributors
|
||||
* Copyright (c) 2015-2021 <Your name and contributors>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
@@ -60,7 +60,7 @@ class ProtocolLibLoginSource implements LoginSource {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void enableOnlinemode() throws InvocationTargetException {
|
||||
public void enableOnlinemode() throws Exception {
|
||||
verifyToken = EncryptionUtil.generateVerifyToken(random);
|
||||
|
||||
/*
|
||||
@@ -83,7 +83,7 @@ class ProtocolLibLoginSource implements LoginSource {
|
||||
|
||||
newPacket.getByteArrays().write(verifyField, verifyToken);
|
||||
|
||||
//serverId is an empty string
|
||||
//serverId is a empty string
|
||||
ProtocolLibrary.getProtocolManager().sendServerPacket(player, newPacket);
|
||||
}
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2015-2022 games647 and contributors
|
||||
* Copyright (c) 2015-2021 <Your name and contributors>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2015-2022 games647 and contributors
|
||||
* Copyright (c) 2015-2021 <Your name and contributors>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
@@ -36,18 +36,15 @@ import com.comphenix.protocol.wrappers.WrappedChatComponent;
|
||||
import com.comphenix.protocol.wrappers.WrappedGameProfile;
|
||||
import com.github.games647.craftapi.model.auth.Verification;
|
||||
import com.github.games647.craftapi.model.skin.SkinProperty;
|
||||
import com.github.games647.craftapi.resolver.AbstractResolver;
|
||||
import com.github.games647.craftapi.resolver.MojangResolver;
|
||||
import com.github.games647.fastlogin.bukkit.BukkitLoginSession;
|
||||
import com.github.games647.fastlogin.bukkit.FastLoginBukkit;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.Reader;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.net.*;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.net.InetAddress;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.security.GeneralSecurityException;
|
||||
import java.security.Key;
|
||||
import java.security.KeyPair;
|
||||
@@ -98,14 +95,13 @@ public class VerifyResponseTask implements Runnable {
|
||||
try {
|
||||
BukkitLoginSession session = plugin.getSession(player.getAddress());
|
||||
if (session == null) {
|
||||
disconnect("invalid-request",
|
||||
"GameProfile {0} tried to send encryption response at invalid state",
|
||||
player.getAddress());
|
||||
disconnect("invalid-request", true
|
||||
, "GameProfile {0} tried to send encryption response at invalid state", player.getAddress());
|
||||
} else {
|
||||
verifyResponse(session);
|
||||
}
|
||||
} finally {
|
||||
//this is a fake packet; it shouldn't be sent to the server
|
||||
//this is a fake packet; it shouldn't be send to the server
|
||||
synchronized (packetEvent.getAsyncMarker().getProcessingLock()) {
|
||||
packetEvent.setCancelled(true);
|
||||
}
|
||||
@@ -121,7 +117,7 @@ public class VerifyResponseTask implements Runnable {
|
||||
try {
|
||||
loginKey = EncryptionUtil.decryptSharedKey(privateKey, sharedSecret);
|
||||
} catch (GeneralSecurityException securityEx) {
|
||||
disconnect("error-kick", "Cannot decrypt received contents", securityEx);
|
||||
disconnect("error-kick", false, "Cannot decrypt received contents", securityEx);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -130,7 +126,7 @@ public class VerifyResponseTask implements Runnable {
|
||||
return;
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
disconnect("error-kick", "Cannot decrypt received contents", ex);
|
||||
disconnect("error-kick", false, "Cannot decrypt received contents", ex);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -147,7 +143,7 @@ public class VerifyResponseTask implements Runnable {
|
||||
plugin.getLog().info("Profile {} has a verified premium account", requestedUsername);
|
||||
String realUsername = verification.getName();
|
||||
if (realUsername == null) {
|
||||
disconnect("invalid-session", "Username field null for {}", requestedUsername);
|
||||
disconnect("invalid-session", true, "Username field null for {}", requestedUsername);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -163,11 +159,13 @@ public class VerifyResponseTask implements Runnable {
|
||||
setPremiumUUID(session.getUuid());
|
||||
receiveFakeStartPacket(realUsername);
|
||||
} else {
|
||||
//user tried to fake an authentication
|
||||
disconnect("invalid-session", "GameProfile {} ({}) tried to log in with an invalid session. ServerId: {}", session.getRequestUsername(), socketAddress, serverId);
|
||||
//user tried to fake a authentication
|
||||
disconnect("invalid-session", true
|
||||
, "GameProfile {0} ({1}) tried to log in with an invalid session ServerId: {2}"
|
||||
, session.getRequestUsername(), socketAddress, serverId);
|
||||
}
|
||||
} catch (IOException ioEx) {
|
||||
disconnect("error-kick", "Failed to connect to session server", ioEx);
|
||||
disconnect("error-kick", false, "Failed to connect to session server", ioEx);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -191,9 +189,9 @@ public class VerifyResponseTask implements Runnable {
|
||||
//https://github.com/bergerkiller/CraftSource/blob/master/net.minecraft.server/LoginListener.java#L182
|
||||
if (!Arrays.equals(requestVerify, EncryptionUtil.decrypt(serverKey.getPrivate(), responseVerify))) {
|
||||
//check if the verify-token are equal to the server sent one
|
||||
disconnect("invalid-verify-token",
|
||||
"GameProfile {0} ({1}) tried to login with an invalid verify token. Server: {2} Client: {3}",
|
||||
session.getRequestUsername(), packetEvent.getPlayer().getAddress(), requestVerify, responseVerify);
|
||||
disconnect("invalid-verify-token", true
|
||||
, "GameProfile {0} ({1}) tried to login with an invalid verify token. Server: {2} Client: {3}"
|
||||
, session.getRequestUsername(), packetEvent.getPlayer().getAddress(), requestVerify, responseVerify);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -211,7 +209,7 @@ public class VerifyResponseTask implements Runnable {
|
||||
}
|
||||
|
||||
private boolean enableEncryption(SecretKey loginKey) throws IllegalArgumentException {
|
||||
plugin.getLog().info("Enabling onlinemode encryption for {}", player.getName());
|
||||
plugin.getLog().info("Enabling onlinemode encryption for {}", player.getAddress());
|
||||
// Initialize method reflections
|
||||
if (encryptMethod == null) {
|
||||
Class<?> networkManagerClass = MinecraftReflection.getNetworkManagerClass();
|
||||
@@ -219,15 +217,15 @@ public class VerifyResponseTask implements Runnable {
|
||||
try {
|
||||
// Try to get the old (pre MC 1.16.4) encryption method
|
||||
encryptMethod = FuzzyReflection.fromClass(networkManagerClass)
|
||||
.getMethodByParameters("a", SecretKey.class);
|
||||
.getMethodByParameters("a", SecretKey.class);
|
||||
} catch (IllegalArgumentException exception) {
|
||||
// Get the new encryption method
|
||||
encryptMethod = FuzzyReflection.fromClass(networkManagerClass)
|
||||
.getMethodByParameters("a", Cipher.class, Cipher.class);
|
||||
.getMethodByParameters("a", Cipher.class, Cipher.class);
|
||||
|
||||
// Get the needed Cipher helper method (used to generate ciphers from login key)
|
||||
cipherMethod = FuzzyReflection.fromClass(ENCRYPTION_CLASS)
|
||||
.getMethodByParameters("a", int.class, Key.class);
|
||||
.getMethodByParameters("a", int.class, Key.class);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -247,15 +245,20 @@ public class VerifyResponseTask implements Runnable {
|
||||
encryptMethod.invoke(networkManager, decryptionCipher, encryptionCipher);
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
disconnect("error-kick", "Couldn't enable encryption", ex);
|
||||
disconnect("error-kick", false, "Couldn't enable encryption", ex);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private void disconnect(String reasonKey, String logMessage, Object... arguments) {
|
||||
plugin.getLog().error(logMessage, arguments);
|
||||
private void disconnect(String reasonKey, boolean debug, String logMessage, Object... arguments) {
|
||||
if (debug) {
|
||||
plugin.getLog().debug(logMessage, arguments);
|
||||
} else {
|
||||
plugin.getLog().error(logMessage, arguments);
|
||||
}
|
||||
|
||||
kickPlayer(plugin.getCore().getMessage(reasonKey));
|
||||
}
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2015-2022 games647 and contributors
|
||||
* Copyright (c) 2015-2021 <Your name and contributors>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
@@ -51,7 +51,7 @@ public class ProtocolLoginSource implements LoginSource {
|
||||
|
||||
@Override
|
||||
public InetSocketAddress getAddress() {
|
||||
return loginStartEvent.getAddress();
|
||||
return loginStartEvent.getConnection().getRawAddress();
|
||||
}
|
||||
|
||||
public PlayerLoginStartEvent getLoginStartEvent() {
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2015-2022 games647 and contributors
|
||||
* Copyright (c) 2015-2021 <Your name and contributors>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
@@ -41,6 +41,7 @@ import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
|
||||
import protocolsupport.api.events.ConnectionCloseEvent;
|
||||
import protocolsupport.api.events.PlayerLoginStartEvent;
|
||||
import protocolsupport.api.events.PlayerProfileCompleteEvent;
|
||||
@@ -52,7 +53,7 @@ public class ProtocolSupportListener extends JoinManagement<Player, CommandSende
|
||||
private final RateLimiter rateLimiter;
|
||||
|
||||
public ProtocolSupportListener(FastLoginBukkit plugin, RateLimiter rateLimiter) {
|
||||
super(plugin.getCore(), plugin.getCore().getAuthPluginHook(), plugin.getBedrockService());
|
||||
super(plugin.getCore(), plugin.getCore().getAuthPluginHook());
|
||||
|
||||
this.plugin = plugin;
|
||||
this.rateLimiter = rateLimiter;
|
||||
@@ -70,7 +71,7 @@ public class ProtocolSupportListener extends JoinManagement<Player, CommandSende
|
||||
}
|
||||
|
||||
String username = loginStartEvent.getConnection().getProfile().getName();
|
||||
InetSocketAddress address = loginStartEvent.getAddress();
|
||||
InetSocketAddress address = loginStartEvent.getConnection().getRawAddress();
|
||||
|
||||
//remove old data every time on a new login in order to keep the session only for one person
|
||||
plugin.removeSession(address);
|
||||
@@ -81,13 +82,14 @@ public class ProtocolSupportListener extends JoinManagement<Player, CommandSende
|
||||
|
||||
@EventHandler
|
||||
public void onConnectionClosed(ConnectionCloseEvent closeEvent) {
|
||||
InetSocketAddress address = closeEvent.getConnection().getAddress();
|
||||
InetSocketAddress address = closeEvent.getConnection().getRawAddress();
|
||||
plugin.removeSession(address);
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onPropertiesResolve(PlayerProfileCompleteEvent profileCompleteEvent) {
|
||||
InetSocketAddress address = profileCompleteEvent.getAddress();
|
||||
InetSocketAddress address = profileCompleteEvent.getConnection().getRawAddress();
|
||||
|
||||
BukkitLoginSession session = plugin.getSession(address);
|
||||
|
||||
if (session != null && profileCompleteEvent.getConnection().getProfile().isOnlineMode()) {
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2015-2022 games647 and contributors
|
||||
* Copyright (c) 2015-2021 <Your name and contributors>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
@@ -32,6 +32,7 @@ import com.github.games647.fastlogin.bukkit.hook.LogItHook;
|
||||
import com.github.games647.fastlogin.bukkit.hook.LoginSecurityHook;
|
||||
import com.github.games647.fastlogin.bukkit.hook.UltraAuthHook;
|
||||
import com.github.games647.fastlogin.bukkit.hook.xAuthHook;
|
||||
import com.github.games647.fastlogin.bukkit.hook.SodionAuthHook;
|
||||
import com.github.games647.fastlogin.core.hooks.AuthPlugin;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
@@ -94,8 +95,8 @@ public class DelayedAuthHook implements Runnable {
|
||||
private AuthPlugin<Player> getAuthHook() {
|
||||
try {
|
||||
List<Class<? extends AuthPlugin<Player>>> hooks = Arrays.asList(AuthMeHook.class,
|
||||
CrazyLoginHook.class, LogItHook.class, LoginSecurityHook.class, UltraAuthHook.class,
|
||||
xAuthHook.class);
|
||||
CrazyLoginHook.class, LogItHook.class, LoginSecurityHook.class,
|
||||
SodionAuthHook.class, UltraAuthHook.class, xAuthHook.class);
|
||||
|
||||
for (Class<? extends AuthPlugin<Player>> clazz : hooks) {
|
||||
String pluginName = clazz.getSimpleName();
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2015-2022 games647 and contributors
|
||||
* Copyright (c) 2015-2021 <Your name and contributors>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
@@ -49,7 +49,8 @@ public class FloodgateAuthTask extends FloodgateManagement<Player, CommandSender
|
||||
BukkitLoginSession session = new BukkitLoginSession(player.getName(), isRegistered, profile);
|
||||
|
||||
// enable auto login based on the value of 'autoLoginFloodgate' in config.yml
|
||||
session.setVerified(isAutoAuthAllowed(autoLoginFloodgate));
|
||||
session.setVerified(autoLoginFloodgate.equals("true")
|
||||
|| (autoLoginFloodgate.equals("linked") && isLinked));
|
||||
|
||||
// run login task
|
||||
Runnable forceLoginTask = new ForceLoginTask(core.getPlugin().getCore(), player, session);
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2015-2022 games647 and contributors
|
||||
* Copyright (c) 2015-2021 <Your name and contributors>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# project data for Bukkit in order to register our plugin with all it's components
|
||||
# project data for Bukkit in order to register our plugin with all it components
|
||||
# ${-} are variables from Maven (pom.xml) which will be replaced after the build
|
||||
name: ${project.parent.name}
|
||||
version: ${project.version}-${git.commit.id.abbrev}
|
||||
@@ -11,17 +11,15 @@ description: |
|
||||
website: ${project.url}
|
||||
dev-url: ${project.url}
|
||||
|
||||
# This plugin doesn't have to be transformed for compatibility with Minecraft >= 1.13
|
||||
# This plugin don't have to be transformed for compatibility with Minecraft >= 1.13
|
||||
api-version: '1.13'
|
||||
|
||||
softdepend:
|
||||
# We depend on either ProtocolLib or ProtocolSupport
|
||||
# We depend either ProtocolLib or ProtocolSupport
|
||||
- ProtocolSupport
|
||||
- ProtocolLib
|
||||
# Premium variable
|
||||
- PlaceholderAPI
|
||||
# Bedrock Player Bridge
|
||||
- Geyser-Spigot
|
||||
- floodgate
|
||||
# Auth plugins
|
||||
- AuthMe
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2015-2022 games647 and contributors
|
||||
* Copyright (c) 2015-2021 <Your name and contributors>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
@@ -36,11 +36,31 @@ import static org.hamcrest.MatcherAssert.assertThat;
|
||||
public class EncryptionUtilTest {
|
||||
|
||||
@Test
|
||||
public void testVerifyToken() {
|
||||
public void testVerifyToken() throws Exception {
|
||||
SecureRandom random = new SecureRandom();
|
||||
byte[] token = EncryptionUtil.generateVerifyToken(random);
|
||||
|
||||
assertThat(token, notNullValue());
|
||||
assertThat(token.length, is(4));
|
||||
}
|
||||
|
||||
// @Test
|
||||
// public void testDecryptSharedSecret() throws Exception {
|
||||
//
|
||||
// }
|
||||
//
|
||||
// @Test
|
||||
// public void testDecryptData() throws Exception {
|
||||
//
|
||||
// }
|
||||
|
||||
// private static SecretKey createNewSharedKey() {
|
||||
// try {
|
||||
// KeyGenerator keygenerator = KeyGenerator.getInstance("AES");
|
||||
// keygenerator.init(128);
|
||||
// return keygenerator.generateKey();
|
||||
// } catch (NoSuchAlgorithmException nosuchalgorithmexception) {
|
||||
// throw new Error(nosuchalgorithmexception);
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2015-2022 games647 and contributors
|
||||
Copyright (c) 2015-2021 <Your name and contributors>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
@@ -36,7 +36,7 @@
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
<!--This has to be in lowercase because it's used by plugin.yml-->
|
||||
<!--This have to be in lowercase because it's used by plugin.yml-->
|
||||
<artifactId>fastlogin.bungee</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
@@ -48,7 +48,7 @@
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-shade-plugin</artifactId>
|
||||
<version>3.3.0</version>
|
||||
<version>3.2.4</version>
|
||||
<configuration>
|
||||
<createDependencyReducedPom>false</createDependencyReducedPom>
|
||||
<shadedArtifactAttached>false</shadedArtifactAttached>
|
||||
@@ -57,7 +57,6 @@
|
||||
<!--Those classes are already present in BungeeCord version-->
|
||||
<exclude>net.md-5:bungeecord-config</exclude>
|
||||
<exclude>com.google.code.gson:gson</exclude>
|
||||
<exclude>com.google.guava:guava</exclude>
|
||||
</excludes>
|
||||
</artifactSet>
|
||||
<relocations>
|
||||
@@ -70,20 +69,6 @@
|
||||
<shadedPattern>fastlogin.slf4j</shadedPattern>
|
||||
</relocation>
|
||||
</relocations>
|
||||
<!-- Rename the service file too to let SLF4J api find our own relocated jdk logger -->
|
||||
<!-- Located in META-INF/services -->
|
||||
<transformers>
|
||||
<transformer implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer"/>
|
||||
</transformers>
|
||||
<filters>
|
||||
<filter>
|
||||
<artifact>*:*</artifact>
|
||||
<excludes>
|
||||
<exclude>META-INF/MANIFEST.MF</exclude>
|
||||
<exclude>**/module-info.class</exclude>
|
||||
</excludes>
|
||||
</filter>
|
||||
</filters>
|
||||
</configuration>
|
||||
<executions>
|
||||
<execution>
|
||||
@@ -103,6 +88,11 @@
|
||||
<url>https://repo.codemc.io/repository/maven-public/</url>
|
||||
</repository>
|
||||
|
||||
<repository>
|
||||
<id>nukkitx-repo</id>
|
||||
<url>https://repo.nukkitx.com/maven-snapshots/</url>
|
||||
</repository>
|
||||
|
||||
<repository>
|
||||
<id>spigotplugins-repo</id>
|
||||
<url>https://maven.gamestrike.de/mvn/</url>
|
||||
@@ -129,54 +119,25 @@
|
||||
<dependency>
|
||||
<groupId>net.md-5</groupId>
|
||||
<artifactId>bungeecord-proxy</artifactId>
|
||||
<version>1.19-R0.1-SNAPSHOT</version>
|
||||
<version>1.16-R0.5-SNAPSHOT</version>
|
||||
<scope>provided</scope>
|
||||
<!-- Use our own newer api version -->
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-api</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
|
||||
<!--Floodgate for Xbox Live Authentication-->
|
||||
<dependency>
|
||||
<groupId>org.geysermc.floodgate</groupId>
|
||||
<artifactId>api</artifactId>
|
||||
<version>${floodgate.version}</version>
|
||||
<scope>provided</scope>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>io.netty</groupId>
|
||||
<artifactId>*</artifactId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<groupId>org.geysermc.cumulus</groupId>
|
||||
<artifactId>*</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
|
||||
<!-- Bedrock player bridge -->
|
||||
<!-- Should be removed one Floodgate 2.0 gets a stable release -->
|
||||
<dependency>
|
||||
<groupId>org.geysermc</groupId>
|
||||
<artifactId>core</artifactId>
|
||||
<version>${geyser.version}</version>
|
||||
<artifactId>floodgate-bungee</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
<scope>provided</scope>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>*</groupId>
|
||||
<artifactId>*</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
|
||||
<!-- We need the API, but it was excluded above -->
|
||||
<!-- Bedrock player bridge -->
|
||||
<!-- Version 2.0 -->
|
||||
<dependency>
|
||||
<groupId>org.geysermc</groupId>
|
||||
<artifactId>geyser-api</artifactId>
|
||||
<version>${geyser.version}</version>
|
||||
<groupId>org.geysermc.floodgate</groupId>
|
||||
<artifactId>api</artifactId>
|
||||
<version>2.0-SNAPSHOT</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
@@ -201,5 +162,19 @@
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.github.Mohist-Community.SodionAuth</groupId>
|
||||
<artifactId>SodionAuth-Bungee</artifactId>
|
||||
<version>2bdfdc854b</version>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>com.github.Mohist-Community.SodionAuth</groupId>
|
||||
<artifactId>SodionAuth-Libs</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
<optional>true</optional>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2015-2022 games647 and contributors
|
||||
* Copyright (c) 2015-2021 <Your name and contributors>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2015-2022 games647 and contributors
|
||||
* Copyright (c) 2015-2021 <Your name and contributors>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2015-2022 games647 and contributors
|
||||
* Copyright (c) 2015-2021 <Your name and contributors>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
@@ -27,14 +27,12 @@ package com.github.games647.fastlogin.bungee;
|
||||
|
||||
import com.github.games647.fastlogin.bungee.hook.BungeeAuthHook;
|
||||
import com.github.games647.fastlogin.bungee.hook.BungeeCordAuthenticatorBungeeHook;
|
||||
import com.github.games647.fastlogin.bungee.hook.SodionAuthHook;
|
||||
import com.github.games647.fastlogin.bungee.listener.ConnectListener;
|
||||
import com.github.games647.fastlogin.bungee.listener.PluginMessageListener;
|
||||
import com.github.games647.fastlogin.core.AsyncScheduler;
|
||||
import com.github.games647.fastlogin.core.CommonUtil;
|
||||
import com.github.games647.fastlogin.core.hooks.AuthPlugin;
|
||||
import com.github.games647.fastlogin.core.hooks.bedrock.BedrockService;
|
||||
import com.github.games647.fastlogin.core.hooks.bedrock.FloodgateService;
|
||||
import com.github.games647.fastlogin.core.hooks.bedrock.GeyserService;
|
||||
import com.github.games647.fastlogin.core.message.ChangePremiumMessage;
|
||||
import com.github.games647.fastlogin.core.message.ChannelMessage;
|
||||
import com.github.games647.fastlogin.core.message.NamespaceKey;
|
||||
@@ -61,8 +59,6 @@ import net.md_5.bungee.api.plugin.Plugin;
|
||||
import net.md_5.bungee.api.plugin.PluginManager;
|
||||
import net.md_5.bungee.api.scheduler.GroupedThreadFactory;
|
||||
|
||||
import org.geysermc.floodgate.api.FloodgateApi;
|
||||
import org.geysermc.geyser.GeyserImpl;
|
||||
import org.slf4j.Logger;
|
||||
|
||||
/**
|
||||
@@ -74,14 +70,12 @@ public class FastLoginBungee extends Plugin implements PlatformPlugin<CommandSen
|
||||
|
||||
private FastLoginCore<ProxiedPlayer, CommandSender, FastLoginBungee> core;
|
||||
private AsyncScheduler scheduler;
|
||||
private FloodgateService floodgateService;
|
||||
private GeyserService geyserService;
|
||||
private Logger logger;
|
||||
|
||||
@Override
|
||||
public void onEnable() {
|
||||
logger = CommonUtil.initializeLoggerService(getLogger());
|
||||
scheduler = new AsyncScheduler(logger, task -> getProxy().getScheduler().runAsync(this, task));
|
||||
logger = CommonUtil.createLoggerFromJDK(getLogger());
|
||||
scheduler = new AsyncScheduler(logger, getThreadFactory());
|
||||
|
||||
core = new FastLoginCore<>(this);
|
||||
core.load();
|
||||
@@ -89,18 +83,11 @@ public class FastLoginBungee extends Plugin implements PlatformPlugin<CommandSen
|
||||
return;
|
||||
}
|
||||
|
||||
if (isPluginInstalled("floodgate")) {
|
||||
floodgateService = new FloodgateService(FloodgateApi.getInstance(), core);
|
||||
}
|
||||
|
||||
if (isPluginInstalled("Geyser-BungeeCord")) {
|
||||
geyserService = new GeyserService(GeyserImpl.getInstance(), core);
|
||||
}
|
||||
|
||||
//events
|
||||
PluginManager pluginManager = getProxy().getPluginManager();
|
||||
|
||||
ConnectListener connectListener = new ConnectListener(this, core.getRateLimiter());
|
||||
|
||||
pluginManager.registerListener(this, connectListener);
|
||||
pluginManager.registerListener(this, new PluginMessageListener(this));
|
||||
|
||||
@@ -129,7 +116,7 @@ public class FastLoginBungee extends Plugin implements PlatformPlugin<CommandSen
|
||||
private void registerHook() {
|
||||
try {
|
||||
List<Class<? extends AuthPlugin<ProxiedPlayer>>> hooks = Arrays.asList(
|
||||
BungeeAuthHook.class, BungeeCordAuthenticatorBungeeHook.class);
|
||||
BungeeAuthHook.class, BungeeCordAuthenticatorBungeeHook.class, SodionAuthHook.class);
|
||||
|
||||
for (Class<? extends AuthPlugin<ProxiedPlayer>> clazz : hooks) {
|
||||
String pluginName = clazz.getSimpleName();
|
||||
@@ -198,20 +185,4 @@ public class FastLoginBungee extends Plugin implements PlatformPlugin<CommandSen
|
||||
public boolean isPluginInstalled(String name) {
|
||||
return getProxy().getPluginManager().getPlugin(name) != null;
|
||||
}
|
||||
|
||||
public FloodgateService getFloodgateService() {
|
||||
return floodgateService;
|
||||
}
|
||||
|
||||
public GeyserService getGeyserService() {
|
||||
return geyserService;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BedrockService<?> getBedrockService() {
|
||||
if (floodgateService != null) {
|
||||
return floodgateService;
|
||||
}
|
||||
return geyserService;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2015-2022 games647 and contributors
|
||||
* Copyright (c) 2015-2021 <Your name and contributors>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2015-2022 games647 and contributors
|
||||
* Copyright (c) 2015-2021 <Your name and contributors>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2015-2022 games647 and contributors
|
||||
* Copyright (c) 2015-2021 <Your name and contributors>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
@@ -27,7 +27,6 @@ package com.github.games647.fastlogin.bungee.event;
|
||||
|
||||
import com.github.games647.fastlogin.core.StoredProfile;
|
||||
import com.github.games647.fastlogin.core.shared.event.FastLoginPremiumToggleEvent;
|
||||
|
||||
import net.md_5.bungee.api.plugin.Event;
|
||||
|
||||
public class BungeeFastLoginPremiumToggleEvent extends Event implements FastLoginPremiumToggleEvent {
|
||||
@@ -46,7 +45,7 @@ public class BungeeFastLoginPremiumToggleEvent extends Event implements FastLogi
|
||||
}
|
||||
|
||||
@Override
|
||||
public PremiumToggleReason getReason() {
|
||||
public FastLoginPremiumToggleEvent.PremiumToggleReason getReason() {
|
||||
return reason;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2015-2022 games647 and contributors
|
||||
* Copyright (c) 2015-2021 <Your name and contributors>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2015-2022 games647 and contributors
|
||||
* Copyright (c) 2015-2021 <Your name and contributors>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
@@ -25,23 +25,22 @@
|
||||
*/
|
||||
package com.github.games647.fastlogin.bungee.hook;
|
||||
|
||||
import java.sql.SQLException;
|
||||
|
||||
import com.github.games647.fastlogin.bungee.FastLoginBungee;
|
||||
import com.github.games647.fastlogin.core.hooks.AuthPlugin;
|
||||
|
||||
import de.xxschrandxx.bca.bungee.BungeeCordAuthenticatorBungee;
|
||||
import de.xxschrandxx.bca.bungee.api.BungeeCordAuthenticatorBungeeAPI;
|
||||
|
||||
import java.sql.SQLException;
|
||||
import java.util.logging.Level;
|
||||
|
||||
import net.md_5.bungee.api.connection.ProxiedPlayer;
|
||||
|
||||
/**
|
||||
* GitHub:
|
||||
* https://github.com/xXSchrandXx/SpigotPlugins/tree/master/BungeeCordAuthenticator
|
||||
* <p>
|
||||
*
|
||||
* Project page:
|
||||
* <p>
|
||||
*
|
||||
* Spigot: https://www.spigotmc.org/resources/bungeecordauthenticator.87669/
|
||||
*/
|
||||
public class BungeeCordAuthenticatorBungeeHook implements AuthPlugin<ProxiedPlayer> {
|
||||
@@ -50,7 +49,7 @@ public class BungeeCordAuthenticatorBungeeHook implements AuthPlugin<ProxiedPlay
|
||||
|
||||
public BungeeCordAuthenticatorBungeeHook(FastLoginBungee plugin) {
|
||||
api = ((BungeeCordAuthenticatorBungee) plugin.getProxy().getPluginManager()
|
||||
.getPlugin("BungeeCordAuthenticatorBungee")).getAPI();
|
||||
.getPlugin("BungeeCordAuthenticatorBungee")).getAPI();
|
||||
plugin.getLog().info("BungeeCordAuthenticatorHook | Hooked successful!");
|
||||
}
|
||||
|
||||
@@ -58,24 +57,25 @@ public class BungeeCordAuthenticatorBungeeHook implements AuthPlugin<ProxiedPlay
|
||||
public boolean forceLogin(ProxiedPlayer player) {
|
||||
if (api.isAuthenticated(player)) {
|
||||
return true;
|
||||
} else {
|
||||
try {
|
||||
api.setAuthenticated(player);
|
||||
}
|
||||
catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
try {
|
||||
api.setAuthenticated(player);
|
||||
} catch (SQLException sqlEx) {
|
||||
api.getLogger().log(Level.WARNING, "Failed to force login", sqlEx);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isRegistered(String playerName) {
|
||||
try {
|
||||
return api.getSQL().checkPlayerEntry(playerName);
|
||||
} catch (SQLException sqlEx) {
|
||||
api.getLogger().log(Level.WARNING, "Failed to check registration", sqlEx);
|
||||
}
|
||||
catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -84,8 +84,9 @@ public class BungeeCordAuthenticatorBungeeHook implements AuthPlugin<ProxiedPlay
|
||||
public boolean forceRegister(ProxiedPlayer player, String password) {
|
||||
try {
|
||||
return api.createPlayerEntry(player, password);
|
||||
} catch (SQLException sqlEx) {
|
||||
api.getLogger().log(Level.WARNING, "Failed to force register", sqlEx);
|
||||
}
|
||||
catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2015-2021 <Your name and contributors>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
package com.github.games647.fastlogin.bungee.hook;
|
||||
|
||||
import com.github.games647.fastlogin.bungee.FastLoginBungee;
|
||||
import com.github.games647.fastlogin.core.hooks.AuthPlugin;
|
||||
import net.md_5.bungee.api.connection.ProxiedPlayer;
|
||||
import red.mohist.sodionauth.bungee.implementation.BungeePlayer;
|
||||
import red.mohist.sodionauth.core.SodionAuthApi;
|
||||
import red.mohist.sodionauth.core.exception.AuthenticatedException;
|
||||
|
||||
/**
|
||||
* GitHub: https://github.com/Mohist-Community/SodionAuth
|
||||
* <p>
|
||||
* Project page: https://gitea.e-loli.com/SodionAuth/SodionAuth
|
||||
* <p>
|
||||
* Bukkit: Unknown
|
||||
* <p>
|
||||
* Spigot: https://www.spigotmc.org/resources/sodionauth.76944/
|
||||
*/
|
||||
public class SodionAuthHook implements AuthPlugin<ProxiedPlayer> {
|
||||
|
||||
private final FastLoginBungee plugin;
|
||||
|
||||
public SodionAuthHook(FastLoginBungee plugin) {
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean forceLogin(ProxiedPlayer player) {
|
||||
try {
|
||||
SodionAuthApi.login(new BungeePlayer(player));
|
||||
} catch (AuthenticatedException e) {
|
||||
plugin.getLog().warn(ALREADY_AUTHENTICATED, player);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean forceRegister(ProxiedPlayer player, String password) {
|
||||
try{
|
||||
return SodionAuthApi.register(new BungeePlayer(player), password);
|
||||
} catch (UnsupportedOperationException e){
|
||||
plugin.getLog().warn("Currently SodionAuth is not accepting forceRegister, " +
|
||||
"It may be caused by unsupported AuthBackend");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isRegistered(String playerName) {
|
||||
return SodionAuthApi.isRegistered(playerName);
|
||||
}
|
||||
}
|
||||
@@ -3,7 +3,7 @@
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2015-2022 games647 and contributors
|
||||
* Copyright (c) 2015-2021 <Your name and contributors>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
@@ -33,7 +33,6 @@ import com.github.games647.fastlogin.bungee.task.FloodgateAuthTask;
|
||||
import com.github.games647.fastlogin.bungee.task.ForceLoginTask;
|
||||
import com.github.games647.fastlogin.core.RateLimiter;
|
||||
import com.github.games647.fastlogin.core.StoredProfile;
|
||||
import com.github.games647.fastlogin.core.hooks.bedrock.FloodgateService;
|
||||
import com.github.games647.fastlogin.core.shared.LoginSession;
|
||||
import com.google.common.base.Throwables;
|
||||
|
||||
@@ -53,10 +52,11 @@ import net.md_5.bungee.api.event.ServerConnectedEvent;
|
||||
import net.md_5.bungee.api.plugin.Listener;
|
||||
import net.md_5.bungee.connection.InitialHandler;
|
||||
import net.md_5.bungee.connection.LoginResult;
|
||||
import net.md_5.bungee.connection.LoginResult.Property;
|
||||
import net.md_5.bungee.event.EventHandler;
|
||||
import net.md_5.bungee.event.EventPriority;
|
||||
import net.md_5.bungee.protocol.Property;
|
||||
|
||||
import org.geysermc.floodgate.api.FloodgateApi;
|
||||
import org.geysermc.floodgate.api.player.FloodgatePlayer;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
@@ -80,12 +80,14 @@ public class ConnectListener implements Listener {
|
||||
Field uuidField = InitialHandler.class.getDeclaredField(UUID_FIELD_NAME);
|
||||
uuidField.setAccessible(true);
|
||||
setHandle = lookup.unreflectSetter(uuidField);
|
||||
} catch (ReflectiveOperationException reflectiveOperationException) {
|
||||
} catch (ClassNotFoundException classNotFoundException) {
|
||||
Logger logger = LoggerFactory.getLogger(ConnectListener.class);
|
||||
logger.error(
|
||||
"Cannot find Bungee initial handler; Disabling premium UUID and skin won't work.",
|
||||
reflectiveOperationException
|
||||
classNotFoundException
|
||||
);
|
||||
} catch (ReflectiveOperationException reflectiveOperationException) {
|
||||
reflectiveOperationException.printStackTrace();
|
||||
}
|
||||
|
||||
uniqueIdSetter = setHandle;
|
||||
@@ -159,8 +161,8 @@ public class ConnectListener implements Listener {
|
||||
|
||||
private void setOfflineId(InitialHandler connection, String username) {
|
||||
try {
|
||||
UUID oldPremiumId = connection.getUniqueId();
|
||||
UUID offlineUUID = UUIDAdapter.generateOfflineId(username);
|
||||
final UUID oldPremiumId = connection.getUniqueId();
|
||||
final UUID offlineUUID = UUIDAdapter.generateOfflineId(username);
|
||||
|
||||
// BungeeCord only allows setting the UUID in PreLogin events and before requesting online mode
|
||||
// However if online mode is requested, it will override previous values
|
||||
@@ -172,7 +174,7 @@ public class ConnectListener implements Listener {
|
||||
} catch (Exception ex) {
|
||||
plugin.getLog().error("Failed to set offline uuid of {}", username, ex);
|
||||
} catch (Throwable throwable) {
|
||||
// throw remaining exceptions like out of memory that we shouldn't handle ourselves
|
||||
// throw remaining exceptions like outofmemory that we shouldn't handle ourself
|
||||
Throwables.throwIfUnchecked(throwable);
|
||||
}
|
||||
}
|
||||
@@ -182,9 +184,8 @@ public class ConnectListener implements Listener {
|
||||
ProxiedPlayer player = serverConnectedEvent.getPlayer();
|
||||
Server server = serverConnectedEvent.getServer();
|
||||
|
||||
FloodgateService floodgateService = plugin.getFloodgateService();
|
||||
if (floodgateService != null) {
|
||||
FloodgatePlayer floodgatePlayer = floodgateService.getBedrockPlayer(player.getUniqueId());
|
||||
if (plugin.isPluginInstalled("floodgate")) {
|
||||
FloodgatePlayer floodgatePlayer = FloodgateApi.getInstance().getPlayer(player.getUniqueId());
|
||||
if (floodgatePlayer != null) {
|
||||
Runnable floodgateAuthTask = new FloodgateAuthTask(plugin.getCore(), player, floodgatePlayer, server);
|
||||
plugin.getScheduler().runAsync(floodgateAuthTask);
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2015-2022 games647 and contributors
|
||||
* Copyright (c) 2015-2021 <Your name and contributors>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
@@ -29,7 +29,6 @@ import com.github.games647.fastlogin.bungee.BungeeLoginSession;
|
||||
import com.github.games647.fastlogin.bungee.FastLoginBungee;
|
||||
import com.github.games647.fastlogin.bungee.task.AsyncToggleMessage;
|
||||
import com.github.games647.fastlogin.core.StoredProfile;
|
||||
import com.github.games647.fastlogin.core.hooks.bedrock.FloodgateService;
|
||||
import com.github.games647.fastlogin.core.message.ChangePremiumMessage;
|
||||
import com.github.games647.fastlogin.core.message.NamespaceKey;
|
||||
import com.github.games647.fastlogin.core.message.SuccessMessage;
|
||||
@@ -69,7 +68,7 @@ public class PluginMessageListener implements Listener {
|
||||
}
|
||||
|
||||
//the client shouldn't be able to read the messages in order to know something about server internal states
|
||||
//moreover the client shouldn't be able to fake a running premium check by sending the result message
|
||||
//moreover the client shouldn't be able fake a running premium check by sending the result message
|
||||
pluginMessageEvent.setCancelled(true);
|
||||
|
||||
if (!(pluginMessageEvent.getSender() instanceof Server)) {
|
||||
@@ -116,15 +115,7 @@ public class PluginMessageListener implements Listener {
|
||||
}
|
||||
|
||||
private void onSuccessMessage(ProxiedPlayer forPlayer) {
|
||||
boolean shouldPersist = forPlayer.getPendingConnection().isOnlineMode();
|
||||
|
||||
FloodgateService floodgateService = plugin.getFloodgateService();
|
||||
if (!shouldPersist && floodgateService != null) {
|
||||
// always save floodgate players to lock this username
|
||||
shouldPersist = floodgateService.isBedrockPlayer(forPlayer.getUniqueId());
|
||||
}
|
||||
|
||||
if (shouldPersist) {
|
||||
if (forPlayer.getPendingConnection().isOnlineMode()) {
|
||||
//bukkit module successfully received and force logged in the user
|
||||
//update only on success to prevent corrupt data
|
||||
BungeeLoginSession loginSession = plugin.getSession().get(forPlayer.getPendingConnection());
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2015-2022 games647 and contributors
|
||||
* Copyright (c) 2015-2021 <Your name and contributors>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
@@ -49,7 +49,7 @@ public class AsyncPremiumCheck extends JoinManagement<ProxiedPlayer, CommandSend
|
||||
|
||||
public AsyncPremiumCheck(FastLoginBungee plugin, PreLoginEvent preLoginEvent, PendingConnection connection,
|
||||
String username) {
|
||||
super(plugin.getCore(), plugin.getCore().getAuthPluginHook(), plugin.getBedrockService());
|
||||
super(plugin.getCore(), plugin.getCore().getAuthPluginHook());
|
||||
|
||||
this.plugin = plugin;
|
||||
this.preLoginEvent = preLoginEvent;
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2015-2022 games647 and contributors
|
||||
* Copyright (c) 2015-2021 <Your name and contributors>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2015-2022 games647 and contributors
|
||||
* Copyright (c) 2015-2021 <Your name and contributors>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
@@ -53,11 +53,14 @@ public class FloodgateAuthTask
|
||||
@Override
|
||||
protected void startLogin() {
|
||||
BungeeLoginSession session = new BungeeLoginSession(player.getName(), isRegistered, profile);
|
||||
core.getPlugin().getSession().put(player.getPendingConnection(), session);
|
||||
|
||||
// enable auto login based on the value of 'autoLoginFloodgate' in config.yml
|
||||
boolean forcedOnlineMode = autoLoginFloodgate.equals("true")
|
||||
|| (autoLoginFloodgate.equals("linked") && isLinked);
|
||||
|
||||
// run login task
|
||||
Runnable forceLoginTask = new ForceLoginTask(core.getPlugin().getCore(), player, server, session,
|
||||
isAutoAuthAllowed(autoLoginFloodgate));
|
||||
forcedOnlineMode);
|
||||
core.getPlugin().getScheduler().runAsync(forceLoginTask);
|
||||
}
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2015-2022 games647 and contributors
|
||||
* Copyright (c) 2015-2021 <Your name and contributors>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
@@ -50,7 +50,7 @@ public class ForceLoginTask
|
||||
private final Server server;
|
||||
|
||||
//treat player as if they had a premium account, even when they don't
|
||||
//use for Floodgate auto login/register
|
||||
//used for Floodgate auto login/register
|
||||
private final boolean forcedOnlineMode;
|
||||
|
||||
public ForceLoginTask(FastLoginCore<ProxiedPlayer, CommandSender, FastLoginBungee> core,
|
||||
|
||||
@@ -13,9 +13,6 @@ softDepends:
|
||||
- BungeeAuth
|
||||
- BungeeCordAuthenticatorBungee
|
||||
- SodionAuth
|
||||
# Bedrock Player Bridge
|
||||
- Geyser-BungeeCord
|
||||
- floodgate
|
||||
|
||||
description: |
|
||||
${project.description}
|
||||
|
||||
93
core/pom.xml
93
core/pom.xml
@@ -4,7 +4,7 @@
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2015-2022 games647 and contributors
|
||||
Copyright (c) 2015-2021 <Your name and contributors>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
@@ -52,17 +52,11 @@
|
||||
<repository>
|
||||
<id>codemc-repo</id>
|
||||
<url>https://repo.codemc.io/repository/maven-public/</url>
|
||||
<snapshots>
|
||||
<enabled>false</enabled>
|
||||
</snapshots>
|
||||
</repository>
|
||||
<!-- Floodgate -->
|
||||
<repository>
|
||||
<id>opencollab-snapshot</id>
|
||||
<url>https://repo.opencollab.dev/maven-snapshots/</url>
|
||||
<releases>
|
||||
<enabled>false</enabled>
|
||||
</releases>
|
||||
<id>nukkitx-snapshot</id>
|
||||
<url>https://repo.nukkitx.com/maven-snapshots/</url>
|
||||
</repository>
|
||||
</repositories>
|
||||
|
||||
@@ -74,28 +68,20 @@
|
||||
<groupId>com.zaxxer</groupId>
|
||||
<artifactId>HikariCP</artifactId>
|
||||
<version>4.0.3</version>
|
||||
<exclusions>
|
||||
<!-- HikariCP uses an old version of this API that has a typo in the service interface -->
|
||||
<!-- We will use the api provided by the jdk14 dependency -->
|
||||
<exclusion>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-api</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
|
||||
<!--Logging framework implements slf4j which is required by hikari-->
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-jdk14</artifactId>
|
||||
<version>2.0.0-alpha7</version>
|
||||
<version>1.7.32</version>
|
||||
</dependency>
|
||||
|
||||
<!-- snakeyaml is present in Bungee, Spigot, Cauldron, so we could use this independent implementation -->
|
||||
<!-- snakeyaml is present in Bungee, Spigot, Cauldron and so we could use this independent implementation -->
|
||||
<dependency>
|
||||
<groupId>net.md-5</groupId>
|
||||
<artifactId>bungeecord-config</artifactId>
|
||||
<version>1.16-R0.4</version>
|
||||
<version>1.12-SNAPSHOT</version>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>*</groupId>
|
||||
@@ -108,39 +94,7 @@
|
||||
<dependency>
|
||||
<groupId>org.geysermc.floodgate</groupId>
|
||||
<artifactId>api</artifactId>
|
||||
<version>${floodgate.version}</version>
|
||||
<scope>provided</scope>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>io.netty</groupId>
|
||||
<artifactId>*</artifactId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<groupId>org.geysermc.cumulus</groupId>
|
||||
<artifactId>*</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
|
||||
<!-- Bedrock player bridge -->
|
||||
<dependency>
|
||||
<groupId>org.geysermc</groupId>
|
||||
<artifactId>core</artifactId>
|
||||
<version>${geyser.version}</version>
|
||||
<scope>provided</scope>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>*</groupId>
|
||||
<artifactId>*</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
|
||||
<!-- We need the API, but it was excluded above -->
|
||||
<dependency>
|
||||
<groupId>org.geysermc</groupId>
|
||||
<artifactId>geyser-api</artifactId>
|
||||
<version>${geyser.version}</version>
|
||||
<version>2.0-SNAPSHOT</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
@@ -148,44 +102,21 @@
|
||||
<dependency>
|
||||
<groupId>com.github.games647</groupId>
|
||||
<artifactId>craftapi</artifactId>
|
||||
<version>0.5.3</version>
|
||||
<version>0.4</version>
|
||||
</dependency>
|
||||
|
||||
<!-- APIs we can use because they are available in all platforms (Spigot, Bungee, Velocity) -->
|
||||
<!-- APIs we can use because they are available in all platforms (Spigot, Bungee) -->
|
||||
<dependency>
|
||||
<groupId>com.google.guava</groupId>
|
||||
<artifactId>guava</artifactId>
|
||||
<!-- Old version for velocity -->
|
||||
<version>25.1-jre</version>
|
||||
<!-- Exclude compile time dependencies not marked as such on upstream -->
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>com.google.code.findbugs</groupId>
|
||||
<artifactId>jsr305</artifactId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<groupId>org.checkerframework</groupId>
|
||||
<artifactId>checker-qual</artifactId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<groupId>com.google.errorprone</groupId>
|
||||
<artifactId>error_prone_annotations</artifactId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<groupId>com.google.j2objc</groupId>
|
||||
<artifactId>j2objc-annotations</artifactId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<groupId>org.codehaus.mojo</groupId>
|
||||
<artifactId>animal-sniffer-annotations</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
<version>17.0</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.google.code.gson</groupId>
|
||||
<artifactId>gson</artifactId>
|
||||
<version>2.9.0</version>
|
||||
<version>2.2.4</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2015-2022 games647 and contributors
|
||||
* Copyright (c) 2015-2021 <Your name and contributors>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
@@ -25,16 +25,21 @@
|
||||
*/
|
||||
package com.github.games647.fastlogin.core;
|
||||
|
||||
import com.google.common.util.concurrent.MoreExecutors;
|
||||
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.LinkedBlockingQueue;
|
||||
import java.util.concurrent.ThreadFactory;
|
||||
import java.util.concurrent.ThreadPoolExecutor;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
|
||||
/**
|
||||
* This limits the number of threads that are used at maximum. Thread creation can be very heavy for the CPU and
|
||||
* context switching between threads too. However, we need many threads for blocking HTTP and database calls.
|
||||
* Nevertheless, this number can be further limited, because the number of actually working database threads
|
||||
* context switching between threads too. However we need many threads for blocking HTTP and database calls.
|
||||
* Nevertheless this number can be further limited, because the number of actually working database threads
|
||||
* is limited by the size of our database pool. The goal is to separate concerns into processing and blocking only
|
||||
* threads.
|
||||
*/
|
||||
@@ -48,9 +53,7 @@ public class AsyncScheduler {
|
||||
// 30 threads are still too many - the optimal solution is to separate into processing and blocking threads
|
||||
// where processing threads could only be max number of cores while blocking threads could be minimized using
|
||||
// non-blocking I/O and a single event executor
|
||||
private final Executor processingPool;
|
||||
|
||||
private final AtomicInteger currentlyRunning = new AtomicInteger();
|
||||
private final ExecutorService processingPool;
|
||||
|
||||
/*
|
||||
private final ExecutorService databaseExecutor = new ThreadPoolExecutor(1, 10,
|
||||
@@ -58,27 +61,34 @@ public class AsyncScheduler {
|
||||
new LinkedBlockingQueue<>(MAX_CAPACITY));
|
||||
*/
|
||||
|
||||
public AsyncScheduler(Logger logger, Executor processingPool) {
|
||||
public AsyncScheduler(Logger logger, ThreadFactory threadFactory) {
|
||||
this.logger = logger;
|
||||
this.processingPool = processingPool;
|
||||
processingPool = new ThreadPoolExecutor(6, 32,
|
||||
60L, TimeUnit.SECONDS,
|
||||
new LinkedBlockingQueue<>(MAX_CAPACITY), threadFactory);
|
||||
}
|
||||
|
||||
/*
|
||||
public <R> CompletableFuture<R> runDatabaseTask(Supplier<R> databaseTask) {
|
||||
return CompletableFuture.supplyAsync(databaseTask, databaseExecutor)
|
||||
.exceptionally(error -> {
|
||||
logger.warn("Error occurred on thread pool", error);
|
||||
return null;
|
||||
})
|
||||
// change context to the processing pool
|
||||
.thenApplyAsync(r -> r, processingPool);
|
||||
}
|
||||
*/
|
||||
|
||||
public CompletableFuture<Void> runAsync(Runnable task) {
|
||||
return CompletableFuture.runAsync(() -> {
|
||||
currentlyRunning.incrementAndGet();
|
||||
try {
|
||||
task.run();
|
||||
} finally {
|
||||
currentlyRunning.getAndDecrement();
|
||||
}
|
||||
}, processingPool).exceptionally(error -> {
|
||||
return CompletableFuture.runAsync(task, processingPool).exceptionally(error -> {
|
||||
logger.warn("Error occurred on thread pool", error);
|
||||
return null;
|
||||
});
|
||||
}
|
||||
|
||||
public void shutdown() {
|
||||
// MoreExecutors.shutdownAndAwaitTermination(processingPool, 1, TimeUnit.MINUTES);
|
||||
MoreExecutors.shutdownAndAwaitTermination(processingPool, 1, TimeUnit.MINUTES);
|
||||
//MoreExecutors.shutdownAndAwaitTermination(databaseExecutor, 1, TimeUnit.MINUTES);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2015-2022 games647 and contributors
|
||||
* Copyright (c) 2015-2021 <Your name and contributors>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
@@ -23,10 +23,9 @@
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
package com.github.games647.fastlogin.core.storage;
|
||||
package com.github.games647.fastlogin.core;
|
||||
|
||||
import com.github.games647.craftapi.UUIDAdapter;
|
||||
import com.github.games647.fastlogin.core.StoredProfile;
|
||||
import com.github.games647.fastlogin.core.shared.FastLoginCore;
|
||||
import com.zaxxer.hikari.HikariConfig;
|
||||
import com.zaxxer.hikari.HikariDataSource;
|
||||
@@ -43,34 +42,23 @@ import java.util.concurrent.ThreadFactory;
|
||||
|
||||
import static java.sql.Statement.RETURN_GENERATED_KEYS;
|
||||
|
||||
public abstract class SQLStorage implements AuthStorage {
|
||||
public class AuthStorage {
|
||||
|
||||
private static final String JDBC_PROTOCOL = "jdbc:";
|
||||
private static final String PREMIUM_TABLE = "premium";
|
||||
|
||||
protected static final String PREMIUM_TABLE = "premium";
|
||||
protected static final String CREATE_TABLE_STMT = "CREATE TABLE IF NOT EXISTS `" + PREMIUM_TABLE + "` ("
|
||||
+ "`UserID` INTEGER PRIMARY KEY AUTO_INCREMENT, "
|
||||
+ "`UUID` CHAR(36), "
|
||||
+ "`Name` VARCHAR(16) NOT NULL, "
|
||||
+ "`Premium` BOOLEAN NOT NULL, "
|
||||
+ "`LastIp` VARCHAR(255) NOT NULL, "
|
||||
+ "`LastLogin` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, "
|
||||
//the premium shouldn't steal the cracked account by changing the name
|
||||
+ "UNIQUE (`Name`) "
|
||||
+ ')';
|
||||
|
||||
protected static final String LOAD_BY_NAME = "SELECT * FROM `" + PREMIUM_TABLE + "` WHERE `Name`=? LIMIT 1";
|
||||
protected static final String LOAD_BY_UUID = "SELECT * FROM `" + PREMIUM_TABLE + "` WHERE `UUID`=? LIMIT 1";
|
||||
protected static final String INSERT_PROFILE = "INSERT INTO `" + PREMIUM_TABLE
|
||||
private static final String LOAD_BY_NAME = "SELECT * FROM `" + PREMIUM_TABLE + "` WHERE `Name`=? LIMIT 1";
|
||||
private static final String LOAD_BY_UUID = "SELECT * FROM `" + PREMIUM_TABLE + "` WHERE `UUID`=? LIMIT 1";
|
||||
private static final String INSERT_PROFILE = "INSERT INTO `" + PREMIUM_TABLE
|
||||
+ "` (`UUID`, `Name`, `Premium`, `LastIp`) " + "VALUES (?, ?, ?, ?) ";
|
||||
// limit not necessary here, because it's unique
|
||||
protected static final String UPDATE_PROFILE = "UPDATE `" + PREMIUM_TABLE
|
||||
private static final String UPDATE_PROFILE = "UPDATE `" + PREMIUM_TABLE
|
||||
+ "` SET `UUID`=?, `Name`=?, `Premium`=?, `LastIp`=?, `LastLogin`=CURRENT_TIMESTAMP WHERE `UserID`=?";
|
||||
|
||||
protected final FastLoginCore<?, ?, ?> core;
|
||||
protected final HikariDataSource dataSource;
|
||||
private final FastLoginCore<?, ?, ?> core;
|
||||
private final HikariDataSource dataSource;
|
||||
|
||||
public SQLStorage(FastLoginCore<?, ?, ?> core, String jdbcURL, HikariConfig config) {
|
||||
public AuthStorage(FastLoginCore<?, ?, ?> core, String host, int port, String databasePath,
|
||||
HikariConfig config, boolean useSSL) {
|
||||
this.core = core;
|
||||
config.setPoolName(core.getPlugin().getName());
|
||||
|
||||
@@ -79,7 +67,68 @@ public abstract class SQLStorage implements AuthStorage {
|
||||
config.setThreadFactory(platformThreadFactory);
|
||||
}
|
||||
|
||||
config.setJdbcUrl(JDBC_PROTOCOL + jdbcURL);
|
||||
String jdbcUrl = "jdbc:";
|
||||
if (config.getDriverClassName().contains("sqlite")) {
|
||||
String pluginFolder = core.getPlugin().getPluginFolder().toAbsolutePath().toString();
|
||||
databasePath = databasePath.replace("{pluginDir}", pluginFolder);
|
||||
|
||||
jdbcUrl += "sqlite://" + databasePath;
|
||||
config.setConnectionTestQuery("SELECT 1");
|
||||
config.setMaximumPoolSize(1);
|
||||
|
||||
//a try to fix https://www.spigotmc.org/threads/fastlogin.101192/page-26#post-1874647
|
||||
// format strings retrieved by the timestamp column to match them from MySQL
|
||||
config.addDataSourceProperty("date_string_format", "yyyy-MM-dd HH:mm:ss");
|
||||
|
||||
// TODO: test first for compatibility
|
||||
// config.addDataSourceProperty("date_precision", "seconds");
|
||||
} else {
|
||||
jdbcUrl += "mysql://" + host + ':' + port + '/' + databasePath;
|
||||
|
||||
// Require SSL on the server if requested in config - this will also verify certificate
|
||||
// Those values are deprecated in favor of sslMode
|
||||
config.addDataSourceProperty("useSSL", useSSL);
|
||||
config.addDataSourceProperty("requireSSL", useSSL);
|
||||
|
||||
// prefer encrypted if possible
|
||||
config.addDataSourceProperty("sslMode", "PREFERRED");
|
||||
|
||||
// adding paranoid hides hostname, username, version and so
|
||||
// could be useful for hiding server details
|
||||
config.addDataSourceProperty("paranoid", true);
|
||||
|
||||
// enable MySQL specific optimizations
|
||||
// disabled by default - will return the same prepared statement instance
|
||||
config.addDataSourceProperty("cachePrepStmts", true);
|
||||
// default prepStmtCacheSize 25 - amount of cached statements
|
||||
config.addDataSourceProperty("prepStmtCacheSize", 250);
|
||||
// default prepStmtCacheSqlLimit 256 - length of SQL
|
||||
config.addDataSourceProperty("prepStmtCacheSqlLimit", 2048);
|
||||
// default false - available in newer versions caches the statements server-side
|
||||
config.addDataSourceProperty("useServerPrepStmts", true);
|
||||
// default false - prefer use of local values for autocommit and
|
||||
// transaction isolation (alwaysSendSetIsolation) should only be enabled if always use the set* methods
|
||||
// instead of raw SQL
|
||||
// https://forums.mysql.com/read.php?39,626495,626512
|
||||
config.addDataSourceProperty("useLocalSessionState", true);
|
||||
// rewrite batched statements to a single statement, adding them behind each other
|
||||
// only useful for addBatch statements and inserts
|
||||
config.addDataSourceProperty("rewriteBatchedStatements", true);
|
||||
// cache result metadata
|
||||
config.addDataSourceProperty("cacheResultSetMetadata", true);
|
||||
// cache results of show variables and collation per URL
|
||||
config.addDataSourceProperty("cacheServerConfiguration", true);
|
||||
// default false - set auto commit only if not matching
|
||||
config.addDataSourceProperty("elideSetAutoCommits", true);
|
||||
|
||||
// default true - internal timers for idle calculation -> removes System.getCurrentTimeMillis call per query
|
||||
// Some platforms are slow on this and it could affect the throughput about 3% according to MySQL
|
||||
// performance gems presentation
|
||||
// In our case it can be useful to see the time in error messages
|
||||
// config.addDataSourceProperty("maintainTimeStats", false);
|
||||
}
|
||||
|
||||
config.setJdbcUrl(jdbcUrl);
|
||||
this.dataSource = new HikariDataSource(config);
|
||||
}
|
||||
|
||||
@@ -87,15 +136,28 @@ public abstract class SQLStorage implements AuthStorage {
|
||||
// choose surrogate PK(ID), because UUID can be null for offline players
|
||||
// if UUID is always Premium UUID we would have to update offline player entries on insert
|
||||
// name cannot be PK, because it can be changed for premium players
|
||||
String createDataStmt = "CREATE TABLE IF NOT EXISTS `" + PREMIUM_TABLE + "` ("
|
||||
+ "`UserID` INTEGER PRIMARY KEY AUTO_INCREMENT, "
|
||||
+ "`UUID` CHAR(36), "
|
||||
+ "`Name` VARCHAR(16) NOT NULL, "
|
||||
+ "`Premium` BOOLEAN NOT NULL, "
|
||||
+ "`LastIp` VARCHAR(255) NOT NULL, "
|
||||
+ "`LastLogin` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, "
|
||||
//the premium shouldn't steal the cracked account by changing the name
|
||||
+ "UNIQUE (`Name`) "
|
||||
+ ')';
|
||||
|
||||
if (dataSource.getJdbcUrl().contains("sqlite")) {
|
||||
createDataStmt = createDataStmt.replace("AUTO_INCREMENT", "AUTOINCREMENT");
|
||||
}
|
||||
|
||||
//todo: add unique uuid index usage
|
||||
try (Connection con = dataSource.getConnection();
|
||||
Statement createStmt = con.createStatement()) {
|
||||
createStmt.executeUpdate(CREATE_TABLE_STMT);
|
||||
createStmt.executeUpdate(createDataStmt);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public StoredProfile loadProfile(String name) {
|
||||
try (Connection con = dataSource.getConnection();
|
||||
PreparedStatement loadStmt = con.prepareStatement(LOAD_BY_NAME)
|
||||
@@ -112,7 +174,6 @@ public abstract class SQLStorage implements AuthStorage {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public StoredProfile loadProfile(UUID uuid) {
|
||||
try (Connection con = dataSource.getConnection();
|
||||
PreparedStatement loadStmt = con.prepareStatement(LOAD_BY_UUID)) {
|
||||
@@ -144,7 +205,6 @@ public abstract class SQLStorage implements AuthStorage {
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void save(StoredProfile playerProfile) {
|
||||
try (Connection con = dataSource.getConnection()) {
|
||||
String uuid = playerProfile.getOptId().map(UUIDAdapter::toMojangId).orElse(null);
|
||||
@@ -185,7 +245,6 @@ public abstract class SQLStorage implements AuthStorage {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
dataSource.close();
|
||||
}
|
||||
@@ -3,7 +3,7 @@
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2015-2022 games647 and contributors
|
||||
* Copyright (c) 2015-2021 <Your name and contributors>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
@@ -35,7 +35,7 @@ import java.util.logging.Level;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.slf4j.jul.JDK14LoggerAdapter;
|
||||
import org.slf4j.impl.JDK14LoggerAdapter;
|
||||
|
||||
public class CommonUtil {
|
||||
|
||||
@@ -70,27 +70,7 @@ public class CommonUtil {
|
||||
return new String(chars);
|
||||
}
|
||||
|
||||
/**
|
||||
* This creates a SLF4J logger. In the process it initializes the SLF4J service provider. This method looks
|
||||
* for the provider in the plugin jar instead of in the server jar when creating a Logger. The provider is only
|
||||
* initialized once, so this method should be called early.
|
||||
*
|
||||
* The provider is bound to the service class `SLF4JServiceProvider`. Relocating this class makes it available
|
||||
* for exclusive own usage. Other dependencies will use the relocated service too, and therefore will find the
|
||||
* initialized provider.
|
||||
*
|
||||
* @param parent JDK logger
|
||||
* @return slf4j logger
|
||||
*/
|
||||
public static Logger initializeLoggerService(java.util.logging.Logger parent) {
|
||||
// set the class loader to the plugin one to find our own SLF4J provider in the plugin jar and not in the global
|
||||
ClassLoader oldLoader = Thread.currentThread().getContextClassLoader();
|
||||
|
||||
ClassLoader pluginLoader = CommonUtil.class.getClassLoader();
|
||||
Thread.currentThread().setContextClassLoader(pluginLoader);
|
||||
|
||||
// Trigger provider search
|
||||
LoggerFactory.getLogger(parent.getName()).info("Initialize logging service");
|
||||
public static Logger createLoggerFromJDK(java.util.logging.Logger parent) {
|
||||
try {
|
||||
parent.setLevel(Level.ALL);
|
||||
|
||||
@@ -102,9 +82,6 @@ public class CommonUtil {
|
||||
parent.log(Level.WARNING, "Cannot create slf4j logging adapter", reflectEx);
|
||||
parent.log(Level.WARNING, "Creating logger instance manually...");
|
||||
return LoggerFactory.getLogger(parent.getName());
|
||||
} finally {
|
||||
// restore previous class loader
|
||||
Thread.currentThread().setContextClassLoader(oldLoader);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2015-2022 games647 and contributors
|
||||
* Copyright (c) 2015-2021 <Your name and contributors>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2015-2022 games647 and contributors
|
||||
* Copyright (c) 2015-2021 <Your name and contributors>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
@@ -25,8 +25,42 @@
|
||||
*/
|
||||
package com.github.games647.fastlogin.core;
|
||||
|
||||
@FunctionalInterface
|
||||
public interface RateLimiter {
|
||||
/**
|
||||
* Limit the number of requests with a maximum size. Each requests expires after the specified time making it available
|
||||
* for another request.
|
||||
*/
|
||||
public class RateLimiter {
|
||||
|
||||
boolean tryAcquire();
|
||||
private final long[] requests;
|
||||
private final long expireTime;
|
||||
private int position;
|
||||
|
||||
public RateLimiter(int maxLimit, long expireTime) {
|
||||
this.requests = new long[maxLimit];
|
||||
this.expireTime = expireTime;
|
||||
}
|
||||
|
||||
/**
|
||||
* Ask if access is allowed. If so register the request.
|
||||
*
|
||||
* @return true if allowed - false otherwise without any side effects
|
||||
*/
|
||||
public boolean tryAcquire() {
|
||||
// current time millis is not monotonic - it can jump back depending on user choice or NTP
|
||||
long now = System.nanoTime() / 1_000_000;
|
||||
|
||||
// after this the request should be expired
|
||||
long toBeExpired = now - expireTime;
|
||||
synchronized (this) {
|
||||
// having synchronized will limit the amount of concurrency a lot
|
||||
long oldest = requests[position];
|
||||
if (oldest < toBeExpired) {
|
||||
requests[position] = now;
|
||||
position = (position + 1) % requests.length;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2015-2022 games647 and contributors
|
||||
* Copyright (c) 2015-2021 <Your name and contributors>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
@@ -113,7 +113,7 @@ public class StoredProfile extends Profile {
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized boolean equals(Object o) {
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (!(o instanceof StoredProfile)) return false;
|
||||
if (!super.equals(o)) return false;
|
||||
@@ -123,7 +123,7 @@ public class StoredProfile extends Profile {
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized int hashCode() {
|
||||
public int hashCode() {
|
||||
return Objects.hash(super.hashCode(), rowId, premium, lastIp, lastLogin);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,147 +0,0 @@
|
||||
/*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2015-2022 games647 and contributors
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
package com.github.games647.fastlogin.core;
|
||||
|
||||
import com.google.common.base.Ticker;
|
||||
|
||||
import java.util.ArrayDeque;
|
||||
import java.util.Deque;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* Limit the number of requests with a maximum size. Each requests expire after the specified time making it available
|
||||
* for another request.
|
||||
*/
|
||||
public class TickingRateLimiter implements RateLimiter {
|
||||
|
||||
private final Ticker ticker;
|
||||
|
||||
// amount of milliseconds to expire
|
||||
private final long expireTime;
|
||||
|
||||
// total request limit
|
||||
private final int requestLimit;
|
||||
|
||||
private final Deque<TimeRecord> records;
|
||||
private int totalRequests;
|
||||
|
||||
public TickingRateLimiter(Ticker ticker, int maxLimit, long expireTime) {
|
||||
this.ticker = ticker;
|
||||
|
||||
this.requestLimit = maxLimit;
|
||||
this.expireTime = expireTime;
|
||||
|
||||
records = new ArrayDeque<>(10);
|
||||
}
|
||||
|
||||
/**
|
||||
* Ask if access is allowed. If so register the request.
|
||||
*
|
||||
* @return true if allowed - false otherwise without any side effects
|
||||
*/
|
||||
@Override
|
||||
public boolean tryAcquire() {
|
||||
// current time millis is not monotonic - it can jump back depending on user choice or NTP
|
||||
long nowMilli = ticker.read() / 1_000_000;
|
||||
synchronized (this) {
|
||||
// having synchronized will limit the amount of concurrency a lot
|
||||
TimeRecord oldest = records.peekFirst();
|
||||
if (oldest != null && oldest.hasExpired(nowMilli)) {
|
||||
records.pop();
|
||||
totalRequests -= oldest.getRequestCount();
|
||||
}
|
||||
|
||||
// total requests reached block any further requests
|
||||
if (totalRequests >= requestLimit) {
|
||||
return false;
|
||||
}
|
||||
|
||||
TimeRecord latest = records.peekLast();
|
||||
if (latest == null) {
|
||||
// empty list - add new record
|
||||
records.add(new TimeRecord(nowMilli, expireTime));
|
||||
totalRequests++;
|
||||
return true;
|
||||
}
|
||||
|
||||
int res = latest.compareTo(nowMilli);
|
||||
if (res < 0) {
|
||||
// now is before than the record means time jumps
|
||||
throw new IllegalStateException("Time jumped back");
|
||||
}
|
||||
|
||||
if (res == 0) {
|
||||
// same minute record
|
||||
latest.hit();
|
||||
totalRequests++;
|
||||
return true;
|
||||
}
|
||||
|
||||
// now is one minute newer
|
||||
records.add(new TimeRecord(nowMilli, expireTime));
|
||||
totalRequests++;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
private static class TimeRecord implements Comparable<Long> {
|
||||
|
||||
private final long firstMinuteRecord;
|
||||
private final long expireTime;
|
||||
private int count;
|
||||
|
||||
public TimeRecord(long firstMinuteRecord, long expireTime) {
|
||||
this.firstMinuteRecord = firstMinuteRecord;
|
||||
this.expireTime = expireTime;
|
||||
this.count = 1;
|
||||
}
|
||||
|
||||
public void hit() {
|
||||
count++;
|
||||
}
|
||||
|
||||
public int getRequestCount() {
|
||||
return count;
|
||||
}
|
||||
|
||||
public boolean hasExpired(long now) {
|
||||
return firstMinuteRecord + expireTime <= now;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(Long other) {
|
||||
if (other < firstMinuteRecord) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (other > firstMinuteRecord + TimeUnit.MINUTES.toMillis(1)) {
|
||||
return +1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,7 +3,7 @@
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2015-2022 games647 and contributors
|
||||
* Copyright (c) 2015-2021 <Your name and contributors>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
@@ -72,7 +72,7 @@ public interface AuthPlugin<P> {
|
||||
/**
|
||||
* Checks whether an account exists for this player name.
|
||||
*
|
||||
* This check should check if a cracked player account exists,
|
||||
* This check should check if a cracked player account exists
|
||||
* so we can be sure the premium player doesn't steal the account
|
||||
* of that player.
|
||||
*
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2015-2022 games647 and contributors
|
||||
* Copyright (c) 2015-2021 <Your name and contributors>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
|
||||
@@ -0,0 +1,112 @@
|
||||
/*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2015-2021 <Your name and contributors>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
package com.github.games647.fastlogin.core.hooks;
|
||||
|
||||
import com.github.games647.craftapi.model.Profile;
|
||||
import com.github.games647.craftapi.resolver.RateLimitException;
|
||||
import com.github.games647.fastlogin.core.shared.FastLoginCore;
|
||||
import com.github.games647.fastlogin.core.shared.LoginSource;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.geysermc.floodgate.api.FloodgateApi;
|
||||
import org.geysermc.floodgate.api.player.FloodgatePlayer;
|
||||
|
||||
public class FloodgateHook<P extends C, C, S extends LoginSource> {
|
||||
|
||||
private final FastLoginCore<P, C, ?> core;
|
||||
|
||||
public FloodgateHook(FastLoginCore<P, C, ?> core) {
|
||||
this.core = core;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the player's name conflicts an existing Java player's name, and
|
||||
* kick them if it does
|
||||
*
|
||||
* @param username the name of the player
|
||||
* @param source an instance of LoginSource
|
||||
*/
|
||||
public void checkFloodgateNameConflict(String username, LoginSource source, FloodgatePlayer floodgatePlayer) {
|
||||
String allowConflict = core.getConfig().get("allowFloodgateNameConflict").toString().toLowerCase();
|
||||
|
||||
// check if the Bedrock player is linked to a Java account
|
||||
boolean isLinked = ((FloodgatePlayer) floodgatePlayer).getLinkedPlayer() != null;
|
||||
|
||||
if (allowConflict.equals("false")
|
||||
|| allowConflict.equals("linked") && !isLinked) {
|
||||
|
||||
// check for conflicting Premium Java name
|
||||
Optional<Profile> premiumUUID = Optional.empty();
|
||||
try {
|
||||
premiumUUID = core.getResolver().findProfile(username);
|
||||
} catch (IOException | RateLimitException e) {
|
||||
core.getPlugin().getLog().error(
|
||||
"Could not check wether Floodgate Player {}'s name conflicts a premium Java player's name.",
|
||||
username);
|
||||
try {
|
||||
source.kick("Could not check if your name conflicts an existing premium Java account's name.\n"
|
||||
+ "This is usually a serverside error.");
|
||||
} catch (Exception e1) {
|
||||
core.getPlugin().getLog().error("Could not kick Player {}", username);
|
||||
}
|
||||
}
|
||||
|
||||
if (premiumUUID.isPresent()) {
|
||||
core.getPlugin().getLog().info("Bedrock Player {}'s name conflicts an existing premium Java account's name",
|
||||
username);
|
||||
try {
|
||||
source.kick("Your name conflicts an existing premium Java account's name");
|
||||
} catch (Exception e) {
|
||||
core.getPlugin().getLog().error("Could not kick Player {}", username);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
core.getPlugin().getLog().info("Skipping name conflict checking for player {}", username);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The FloodgateApi does not support querying players by name, so this function
|
||||
* iterates over every online FloodgatePlayer and checks if the requested
|
||||
* username can be found
|
||||
*
|
||||
* @param username the name of the player
|
||||
* @return FloodgatePlayer if found, null otherwise
|
||||
*/
|
||||
public FloodgatePlayer getFloodgatePlayer(String username) {
|
||||
if (core.getPlugin().isPluginInstalled("floodgate")) {
|
||||
for (FloodgatePlayer floodgatePlayer : FloodgateApi.getInstance().getPlayers()) {
|
||||
if (floodgatePlayer.getUsername().equals(username)) {
|
||||
return floodgatePlayer;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -3,7 +3,7 @@
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2015-2022 games647 and contributors
|
||||
* Copyright (c) 2015-2021 <Your name and contributors>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
|
||||
@@ -1,135 +0,0 @@
|
||||
/*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2015-2022 games647 and contributors
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
package com.github.games647.fastlogin.core.hooks.bedrock;
|
||||
|
||||
import com.github.games647.craftapi.model.Profile;
|
||||
import com.github.games647.craftapi.resolver.RateLimitException;
|
||||
import com.github.games647.fastlogin.core.StoredProfile;
|
||||
import com.github.games647.fastlogin.core.shared.FastLoginCore;
|
||||
import com.github.games647.fastlogin.core.shared.LoginSource;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @param <B> is an instance of either FloodgatePlayer or GeyserSession
|
||||
*/
|
||||
public abstract class BedrockService<B> {
|
||||
|
||||
protected final FastLoginCore<?, ?, ?> core;
|
||||
protected final String allowConflict;
|
||||
|
||||
public BedrockService(FastLoginCore<?, ?, ?> core) {
|
||||
this.core = core;
|
||||
this.allowConflict = core.getConfig().get("allowFloodgateNameConflict").toString().toLowerCase();
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform every packet level check needed on a Bedrock player.
|
||||
*
|
||||
* @param username the name of the player
|
||||
* @param source an instance of LoginSource
|
||||
* @return true if Java specific checks can be skipped
|
||||
*/
|
||||
public abstract boolean performChecks(String username, LoginSource source);
|
||||
|
||||
/**
|
||||
* Check if the player's name conflicts an existing Java player's name, and kick
|
||||
* them if it does
|
||||
*
|
||||
* @param username the name of the player
|
||||
* @param source an instance of LoginSource
|
||||
*/
|
||||
protected void checkNameConflict(String username, LoginSource source) {
|
||||
// check for conflicting Premium Java name
|
||||
Optional<Profile> premiumUUID = Optional.empty();
|
||||
try {
|
||||
premiumUUID = core.getResolver().findProfile(username);
|
||||
} catch (IOException ioEx) {
|
||||
core.getPlugin().getLog().error(
|
||||
"Could not check whether Bedrock Player {}'s name conflicts a premium Java player's name.",
|
||||
username);
|
||||
|
||||
kickPlayer(source, username, "Could not check if your name conflicts an existing " +
|
||||
"premium Java account's name. This is usually a serverside error.");
|
||||
} catch (RateLimitException rateLimitException) {
|
||||
core.getPlugin().getLog().warn("Mojang API rate limit hit");
|
||||
kickPlayer(source, username, "Could not check if your name conflicts an existing premium " +
|
||||
"Java account's name. Try again in a few minutes");
|
||||
}
|
||||
|
||||
if (premiumUUID.isPresent()) {
|
||||
core.getPlugin().getLog().info("Bedrock Player {}'s name conflicts an existing premium Java account's name",
|
||||
username);
|
||||
kickPlayer(source, username, "Your name conflicts an existing premium Java account's name");
|
||||
}
|
||||
}
|
||||
|
||||
private void kickPlayer(LoginSource source, String username, String message) {
|
||||
try {
|
||||
source.kick(message);
|
||||
} catch (Exception ex) {
|
||||
core.getPlugin().getLog().error("Could not kick Player {}", username, ex);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The Floodgate / Geyser API does not support querying players by name, so this function
|
||||
* iterates over every online Bedrock Player and checks if the requested
|
||||
* username can be found
|
||||
* <br>
|
||||
* <i>Falls back to non-prefixed name checks, if ProtocolLib is installed</i>
|
||||
*
|
||||
* @param prefixedUsername the name of the player with the prefix appended
|
||||
* @return Bedrock Player if found, null otherwise
|
||||
*/
|
||||
public B getBedrockPlayer(String prefixedUsername) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public B getBedrockPlayer(UUID uuid) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public boolean isBedrockPlayer(UUID uuid) {
|
||||
return getBedrockPlayer(uuid) != null;
|
||||
}
|
||||
|
||||
public boolean isBedrockConnection(String username) {
|
||||
return getBedrockPlayer(username) != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a profile's name starts with the Floodgate prefix, if it's available
|
||||
* @param profile profile of the connecting player
|
||||
* @return true if the username is forbidden
|
||||
*/
|
||||
public boolean isUsernameForbidden(StoredProfile profile) {
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,136 +0,0 @@
|
||||
/*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2015-2022 games647 and contributors
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
package com.github.games647.fastlogin.core.hooks.bedrock;
|
||||
|
||||
import com.github.games647.fastlogin.core.StoredProfile;
|
||||
import com.github.games647.fastlogin.core.shared.FastLoginCore;
|
||||
import com.github.games647.fastlogin.core.shared.LoginSource;
|
||||
|
||||
import java.util.Locale;
|
||||
import java.util.UUID;
|
||||
|
||||
import org.geysermc.floodgate.api.FloodgateApi;
|
||||
import org.geysermc.floodgate.api.player.FloodgatePlayer;
|
||||
|
||||
public class FloodgateService extends BedrockService<FloodgatePlayer> {
|
||||
|
||||
private final FloodgateApi floodgate;
|
||||
|
||||
public FloodgateService(FloodgateApi floodgate, FastLoginCore<?, ?, ?> core) {
|
||||
super(core);
|
||||
this.floodgate = floodgate;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a config entry (related to Floodgate) is valid. <br>
|
||||
* Writes to Log if the value is invalid.
|
||||
* <p>
|
||||
* This should be used for:
|
||||
* <ul>
|
||||
* <li>allowFloodgateNameConflict
|
||||
* <li>autoLoginFloodgate
|
||||
* <li>autoRegisterFloodgate
|
||||
* </ul>
|
||||
* </p>
|
||||
*
|
||||
* @param key the key of the entry in config.yml
|
||||
* @return <b>true</b> if the entry's value is "true", "false", or "linked"
|
||||
*/
|
||||
public boolean isValidFloodgateConfigString(String key) {
|
||||
String value = core.getConfig().get(key).toString().toLowerCase(Locale.ENGLISH);
|
||||
if (!value.equals("true") && !value.equals("linked") && !value.equals("false") && !value.equals("no-conflict")) {
|
||||
core.getPlugin().getLog().error("Invalid value detected for {} in FastLogin/config.yml.", key);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isUsernameForbidden(StoredProfile profile) {
|
||||
String playerPrefix = floodgate.getPlayerPrefix();
|
||||
return profile.getName().startsWith(playerPrefix) && !playerPrefix.isEmpty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean performChecks(String username, LoginSource source) {
|
||||
// check if the Bedrock player is linked to a Java account
|
||||
FloodgatePlayer floodgatePlayer = getBedrockPlayer(username);
|
||||
boolean isLinked = floodgatePlayer.getLinkedPlayer() != null;
|
||||
|
||||
if ("false".equals(allowConflict)
|
||||
|| "linked".equals(allowConflict) && !isLinked) {
|
||||
super.checkNameConflict(username, source);
|
||||
} else {
|
||||
core.getPlugin().getLog().info("Skipping name conflict checking for player {}", username);
|
||||
}
|
||||
|
||||
//Floodgate users don't need Java specific checks
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* The FloodgateApi does not support querying players by name, so this function
|
||||
* iterates over every online FloodgatePlayer and checks if the requested
|
||||
* username can be found
|
||||
* <br>
|
||||
* <i>Falls back to non-prefixed name checks, if ProtocolLib is installed</i>
|
||||
*
|
||||
* @param prefixedUsername the name of the player with the prefix appended
|
||||
* @return FloodgatePlayer if found, null otherwise
|
||||
*/
|
||||
public FloodgatePlayer getBedrockPlayer(String prefixedUsername) {
|
||||
//prefixes are broken with ProtocolLib, so fall back to name checks without prefixes
|
||||
//this should be removed if #493 gets fixed
|
||||
if (core.getPlugin().isPluginInstalled("ProtocolLib")) {
|
||||
for (FloodgatePlayer floodgatePlayer : floodgate.getPlayers()) {
|
||||
if (floodgatePlayer.getUsername().equals(prefixedUsername)) {
|
||||
return floodgatePlayer;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
for (FloodgatePlayer floodgatePlayer : floodgate.getPlayers()) {
|
||||
if (floodgatePlayer.getCorrectUsername().equals(prefixedUsername)) {
|
||||
return floodgatePlayer;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public FloodgatePlayer getBedrockPlayer(UUID uuid) {
|
||||
return floodgate.getPlayer(uuid);
|
||||
}
|
||||
|
||||
public boolean isBedrockPlayer(UUID uuid) {
|
||||
return getBedrockPlayer(uuid) != null;
|
||||
}
|
||||
|
||||
public boolean isBedrockConnection(String username) {
|
||||
return getBedrockPlayer(username) != null;
|
||||
}
|
||||
}
|
||||
@@ -1,75 +0,0 @@
|
||||
/*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2015-2022 games647 and contributors
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
package com.github.games647.fastlogin.core.hooks.bedrock;
|
||||
|
||||
import com.github.games647.fastlogin.core.shared.FastLoginCore;
|
||||
import com.github.games647.fastlogin.core.shared.LoginSource;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
import org.geysermc.geyser.GeyserImpl;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
import org.geysermc.geyser.session.auth.AuthType;
|
||||
|
||||
public class GeyserService extends BedrockService<GeyserSession> {
|
||||
|
||||
private final GeyserImpl geyser;
|
||||
private final FastLoginCore<?, ?, ?> core;
|
||||
private final AuthType authType;
|
||||
|
||||
public GeyserService(GeyserImpl geyser, FastLoginCore<?, ?, ?> core) {
|
||||
super(core);
|
||||
this.geyser = geyser;
|
||||
this.core = core;
|
||||
this.authType = GeyserImpl.getInstance().getConfig().getRemote().getAuthType();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean performChecks(String username, LoginSource source) {
|
||||
// AuthType.FLOODGATE will be handled by FloodgateService
|
||||
if (authType == AuthType.ONLINE) {
|
||||
// authenticate everyone, as if they were Java players, since they have signed
|
||||
// in through Mojang
|
||||
return false;
|
||||
}
|
||||
if ("true".equals(allowConflict)) {
|
||||
core.getPlugin().getLog().info("Skipping name conflict checking for player {}", username);
|
||||
} else {
|
||||
super.checkNameConflict(username, source);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public GeyserSession getBedrockPlayer(String username) {
|
||||
return geyser.connectionByName(username);
|
||||
}
|
||||
|
||||
@Override
|
||||
public GeyserSession getBedrockPlayer(UUID uuid) {
|
||||
return geyser.connectionByUuid(uuid);
|
||||
}
|
||||
}
|
||||
@@ -3,7 +3,7 @@
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2015-2022 games647 and contributors
|
||||
* Copyright (c) 2015-2021 <Your name and contributors>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2015-2022 games647 and contributors
|
||||
* Copyright (c) 2015-2021 <Your name and contributors>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2015-2022 games647 and contributors
|
||||
* Copyright (c) 2015-2021 <Your name and contributors>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2015-2022 games647 and contributors
|
||||
* Copyright (c) 2015-2021 <Your name and contributors>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2015-2022 games647 and contributors
|
||||
* Copyright (c) 2015-2021 <Your name and contributors>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2015-2022 games647 and contributors
|
||||
* Copyright (c) 2015-2021 <Your name and contributors>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
|
||||
@@ -1,77 +0,0 @@
|
||||
/*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2015-2022 games647 and contributors
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
package com.github.games647.fastlogin.core.mojang;
|
||||
|
||||
import com.github.games647.craftapi.model.auth.Verification;
|
||||
import com.github.games647.craftapi.resolver.MojangResolver;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.InetAddress;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* An extension to {@link MojangResolver} which allows connection using transparent reverse proxies.
|
||||
* The significant difference is that unlike MojangResolver from the CraftAPI implementation, which sends the "ip" parameter
|
||||
* when the hostIp parameter is an IPv4 address, but skips it for IPv6, this implementation leaves out the "ip" parameter
|
||||
* also for IPv4, effectively enabling transparent proxies to work.
|
||||
* @author games647, Enginecrafter77
|
||||
*/
|
||||
public class ProxyAgnosticMojangResolver extends MojangResolver {
|
||||
/**
|
||||
* A formatting string containing an URL used to call the {@code hasJoined} method on mojang session servers.
|
||||
*
|
||||
* Formatting parameters:
|
||||
* 1. The username of the player in question
|
||||
* 2. The serverId of this server
|
||||
*/
|
||||
public static final String MOJANG_SESSIONSERVER_HASJOINED_CALL_URLFMT = "https://sessionserver.mojang.com/session/minecraft/hasJoined?username=%s&serverId=%s";
|
||||
|
||||
@Override
|
||||
public Optional<Verification> hasJoined(String username, String serverHash, InetAddress hostIp) throws IOException
|
||||
{
|
||||
String url = String.format(MOJANG_SESSIONSERVER_HASJOINED_CALL_URLFMT, username, serverHash);
|
||||
|
||||
HttpURLConnection conn = this.getConnection(url);
|
||||
int responseCode = conn.getResponseCode();
|
||||
|
||||
Verification verification = null;
|
||||
|
||||
// Mojang session servers send HTTP 204 (NO CONTENT) when the authentication seems invalid
|
||||
// If that's not our case, the authentication is valid, and so we can parse the response.
|
||||
if(responseCode != HttpURLConnection.HTTP_NO_CONTENT)
|
||||
verification = this.parseRequest(conn, this::parseVerification);
|
||||
|
||||
return Optional.ofNullable(verification);
|
||||
}
|
||||
|
||||
// Functional implementation of InputStreamAction, used in hasJoined method in parseRequest call
|
||||
protected Verification parseVerification(InputStream input) throws IOException
|
||||
{
|
||||
return this.readJson(input, Verification.class);
|
||||
}
|
||||
}
|
||||
@@ -3,7 +3,7 @@
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2015-2022 games647 and contributors
|
||||
* Copyright (c) 2015-2021 <Your name and contributors>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2015-2022 games647 and contributors
|
||||
* Copyright (c) 2015-2021 <Your name and contributors>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
@@ -27,17 +27,12 @@ package com.github.games647.fastlogin.core.shared;
|
||||
|
||||
import com.github.games647.craftapi.resolver.MojangResolver;
|
||||
import com.github.games647.craftapi.resolver.http.RotatingProxySelector;
|
||||
import com.github.games647.fastlogin.core.AuthStorage;
|
||||
import com.github.games647.fastlogin.core.CommonUtil;
|
||||
import com.github.games647.fastlogin.core.RateLimiter;
|
||||
import com.github.games647.fastlogin.core.TickingRateLimiter;
|
||||
import com.github.games647.fastlogin.core.hooks.AuthPlugin;
|
||||
import com.github.games647.fastlogin.core.hooks.DefaultPasswordGenerator;
|
||||
import com.github.games647.fastlogin.core.hooks.PasswordGenerator;
|
||||
import com.github.games647.fastlogin.core.mojang.ProxyAgnosticMojangResolver;
|
||||
import com.github.games647.fastlogin.core.storage.MySQLStorage;
|
||||
import com.github.games647.fastlogin.core.storage.SQLStorage;
|
||||
import com.github.games647.fastlogin.core.storage.SQLiteStorage;
|
||||
import com.google.common.base.Ticker;
|
||||
import com.google.common.net.HostAndPort;
|
||||
import com.zaxxer.hikari.HikariConfig;
|
||||
|
||||
@@ -84,10 +79,10 @@ public class FastLoginCore<P extends C, C, T extends PlatformPlugin<C>> {
|
||||
private final Collection<UUID> pendingConfirms = new HashSet<>();
|
||||
private final T plugin;
|
||||
|
||||
private MojangResolver resolver;
|
||||
private final MojangResolver resolver = new MojangResolver();
|
||||
|
||||
private Configuration config;
|
||||
private SQLStorage storage;
|
||||
private AuthStorage storage;
|
||||
private RateLimiter rateLimiter;
|
||||
private PasswordGenerator<P> passwordGenerator = new DefaultPasswordGenerator<>();
|
||||
private AuthPlugin<P> authPlugin;
|
||||
@@ -119,14 +114,17 @@ public class FastLoginCore<P extends C, C, T extends PlatformPlugin<C>> {
|
||||
return;
|
||||
}
|
||||
|
||||
// Initialize the resolver based on the config parameter
|
||||
this.resolver = this.config.getBoolean("useProxyAgnosticResolver", false) ? new ProxyAgnosticMojangResolver() : new MojangResolver();
|
||||
int maxCon = config.getInt("anti-bot.connections", 200);
|
||||
long expireTime = config.getLong("anti-bot.expire", 5) * 60 * 1_000L;
|
||||
if (expireTime > MAX_EXPIRE_RATE) {
|
||||
expireTime = MAX_EXPIRE_RATE;
|
||||
}
|
||||
|
||||
rateLimiter = createRateLimiter(config.getSection("anti-bot"));
|
||||
rateLimiter = new RateLimiter(maxCon, expireTime);
|
||||
Set<Proxy> proxies = config.getStringList("proxies")
|
||||
.stream()
|
||||
.map(HostAndPort::fromString)
|
||||
.map(proxy -> new InetSocketAddress(proxy.getHost(), proxy.getPort()))
|
||||
.map(proxy -> new InetSocketAddress(proxy.getHostText(), proxy.getPort()))
|
||||
.map(sa -> new Proxy(Type.HTTP, sa))
|
||||
.collect(toSet());
|
||||
|
||||
@@ -144,22 +142,6 @@ public class FastLoginCore<P extends C, C, T extends PlatformPlugin<C>> {
|
||||
resolver.setOutgoingAddresses(addresses);
|
||||
}
|
||||
|
||||
private RateLimiter createRateLimiter(Configuration botSection) {
|
||||
boolean enabled = botSection.getBoolean("enabled", true);
|
||||
if (!enabled) {
|
||||
// no-op rate limiter
|
||||
return () -> true;
|
||||
}
|
||||
|
||||
int maxCon = botSection.getInt("anti-bot.connections", 200);
|
||||
long expireTime = botSection.getLong("anti-bot.expire", 5) * 60 * 1_000L;
|
||||
if (expireTime > MAX_EXPIRE_RATE) {
|
||||
expireTime = MAX_EXPIRE_RATE;
|
||||
}
|
||||
|
||||
return new TickingRateLimiter(Ticker.systemTicker(), maxCon, expireTime);
|
||||
}
|
||||
|
||||
private Configuration loadFile(String fileName) throws IOException {
|
||||
ConfigurationProvider configProvider = ConfigurationProvider.getProvider(YamlConfiguration.class);
|
||||
|
||||
@@ -187,7 +169,7 @@ public class FastLoginCore<P extends C, C, T extends PlatformPlugin<C>> {
|
||||
return resolver;
|
||||
}
|
||||
|
||||
public SQLStorage getStorage() {
|
||||
public AuthStorage getStorage() {
|
||||
return storage;
|
||||
}
|
||||
|
||||
@@ -207,37 +189,26 @@ public class FastLoginCore<P extends C, C, T extends PlatformPlugin<C>> {
|
||||
}
|
||||
|
||||
public boolean setupDatabase() {
|
||||
String driver = config.getString("driver");
|
||||
if (!checkDriver(driver)) {
|
||||
if (!checkDriver(config.getString("driver"))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
HikariConfig databaseConfig = new HikariConfig();
|
||||
databaseConfig.setDriverClassName(driver);
|
||||
databaseConfig.setDriverClassName(config.getString("driver"));
|
||||
|
||||
String host = config.get("host", "");
|
||||
int port = config.get("port", 3306);
|
||||
String database = config.getString("database");
|
||||
|
||||
boolean useSSL = config.get("useSSL", false);
|
||||
|
||||
databaseConfig.setUsername(config.get("username", ""));
|
||||
databaseConfig.setPassword(config.getString("password"));
|
||||
|
||||
databaseConfig.setConnectionTimeout(config.getInt("timeout", 30) * 1_000L);
|
||||
databaseConfig.setMaxLifetime(config.getInt("lifetime", 30) * 1_000L);
|
||||
|
||||
if (driver.contains("sqlite")) {
|
||||
storage = new SQLiteStorage(this, database, databaseConfig);
|
||||
} else {
|
||||
String host = config.get("host", "");
|
||||
int port = config.get("port", 3306);
|
||||
boolean useSSL = config.get("useSSL", false);
|
||||
|
||||
if (useSSL) {
|
||||
databaseConfig.addDataSourceProperty("allowPublicKeyRetrieval", config.getBoolean("allowPublicKeyRetrieval", false));
|
||||
databaseConfig.addDataSourceProperty("serverRSAPublicKeyFile", config.getString("ServerRSAPublicKeyFile"));
|
||||
databaseConfig.addDataSourceProperty("sslMode", config.getString("sslMode", "Required"));
|
||||
}
|
||||
|
||||
databaseConfig.setUsername(config.get("username", ""));
|
||||
databaseConfig.setPassword(config.getString("password"));
|
||||
storage = new MySQLStorage(this, driver, host, port, database, databaseConfig, useSSL);
|
||||
}
|
||||
|
||||
storage = new AuthStorage(this, host, port, database, databaseConfig, useSSL);
|
||||
try {
|
||||
storage.createTables();
|
||||
return true;
|
||||
@@ -254,8 +225,7 @@ public class FastLoginCore<P extends C, C, T extends PlatformPlugin<C>> {
|
||||
} catch (ClassNotFoundException notFoundEx) {
|
||||
Logger log = plugin.getLog();
|
||||
log.warn("This driver {} is not supported on this platform", className);
|
||||
log.warn("Please choose either MySQL (Spigot, BungeeCord), SQLite (Spigot, Sponge) or " +
|
||||
"MariaDB (Sponge, Velocity)", notFoundEx);
|
||||
log.warn("Please choose MySQL (Spigot+BungeeCord), SQLite (Spigot+Sponge) or MariaDB (Sponge)", notFoundEx);
|
||||
}
|
||||
|
||||
return false;
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2015-2022 games647 and contributors
|
||||
* Copyright (c) 2015-2021 <Your name and contributors>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
@@ -73,27 +73,10 @@ public abstract class FloodgateManagement<P extends C, C, L extends LoginSession
|
||||
|
||||
// check if the Bedrock player is linked to a Java account
|
||||
isLinked = floodgatePlayer.getLinkedPlayer() != null;
|
||||
|
||||
//this happens on Bukkit if it's connected to Bungee
|
||||
//if that's the case, players will be logged in via plugin messages
|
||||
if (core.getStorage() == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
profile = core.getStorage().loadProfile(username);
|
||||
AuthPlugin<P> authPlugin = core.getAuthPluginHook();
|
||||
|
||||
|
||||
try {
|
||||
//maybe Bungee without auth plugin
|
||||
if (authPlugin == null) {
|
||||
if (profile != null) {
|
||||
isRegistered = profile.isPremium();
|
||||
} else {
|
||||
isRegistered = false;
|
||||
}
|
||||
} else {
|
||||
isRegistered = authPlugin.isRegistered(username);
|
||||
}
|
||||
isRegistered = authPlugin.isRegistered(username);
|
||||
} catch (Exception ex) {
|
||||
core.getPlugin().getLog().error(
|
||||
"An error has occured while checking if player {} is registered",
|
||||
@@ -120,11 +103,12 @@ public abstract class FloodgateManagement<P extends C, C, L extends LoginSession
|
||||
}
|
||||
}
|
||||
|
||||
if (!isRegistered && !isAutoAuthAllowed(autoRegisterFloodgate)) {
|
||||
if (!isRegistered && !isAutoRegisterAllowed()) {
|
||||
return;
|
||||
}
|
||||
|
||||
//logging in from bedrock for a second time threw an error with UUID
|
||||
profile = core.getStorage().loadProfile(username);
|
||||
if (profile == null) {
|
||||
profile = new StoredProfile(getUUID(player), username, true, getAddress(player).toString());
|
||||
}
|
||||
@@ -135,18 +119,14 @@ public abstract class FloodgateManagement<P extends C, C, L extends LoginSession
|
||||
}
|
||||
|
||||
/**
|
||||
* Decide if the player can be automatically registered or logged in.<br>
|
||||
* The config option 'non-conflicting' is ignored by this function, as name
|
||||
* conflicts are checked by a different part of the code.
|
||||
*
|
||||
* @param configValue the value of either 'autoLoginFloodgate' or
|
||||
* 'autoRegisterFloodgate' from config.yml
|
||||
* Decude if the player can be auto registered.
|
||||
* The config option 'non-conflicting' is ignored by this function.
|
||||
* @return true if the Player can be registered automatically
|
||||
*/
|
||||
protected boolean isAutoAuthAllowed(String configValue) {
|
||||
return "true".equals(configValue)
|
||||
|| "no-conflict".equals(configValue) // this was checked before
|
||||
|| ("linked".equals(configValue) && isLinked);
|
||||
private boolean isAutoRegisterAllowed() {
|
||||
return "true".equals(autoRegisterFloodgate)
|
||||
|| "no-conflict".equals(autoRegisterFloodgate) // this was checked before
|
||||
|| ("linked".equals(autoRegisterFloodgate) && isLinked);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2015-2022 games647 and contributors
|
||||
* Copyright (c) 2015-2021 <Your name and contributors>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
@@ -25,7 +25,7 @@
|
||||
*/
|
||||
package com.github.games647.fastlogin.core.shared;
|
||||
|
||||
import com.github.games647.fastlogin.core.storage.SQLStorage;
|
||||
import com.github.games647.fastlogin.core.AuthStorage;
|
||||
import com.github.games647.fastlogin.core.StoredProfile;
|
||||
import com.github.games647.fastlogin.core.hooks.AuthPlugin;
|
||||
import com.github.games647.fastlogin.core.shared.event.FastLoginAutoLoginEvent;
|
||||
@@ -55,7 +55,7 @@ public abstract class ForceLoginManagement<P extends C, C, L extends LoginSessio
|
||||
return;
|
||||
}
|
||||
|
||||
SQLStorage storage = core.getStorage();
|
||||
AuthStorage storage = core.getStorage();
|
||||
StoredProfile playerProfile = session.getProfile();
|
||||
try {
|
||||
if (isOnlineMode()) {
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2015-2022 games647 and contributors
|
||||
* Copyright (c) 2015-2021 <Your name and contributors>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
@@ -29,23 +29,25 @@ import com.github.games647.craftapi.model.Profile;
|
||||
import com.github.games647.craftapi.resolver.RateLimitException;
|
||||
import com.github.games647.fastlogin.core.StoredProfile;
|
||||
import com.github.games647.fastlogin.core.hooks.AuthPlugin;
|
||||
import com.github.games647.fastlogin.core.hooks.bedrock.BedrockService;
|
||||
import com.github.games647.fastlogin.core.hooks.FloodgateHook;
|
||||
import com.github.games647.fastlogin.core.shared.event.FastLoginPreLoginEvent;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import org.geysermc.floodgate.api.player.FloodgatePlayer;
|
||||
|
||||
import net.md_5.bungee.config.Configuration;
|
||||
|
||||
public abstract class JoinManagement<P extends C, C, S extends LoginSource> {
|
||||
|
||||
protected final FastLoginCore<P, C, ?> core;
|
||||
protected final AuthPlugin<P> authHook;
|
||||
private final BedrockService<?> bedrockService;
|
||||
private final FloodgateHook<P, C, ?> floodgateHook;
|
||||
|
||||
public JoinManagement(FastLoginCore<P, C, ?> core, AuthPlugin<P> authHook, BedrockService<?> bedrockService) {
|
||||
public JoinManagement(FastLoginCore<P, C, ?> core, AuthPlugin<P> authHook) {
|
||||
this.core = core;
|
||||
this.authHook = authHook;
|
||||
this.bedrockService = bedrockService;
|
||||
this.floodgateHook = new FloodgateHook<>(core);
|
||||
}
|
||||
|
||||
public void onLogin(String username, S source) {
|
||||
@@ -55,14 +57,13 @@ public abstract class JoinManagement<P extends C, C, S extends LoginSource> {
|
||||
return;
|
||||
}
|
||||
|
||||
//check if the player is connecting through Bedrock Edition
|
||||
if (bedrockService != null && bedrockService.isBedrockConnection(username)) {
|
||||
//perform Bedrock specific checks and skip Java checks, if they are not needed
|
||||
if (bedrockService.performChecks(username, source)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
//check if the player is connecting through Floodgate
|
||||
FloodgatePlayer floodgatePlayer = floodgateHook.getFloodgatePlayer(username);
|
||||
|
||||
if (floodgatePlayer != null) {
|
||||
floodgateHook.checkFloodgateNameConflict(username, source, floodgatePlayer);
|
||||
return;
|
||||
}
|
||||
callFastLoginPreLoginEvent(username, source, profile);
|
||||
|
||||
Configuration config = core.getConfig();
|
||||
@@ -75,9 +76,7 @@ public abstract class JoinManagement<P extends C, C, S extends LoginSource> {
|
||||
core.getPlugin().getLog().info("Requesting premium login for registered player: {}", username);
|
||||
requestPremiumLogin(source, profile, username, true);
|
||||
} else {
|
||||
if (isValidUsername(source, profile)) {
|
||||
startCrackedSession(source, profile, username);
|
||||
}
|
||||
startCrackedSession(source, profile, username);
|
||||
}
|
||||
} else {
|
||||
if (core.getPendingLogin().remove(ip + username) != null && config.get("secondAttemptCracked", false)) {
|
||||
@@ -115,16 +114,6 @@ public abstract class JoinManagement<P extends C, C, S extends LoginSource> {
|
||||
}
|
||||
}
|
||||
|
||||
protected boolean isValidUsername(LoginSource source, StoredProfile profile) throws Exception {
|
||||
if (bedrockService != null && bedrockService.isUsernameForbidden(profile)) {
|
||||
core.getPlugin().getLog().info("Floodgate Prefix detected on cracked player");
|
||||
source.kick("Your username contains illegal characters");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean checkPremiumName(S source, String username, StoredProfile profile) throws Exception {
|
||||
core.getPlugin().getLog().info("GameProfile {} uses a premium username", username);
|
||||
if (core.getConfig().get("autoRegister", false) && (authHook == null || !authHook.isRegistered(username))) {
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2015-2022 games647 and contributors
|
||||
* Copyright (c) 2015-2021 <Your name and contributors>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
@@ -26,7 +26,6 @@
|
||||
package com.github.games647.fastlogin.core.shared;
|
||||
|
||||
import com.github.games647.fastlogin.core.StoredProfile;
|
||||
import com.google.common.base.MoreObjects;
|
||||
import com.google.common.base.Objects;
|
||||
|
||||
import java.util.UUID;
|
||||
@@ -92,7 +91,7 @@ public abstract class LoginSession {
|
||||
|
||||
@Override
|
||||
public synchronized String toString() {
|
||||
return MoreObjects.toStringHelper(this)
|
||||
return Objects.toStringHelper(this)
|
||||
.add("profile", profile)
|
||||
.add("requestUsername", requestUsername)
|
||||
.add("username", username)
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2015-2022 games647 and contributors
|
||||
* Copyright (c) 2015-2021 <Your name and contributors>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2015-2022 games647 and contributors
|
||||
* Copyright (c) 2015-2021 <Your name and contributors>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
@@ -26,7 +26,6 @@
|
||||
package com.github.games647.fastlogin.core.shared;
|
||||
|
||||
import com.github.games647.fastlogin.core.AsyncScheduler;
|
||||
import com.github.games647.fastlogin.core.hooks.bedrock.BedrockService;
|
||||
import com.google.common.util.concurrent.ThreadFactoryBuilder;
|
||||
|
||||
import java.nio.file.Path;
|
||||
@@ -54,8 +53,6 @@ public interface PlatformPlugin<C> {
|
||||
}
|
||||
}
|
||||
|
||||
BedrockService<?> getBedrockService();
|
||||
|
||||
default ThreadFactory getThreadFactory() {
|
||||
return new ThreadFactoryBuilder()
|
||||
.setNameFormat(getName() + " Pool Thread #%1$d")
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2015-2022 games647 and contributors
|
||||
* Copyright (c) 2015-2021 <Your name and contributors>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
@@ -28,9 +28,6 @@ package com.github.games647.fastlogin.core.shared.event;
|
||||
import com.github.games647.fastlogin.core.StoredProfile;
|
||||
import com.github.games647.fastlogin.core.shared.LoginSession;
|
||||
|
||||
/**
|
||||
* This event fires if the plugin performs an auto login on the platform where the login plugin is.
|
||||
*/
|
||||
public interface FastLoginAutoLoginEvent extends FastLoginCancellableEvent {
|
||||
LoginSession getSession();
|
||||
StoredProfile getProfile();
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2015-2022 games647 and contributors
|
||||
* Copyright (c) 2015-2021 <Your name and contributors>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2015-2022 games647 and contributors
|
||||
* Copyright (c) 2015-2021 <Your name and contributors>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
@@ -28,9 +28,6 @@ package com.github.games647.fastlogin.core.shared.event;
|
||||
import com.github.games647.fastlogin.core.StoredProfile;
|
||||
import com.github.games647.fastlogin.core.shared.LoginSource;
|
||||
|
||||
/**
|
||||
* This action represents the login attempt of a player before the plugin makes any online mode actions.
|
||||
*/
|
||||
public interface FastLoginPreLoginEvent {
|
||||
|
||||
String getUsername();
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2015-2022 games647 and contributors
|
||||
* Copyright (c) 2015-2021 <Your name and contributors>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
@@ -27,9 +27,6 @@ package com.github.games647.fastlogin.core.shared.event;
|
||||
|
||||
import com.github.games647.fastlogin.core.StoredProfile;
|
||||
|
||||
/**
|
||||
* This even represents the opt-in premium status change by request.
|
||||
*/
|
||||
public interface FastLoginPremiumToggleEvent {
|
||||
|
||||
StoredProfile getProfile();
|
||||
|
||||
@@ -1,40 +0,0 @@
|
||||
/*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2015-2022 games647 and contributors
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
package com.github.games647.fastlogin.core.storage;
|
||||
|
||||
import com.github.games647.fastlogin.core.StoredProfile;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public interface AuthStorage {
|
||||
StoredProfile loadProfile(String name);
|
||||
|
||||
StoredProfile loadProfile(UUID uuid);
|
||||
|
||||
void save(StoredProfile playerProfile);
|
||||
|
||||
void close();
|
||||
}
|
||||
@@ -1,94 +0,0 @@
|
||||
/*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2015-2022 games647 and contributors
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
package com.github.games647.fastlogin.core.storage;
|
||||
|
||||
import com.github.games647.fastlogin.core.shared.FastLoginCore;
|
||||
import com.zaxxer.hikari.HikariConfig;
|
||||
|
||||
public class MySQLStorage extends SQLStorage {
|
||||
|
||||
public MySQLStorage(FastLoginCore<?, ?, ?> core, String driver, String host, int port, String database,
|
||||
HikariConfig config,boolean useSSL) {
|
||||
super(core,
|
||||
buildJDBCUrl(driver, host, port, database),
|
||||
setParams(config, useSSL));
|
||||
}
|
||||
|
||||
private static String buildJDBCUrl(String driver, String host, int port, String database) {
|
||||
String protocol = "mysql";
|
||||
if (driver.contains("mariadb")) {
|
||||
protocol = "mariadb";
|
||||
}
|
||||
|
||||
return protocol + "://" + host + ':' + port + '/' + database;
|
||||
}
|
||||
|
||||
private static HikariConfig setParams(HikariConfig config, boolean useSSL) {
|
||||
// Require SSL on the server if requested in config - this will also verify certificate
|
||||
// Those values are deprecated in favor of sslMode
|
||||
config.addDataSourceProperty("useSSL", useSSL);
|
||||
config.addDataSourceProperty("requireSSL", useSSL);
|
||||
|
||||
// adding paranoid hides hostname, username, version and so
|
||||
// could be useful for hiding server details
|
||||
config.addDataSourceProperty("paranoid", true);
|
||||
|
||||
// enable MySQL specific optimizations
|
||||
addPerformanceProperties(config);
|
||||
return config;
|
||||
}
|
||||
|
||||
private static void addPerformanceProperties(HikariConfig config) {
|
||||
// disabled by default - will return the same prepared statement instance
|
||||
config.addDataSourceProperty("cachePrepStmts", true);
|
||||
// default prepStmtCacheSize 25 - amount of cached statements
|
||||
config.addDataSourceProperty("prepStmtCacheSize", 250);
|
||||
// default prepStmtCacheSqlLimit 256 - length of SQL
|
||||
config.addDataSourceProperty("prepStmtCacheSqlLimit", 2048);
|
||||
// default false - available in newer versions caches the statements server-side
|
||||
config.addDataSourceProperty("useServerPrepStmts", true);
|
||||
// default false - prefer use of local values for autocommit and
|
||||
// transaction isolation (alwaysSendSetIsolation) should only be enabled if always use the set* methods
|
||||
// instead of raw SQL
|
||||
// https://forums.mysql.com/read.php?39,626495,626512
|
||||
config.addDataSourceProperty("useLocalSessionState", true);
|
||||
// rewrite batched statements to a single statement, adding them behind each other
|
||||
// only useful for addBatch statements and inserts
|
||||
config.addDataSourceProperty("rewriteBatchedStatements", true);
|
||||
// cache result metadata
|
||||
config.addDataSourceProperty("cacheResultSetMetadata", true);
|
||||
// cache results of show variables and collation per URL
|
||||
config.addDataSourceProperty("cacheServerConfiguration", true);
|
||||
// default false - set auto commit only if not matching
|
||||
config.addDataSourceProperty("elideSetAutoCommits", true);
|
||||
|
||||
// default true - internal timers for idle calculation -> removes System.getCurrentTimeMillis call per query
|
||||
// Some platforms are slow on this and it could affect the throughput about 3% according to MySQL
|
||||
// performance gems presentation
|
||||
// In our case it can be useful to see the time in error messages
|
||||
// config.addDataSourceProperty("maintainTimeStats", false);
|
||||
}
|
||||
}
|
||||
@@ -1,107 +0,0 @@
|
||||
/*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2015-2022 games647 and contributors
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
package com.github.games647.fastlogin.core.storage;
|
||||
|
||||
import com.github.games647.fastlogin.core.StoredProfile;
|
||||
import com.github.games647.fastlogin.core.shared.FastLoginCore;
|
||||
import com.github.games647.fastlogin.core.shared.PlatformPlugin;
|
||||
import com.zaxxer.hikari.HikariConfig;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Statement;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.locks.Lock;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
public class SQLiteStorage extends SQLStorage {
|
||||
|
||||
private final Lock lock = new ReentrantLock();
|
||||
|
||||
public SQLiteStorage(FastLoginCore<?, ?, ?> core, String databasePath, HikariConfig config) {
|
||||
super(core,
|
||||
"sqlite://" + replacePathVariables(core.getPlugin(), databasePath),
|
||||
setParams(config));
|
||||
}
|
||||
|
||||
private static HikariConfig setParams(HikariConfig config) {
|
||||
config.setConnectionTestQuery("SELECT 1");
|
||||
config.setMaximumPoolSize(1);
|
||||
|
||||
//a try to fix https://www.spigotmc.org/threads/fastlogin.101192/page-26#post-1874647
|
||||
// format strings retrieved by the timestamp column to match them from MySQL
|
||||
config.addDataSourceProperty("date_string_format", "yyyy-MM-dd HH:mm:ss");
|
||||
|
||||
// TODO: test first for compatibility
|
||||
// config.addDataSourceProperty("date_precision", "seconds");
|
||||
|
||||
return config;
|
||||
}
|
||||
|
||||
@Override
|
||||
public StoredProfile loadProfile(String name) {
|
||||
lock.lock();
|
||||
try {
|
||||
return super.loadProfile(name);
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public StoredProfile loadProfile(UUID uuid) {
|
||||
lock.lock();
|
||||
try {
|
||||
return super.loadProfile(uuid);
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void save(StoredProfile playerProfile) {
|
||||
lock.lock();
|
||||
try {
|
||||
super.save(playerProfile);
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void createTables() throws SQLException {
|
||||
try (Connection con = dataSource.getConnection();
|
||||
Statement createStmt = con.createStatement()) {
|
||||
// SQLite has a different syntax for auto increment
|
||||
createStmt.executeUpdate(CREATE_TABLE_STMT.replace("AUTO_INCREMENT", "AUTOINCREMENT"));
|
||||
}
|
||||
}
|
||||
|
||||
private static String replacePathVariables(PlatformPlugin<?> plugin, String input) {
|
||||
String pluginFolder = plugin.getPluginFolder().toAbsolutePath().toString();
|
||||
return input.replace("{pluginDir}", pluginFolder);
|
||||
}
|
||||
}
|
||||
@@ -5,15 +5,14 @@
|
||||
# You can access the newest config here:
|
||||
# https://github.com/games647/FastLogin/blob/main/core/src/main/resources/config.yml
|
||||
|
||||
# This a **very** simple anti bot protection. Recommendation is to use a dedicated program to approach this
|
||||
# This a **very** simple anti bot protection. Recommendation is to use a a dedicated program to approach this
|
||||
# problem. Low level firewalls like uwf (or iptables direct) are more efficient than a Minecraft plugin. TCP reverse
|
||||
# proxies could also be used and offload some work even to different host.
|
||||
#
|
||||
# The settings wil limit how many connections this plugin will handle. After hitting this limit. FastLogin will
|
||||
# completely ignore incoming connections. Effectively there will be no database requests and network requests.
|
||||
# Therefore, auto logins won't be possible.
|
||||
# Therefore auto logins won't be possible.
|
||||
anti-bot:
|
||||
enabled: true
|
||||
# Image the following like bucket. The following is total amount that is allowed in this bucket, while expire
|
||||
# means how long it takes for every entry to expire.
|
||||
# Total number of connections
|
||||
@@ -31,7 +30,7 @@ anti-bot:
|
||||
# -> cracked player cannot register an account for the premium player and so cannot the steal the account
|
||||
#
|
||||
# Furthermore the premium player check have to be made based on the player name
|
||||
# This means if a cracked player connects to the server, we request a paid account login from this player
|
||||
# This means if a cracked player connects to the server and we request a paid account login from this player
|
||||
# the player just disconnect and sees the message: 'bad login' or 'invalid session'
|
||||
# There is no way to change this message
|
||||
# For more information: https://github.com/games647/FastLogin#why-do-players-have-to-invoke-a-command
|
||||
@@ -57,9 +56,9 @@ secondAttemptCracked: false
|
||||
# New cracked players will be kicked from server. Good if you want switch from offline-mode to online-mode without
|
||||
# losing players!
|
||||
#
|
||||
# Existing cracked and premium players could still join your server. Moreover, you could add player names to an
|
||||
# allow-list.
|
||||
# So that these cracked players could join too, although they are new players.
|
||||
# Existing cracked and premium players could still join your server. Moreover you could add playernames to a
|
||||
# allowlist.
|
||||
# So that these cracked players could join too although they are new players.
|
||||
switchMode: false
|
||||
|
||||
# If this plugin detected that a player has a premium, it can also set the associated
|
||||
@@ -67,14 +66,14 @@ switchMode: false
|
||||
# the same player data (inventory, permissions, ...)
|
||||
#
|
||||
# Warning: This also means that the UUID will be different if the player is connecting
|
||||
# through an offline mode connection. This **could** cause plugin compatibility issues.
|
||||
# through a offline mode connection. This **could** cause plugin compatibility issues.
|
||||
#
|
||||
# This is an example and doesn't apply for every plugin.
|
||||
# This is a example and doesn't apply for every plugin.
|
||||
# Example: If you want to ban players who aren't online at the moment, the ban plugin will look
|
||||
# after an offline uuid associated to the player, because the server is in offline mode. Then the premium
|
||||
# after a offline uuid associated to the player, because the server is in offline mode. Then the premium
|
||||
# players could still join the server, because they have different UUID.
|
||||
#
|
||||
# Moreover, you may want to convert the offline UUID to a premium UUID. This will ensure that the player
|
||||
# Moreover you may want to convert the offline UUID to a premium UUID. This will ensure that the player
|
||||
# will have the same inventory, permissions, ... if they switched to premium authentication from offline/cracked
|
||||
# authentication.
|
||||
#
|
||||
@@ -83,7 +82,7 @@ premiumUuid: false
|
||||
|
||||
# This will make an additional check (only for player names which are not in the database) against the mojang servers
|
||||
# in order to get the premium UUID. If that premium UUID is in the database, we can assume on successful login that the
|
||||
# player changed its username and then update the name in the database.
|
||||
# player changed it's username and we just update the name in the database.
|
||||
# Examples:
|
||||
# #### Case 1
|
||||
# autoRegister = false
|
||||
@@ -98,10 +97,10 @@ premiumUuid: false
|
||||
#
|
||||
# Connect the Mojang API and check what UUID the player has (UUID exists => Paid Minecraft account). If that UUID is in
|
||||
# the database it's an **existing player** and FastLogin can **assume** the player is premium and changed the username.
|
||||
# If it's not in the database, it's a new player and **could be a cracked player**. So we just use an offline mode
|
||||
# If it's not in the database, it's a new player and **could be a cracked player**. So we just use a offline mode
|
||||
# authentication for this player.
|
||||
#
|
||||
# **Limitation**: Cracked players who use the new username of a paid account cannot join the server if the database
|
||||
# **Limitation**: Cracked players who uses the new username of a paid account cannot join the server if the database
|
||||
# contains the old name. (Example: The owner of the paid account no longer plays on the server, but changed the username
|
||||
# in the meanwhile).
|
||||
#
|
||||
@@ -111,7 +110,7 @@ premiumUuid: false
|
||||
#
|
||||
# We will always request a premium authentication if the username is unknown to us, but is in use by a paid Minecraft
|
||||
# account. This means it's kind of a more aggressive check like nameChangeCheck = true and autoRegister = false, because
|
||||
# it requests a premium authentication which are completely new to us, that even the premium UUID is not in our database.
|
||||
# it request a premium authentication which are completely new to us, that even the premium UUID is not in our database.
|
||||
#
|
||||
# **Limitation**: see below
|
||||
#
|
||||
@@ -122,14 +121,14 @@ premiumUuid: false
|
||||
# Based on autoRegister it checks if the player name is premium and login using a premium authentication. After that
|
||||
# fastlogin receives the premium UUID and can update the database record.
|
||||
#
|
||||
# **Limitation from autoRegister**: New offline players who use the username of an existing Minecraft cannot join the
|
||||
# **Limitation from autoRegister**: New offline players who uses the username of an existing Minecraft cannot join the
|
||||
# server.
|
||||
nameChangeCheck: false
|
||||
|
||||
# If your players have a premium account and a skin associated to their account, this plugin
|
||||
# can download the data and set it to the online player.
|
||||
#
|
||||
# Keep in mind that this will only work if the player:
|
||||
# Keep in mind that this will only works if the player:
|
||||
# * is the owner of the premium account
|
||||
# * the server connection is established through a premium connection (paid account authentication)
|
||||
# * has a skin
|
||||
@@ -152,24 +151,6 @@ forwardSkin: true
|
||||
# If they still want to invoke the command, they have to invoke /premium again
|
||||
premium-warning: true
|
||||
|
||||
# ======[[ Spigot+ProtocolLib users only ]]======
|
||||
# When set to true, enables the use of alternative session resolver which does not send the server IP
|
||||
# to mojang session servers. This setting might be useful when you are trying to run the server via a
|
||||
# transparent reverse proxy or some other form of DNAT. As far as security goes, this setting has
|
||||
# negligible to no security impact.
|
||||
#
|
||||
# This setting works on a similar principle as 'prevent-proxy' setting in server.properties.
|
||||
# When set to false, the server behaves like prevent-proxy was set to true and vice-versa.
|
||||
# Normally, when you use the prevent-proxy=true, you would want this disabled.
|
||||
#
|
||||
# Please note that this setting has no effect when used outside of Spigot+ProtocolLib context.
|
||||
#
|
||||
# !!! [WARNING] !!!
|
||||
# This option is considered highly experimental. While it is highly unlikely this will break your server,
|
||||
# more tests need to be conducted in order to verify its effectiveness. Brief tests seemed promising, but
|
||||
# every environment is different, and so it might not work for you as it did for me.
|
||||
useProxyAgnosticResolver: false
|
||||
|
||||
# If you have autoRegister or nameChangeCheck enabled, you could be rate-limited by Mojang.
|
||||
# The requests of the both options will be only made by FastLogin if the username is unknown to the server
|
||||
# You are allowed to make 600 requests per 10-minutes (60 per minute)
|
||||
@@ -207,7 +188,7 @@ auto-register-unknown: false
|
||||
autoLogin: true
|
||||
|
||||
# Floodgate configuration
|
||||
# Connecting through Floodgate requires player's to sign in via their Xbox Live account
|
||||
# Connecing through Floodgate requires player's to sign in via their Xbox Live account
|
||||
# !!!!!!!! WARNING: FLOODGATE SUPPORT IS AN EXPERIMENTAL FEATURE !!!!!!!!
|
||||
# Enabling any of these settings might lead to people gaining unauthorized access to other's accounts!
|
||||
|
||||
@@ -224,26 +205,26 @@ autoLogin: true
|
||||
# Enabling this might lead to people gaining unauthorized access to other's accounts!
|
||||
autoLoginFloodgate: false
|
||||
|
||||
# This enables Floodgate or Offline Geyser players to join the server, even if they are using the name of an
|
||||
# existing Java **PREMIUM** account (so someone has bought Minecraft with that username)
|
||||
# This enables Floodgate players to join the server, even if autoRegister is true and there's an existing
|
||||
# Java **PREMIUM** account with the same name
|
||||
#
|
||||
# Java and Bedrock players will get different UUIDs, so their inventories, location, etc. will be different.
|
||||
# However, some plugins (such as AuthMe) rely on names instead of UUIDs to identify a player which might cause issues.
|
||||
# In the case of AuthMe (and other auth plugins), both the Java and the Bedrock player will have the same password.
|
||||
#
|
||||
# To prevent conflicts from two different players having the same name, it is highly recommended using a
|
||||
# 'username-prefix' in floodgate/config.yml
|
||||
# Note: 'username-prefix' is currently broken when used with FastLogin and ProtocolLib.
|
||||
# A solution to this is to enable 'floodgatePrefixWorkaround' below.
|
||||
# To prevent conflits from two different players having the same name, it is highly recommended to use a 'username-prefix'
|
||||
# in floodgate/config.yml
|
||||
# Note: 'username-prefix' is currently broken when used with FastLogin and ProtocolLib. For more information visit:
|
||||
# https://github.com/games647/FastLogin/issues/493
|
||||
# A solution to this is to replace ProtocolLib with ProtocolSupport
|
||||
#
|
||||
# Possible values:
|
||||
# false: Kick Bedrock players, if they are using an existing Premium Java account's name
|
||||
# Note: Linked Floodgate players have the same name as their Java profile, so the Bedrock player will always conflict
|
||||
# false: Check for Premium Java name conflicts as described in 'autoRegister'
|
||||
# Note: Linked players have the same name as their Java profile, so the Bedrock player will always conflict
|
||||
# their own Java account's name. Therefore, setting this to false will prevent any linked player from joining.
|
||||
# true: Bypass name conflict checking.
|
||||
# linked: Floodgate accounts linked to a Java account will be allowed to join with conflicting names
|
||||
# For Offline Geyser players, 'linked' works as 'false'
|
||||
# !!!!!!!! WARNING: FLOODGATE/GEYSER SUPPORT IS AN EXPERIMENTAL FEATURE !!!!!!!!
|
||||
# true: Bypass 'autoRegister's name conflict checking
|
||||
# linked: Bedrock accounts linked to a Java account will be allowed to join with conflicting names
|
||||
# !!!!!!!! WARNING: FLOODGATE SUPPORT IS AN EXPERIMENTAL FEATURE !!!!!!!!
|
||||
# Enabling this might lead to people gaining unauthorized access to other's accounts!
|
||||
allowFloodgateNameConflict: false
|
||||
|
||||
@@ -261,14 +242,6 @@ allowFloodgateNameConflict: false
|
||||
# Enabling this might lead to people gaining unauthorized access to other's accounts!
|
||||
autoRegisterFloodgate: false
|
||||
|
||||
# Make FastLogin inject the Floodgate name prefixes, instead of Floodgate.
|
||||
# This can fix prefixes, if you are using Floodgate alongside ProtocolLib.
|
||||
# If either of those plugins are not installed, this option will have no effect.
|
||||
# For more information visit: https://github.com/games647/FastLogin/issues/493
|
||||
# !!!!!!!! WARNING: FLOODGATE SUPPORT IS AN EXPERIMENTAL FEATURE !!!!!!!!
|
||||
# Enabling this might lead to people gaining unauthorized access to other's accounts!
|
||||
floodgatePrefixWorkaround: false
|
||||
|
||||
# Database configuration
|
||||
# Recommended is the use of MariaDB (a better version of MySQL)
|
||||
|
||||
@@ -279,7 +252,6 @@ database: '{pluginDir}/FastLogin.db'
|
||||
|
||||
# MySQL/MariaDB
|
||||
# If you want to enable it uncomment only the lines below this not this line.
|
||||
# If on velocity use 'fastlogin.mariadb.jdbc.Driver' as driver
|
||||
#driver: 'com.mysql.jdbc.Driver'
|
||||
#host: '127.0.0.1'
|
||||
#port: 3306
|
||||
@@ -291,19 +263,9 @@ database: '{pluginDir}/FastLogin.db'
|
||||
#timeout: 30
|
||||
#lifetime: 30
|
||||
|
||||
## It's recommended to enable SSL if the MySQL server isn't running on the same host
|
||||
## This will encrypt the connection for secure transportation of the sql server password
|
||||
# It's strongly recommended to enable SSL and setup a SSL certificate if the MySQL server isn't running on the same
|
||||
# machine
|
||||
#useSSL: false
|
||||
## Verification requirements for the server cert,
|
||||
## Values: Required (unchecked SSL connection), VerifyCA (verify CA), VerifyFull (verify CA and matching hostname)
|
||||
#sslMode=Required
|
||||
## TLS is preferred for this technique, then your host stored certificate store will be used to verify the server cert
|
||||
## Similar to HTTPS. If that's not possible RSA can be used with the following options.
|
||||
## This allows to request the public RSA key from the server to encrypt the data to it. True would allow machine-in-the-
|
||||
## middle attacks.
|
||||
#allowPublicKeyRetrieval=false
|
||||
## Path to the RSA public key if key retrieval is forbidden
|
||||
#ServerRSAPublicKeyFile=
|
||||
|
||||
# HTTP proxies for connecting to the Mojang servers in order to check if the username of a player is premium.
|
||||
# This is a workaround to prevent rate-limiting by Mojang. These proxies will only be used once your server hit
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
# Second line
|
||||
# Third line'
|
||||
|
||||
# If you want to disable a message, you can just set it to an empty value.
|
||||
# If you want to disable a message, you can just set it to a empty value.
|
||||
# In this case no message will be sent
|
||||
# Example:
|
||||
# bla: ''
|
||||
@@ -55,7 +55,7 @@ auto-login: '&2Auto logged in'
|
||||
|
||||
# FastLogin attempted to auto register user. The user account is registered to protect it from cracked players
|
||||
# If FastLogin is respecting auth plugin IP limit - the registration may have failed, however the message is still displayed
|
||||
# The password can be used if the mojang servers are down, and you still want your premium users to login (PLANNED)
|
||||
# The password can be used if the mojang servers are down and you still want your premium users to login (PLANNED)
|
||||
auto-register: '&2Tried auto registering with password: &7%password&2. You may want change it?'
|
||||
|
||||
# GameProfile is not able to toggle the premium state of other players
|
||||
@@ -70,12 +70,12 @@ no-console: '&4You are not a player. You cannot toggle the premium state for YOU
|
||||
wait-on-proxy: '&6Sending request... (Do not forget to follow the BungeeCord setup guide)'
|
||||
|
||||
# When ProtocolLib is enabled and the plugin is unable to continue handling a login request after a requested premium
|
||||
# authentication. In this state the client expects a success packet with an encrypted connection or disconnect packet.
|
||||
# authentication. In this state the client expects a success packet with a encrypted connection or disconnect packet.
|
||||
# So we kick the player, if we cannot encrypt the connection. In other situation (example: premium name check),
|
||||
# the player will be just authenticated as cracked
|
||||
error-kick: '&4Error occurred'
|
||||
|
||||
# The server sends a verify-token within the premium authentication request. If this doesn't match on response,
|
||||
# The server sends a verify token within the premium authentication request. If this doesn't match on response,
|
||||
# it could be another client sending malicious packets
|
||||
invalid-verify-token: '&4Invalid token'
|
||||
|
||||
@@ -84,7 +84,7 @@ invalid-verify-token: '&4Invalid token'
|
||||
invalid-session: '&4Invalid session'
|
||||
|
||||
# The client sent a malicious packet without a login request packet
|
||||
invalid-request: '&4Invalid request'
|
||||
invalid-requst: '&4Invalid request'
|
||||
|
||||
# Message if the Bukkit isn't fully started to inject the packets
|
||||
not-started: '&cServer is not fully started yet. Please retry'
|
||||
|
||||
@@ -1,48 +0,0 @@
|
||||
/*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2015-2022 games647 and contributors
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
package com.github.games647.fastlogin.core;
|
||||
|
||||
import com.google.common.base.Ticker;
|
||||
|
||||
import java.time.Duration;
|
||||
|
||||
public class FakeTicker extends Ticker {
|
||||
|
||||
private long timestamp;
|
||||
|
||||
public FakeTicker(long initial) {
|
||||
timestamp = initial;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long read() {
|
||||
return timestamp;
|
||||
}
|
||||
|
||||
public void add(Duration duration) {
|
||||
timestamp += duration.toNanos();
|
||||
}
|
||||
}
|
||||
@@ -3,7 +3,7 @@
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2015-2022 games647 and contributors
|
||||
* Copyright (c) 2015-2021 <Your name and contributors>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
@@ -25,7 +25,6 @@
|
||||
*/
|
||||
package com.github.games647.fastlogin.core;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.junit.Test;
|
||||
@@ -33,7 +32,7 @@ import org.junit.Test;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
public class TickingRateLimiterTest {
|
||||
public class RateLimiterTest {
|
||||
|
||||
private static final long THRESHOLD_MILLI = 10;
|
||||
|
||||
@@ -44,34 +43,14 @@ public class TickingRateLimiterTest {
|
||||
public void allowExpire() throws InterruptedException {
|
||||
int size = 3;
|
||||
|
||||
FakeTicker ticker = new FakeTicker(5_000_000L);
|
||||
|
||||
// run twice the size to fill it first and then test it
|
||||
TickingRateLimiter rateLimiter = new TickingRateLimiter(ticker, size, 0);
|
||||
RateLimiter rateLimiter = new RateLimiter(size, 0);
|
||||
for (int i = 0; i < size; i++) {
|
||||
assertTrue("Filling up", rateLimiter.tryAcquire());
|
||||
}
|
||||
|
||||
for (int i = 0; i < size; i++) {
|
||||
ticker.add(Duration.ofSeconds(1));
|
||||
assertTrue("Should be expired", rateLimiter.tryAcquire());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void allowExpireNegative() throws InterruptedException {
|
||||
int size = 3;
|
||||
|
||||
FakeTicker ticker = new FakeTicker(-5_000_000L);
|
||||
|
||||
// run twice the size to fill it first and then test it
|
||||
TickingRateLimiter rateLimiter = new TickingRateLimiter(ticker, size, 0);
|
||||
for (int i = 0; i < size; i++) {
|
||||
assertTrue("Filling up", rateLimiter.tryAcquire());
|
||||
}
|
||||
|
||||
for (int i = 0; i < size; i++) {
|
||||
ticker.add(Duration.ofSeconds(1));
|
||||
Thread.sleep(1);
|
||||
assertTrue("Should be expired", rateLimiter.tryAcquire());
|
||||
}
|
||||
}
|
||||
@@ -80,31 +59,11 @@ public class TickingRateLimiterTest {
|
||||
* Too many requests
|
||||
*/
|
||||
@Test
|
||||
public void shouldBlock() {
|
||||
public void shoudBlock() {
|
||||
int size = 3;
|
||||
|
||||
FakeTicker ticker = new FakeTicker(5_000_000L);
|
||||
|
||||
// fill the size
|
||||
TickingRateLimiter rateLimiter = new TickingRateLimiter(ticker, size, TimeUnit.SECONDS.toMillis(30));
|
||||
for (int i = 0; i < size; i++) {
|
||||
assertTrue("Filling up", rateLimiter.tryAcquire());
|
||||
}
|
||||
|
||||
assertFalse("Should be full and no entry should be expired", rateLimiter.tryAcquire());
|
||||
}
|
||||
|
||||
/**
|
||||
* Too many requests
|
||||
*/
|
||||
@Test
|
||||
public void shouldBlockNegative() {
|
||||
int size = 3;
|
||||
|
||||
FakeTicker ticker = new FakeTicker(-5_000_000L);
|
||||
|
||||
// fill the size
|
||||
TickingRateLimiter rateLimiter = new TickingRateLimiter(ticker, size, TimeUnit.SECONDS.toMillis(30));
|
||||
RateLimiter rateLimiter = new RateLimiter(size, TimeUnit.SECONDS.toMillis(30));
|
||||
for (int i = 0; i < size; i++) {
|
||||
assertTrue("Filling up", rateLimiter.tryAcquire());
|
||||
}
|
||||
@@ -117,40 +76,17 @@ public class TickingRateLimiterTest {
|
||||
*/
|
||||
@Test
|
||||
public void blockedNotAdded() throws InterruptedException {
|
||||
FakeTicker ticker = new FakeTicker(5_000_000L);
|
||||
|
||||
// fill the size - 100ms should be reasonable high
|
||||
TickingRateLimiter rateLimiter = new TickingRateLimiter(ticker, 1, 100);
|
||||
RateLimiter rateLimiter = new RateLimiter(1, 100);
|
||||
assertTrue("Filling up", rateLimiter.tryAcquire());
|
||||
|
||||
ticker.add(Duration.ofMillis(50));
|
||||
Thread.sleep(50);
|
||||
|
||||
// still is full - should fail
|
||||
assertFalse("Expired too early", rateLimiter.tryAcquire());
|
||||
|
||||
// wait the remaining time and add a threshold, because
|
||||
ticker.add(Duration.ofMillis(50));
|
||||
assertTrue("Request not released", rateLimiter.tryAcquire());
|
||||
}
|
||||
|
||||
/**
|
||||
* Blocked attempts shouldn't replace existing ones.
|
||||
*/
|
||||
@Test
|
||||
public void blockedNotAddedNegative() throws InterruptedException {
|
||||
FakeTicker ticker = new FakeTicker(-5_000_000L);
|
||||
|
||||
// fill the size - 100ms should be reasonable high
|
||||
TickingRateLimiter rateLimiter = new TickingRateLimiter(ticker, 1, 100);
|
||||
assertTrue("Filling up", rateLimiter.tryAcquire());
|
||||
|
||||
ticker.add(Duration.ofMillis(50));
|
||||
|
||||
// still is full - should fail
|
||||
assertFalse("Expired too early", rateLimiter.tryAcquire());
|
||||
|
||||
// wait the remaining time and add a threshold, because
|
||||
ticker.add(Duration.ofMillis(50));
|
||||
Thread.sleep(50 + THRESHOLD_MILLI);
|
||||
assertTrue("Request not released", rateLimiter.tryAcquire());
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user