Compare commits
461 Commits
5.5.0-SNAP
...
master
Author | SHA1 | Date |
---|---|---|
|
f56a23f4b7 | |
|
a57382f269 | |
|
9380efdd3d | |
|
ad64370bf1 | |
|
54bae76d27 | |
|
93f1385c7a | |
|
d5dbc7e5c7 | |
|
72bbb4ebaa | |
|
caf0d3f8ed | |
|
95726cc7f9 | |
|
9b93e0e4b6 | |
|
65a272d6cb | |
|
2de4a60f3a | |
|
79309c3c05 | |
|
80c1c2edac | |
|
f098cc0762 | |
|
a1b4ccb736 | |
|
550b3a1b69 | |
|
7bfb79f4dd | |
|
44b255512d | |
|
7a76050cc7 | |
|
e11f36412f | |
|
abcd2640bb | |
|
974e6780a5 | |
|
b6bf9dabcc | |
|
642ff72ee0 | |
|
f24d6c5b5f | |
|
df6931d4b1 | |
|
793ab1d75b | |
|
db04fd2a5b | |
|
2e3448ab58 | |
|
c4d1c41059 | |
|
9fd532d798 | |
|
779e62674e | |
|
ca6e301d46 | |
|
a14df80a87 | |
|
d7437bd2b1 | |
|
569b8ba2d3 | |
|
87c60a5b44 | |
|
3741fb4cec | |
|
ddca37ab73 | |
|
0c83c6d9d8 | |
|
681689bd5c | |
|
1492d8d4a1 | |
|
12978a82d1 | |
|
a865f9bc2d | |
|
683c897c0f | |
|
fefeead323 | |
|
3f5353a328 | |
|
dca829650c | |
|
37b8728197 | |
|
50a1f9de98 | |
|
51760c4a8c | |
|
0d29c18ab4 | |
|
63780e3f7c | |
|
0f24197323 | |
|
75b3a571e1 | |
|
909617fce1 | |
|
c38e2aba28 | |
|
6f1c63e693 | |
|
b65ffd7c74 | |
|
7c8bbe6294 | |
|
fd0a0a1155 | |
|
af2fbd0558 | |
|
ec9de15bb9 | |
|
70f06b6da8 | |
|
1869c3097f | |
|
4b2a122581 | |
|
817a4af65b | |
|
aaba6dc24d | |
|
9c928e04e5 | |
|
4fe6cfe485 | |
|
053519faa4 | |
|
24d03aa1e2 | |
|
6d49d798f1 | |
|
be2881182f | |
|
4652aae8f7 | |
|
61710e9a47 | |
|
a9898fd806 | |
|
ed4200b23f | |
|
0ac1854a52 | |
|
d07cb90858 | |
|
a67a4bb72b | |
|
64c45c43df | |
|
f1f5434b4b | |
|
7530528432 | |
|
9d9e039cac | |
|
dbf9afbf82 | |
|
291790178d | |
|
a111d6799e | |
|
a14b8bd60e | |
|
18613cb3cc | |
|
0b6c92949c | |
|
32d92e13c5 | |
|
25cf85a7dc | |
|
3892bb6923 | |
|
8d4942731d | |
|
507d5ed276 | |
|
84955599de | |
|
aca50ec87a | |
|
ff3f025133 | |
|
54bdba1abd | |
|
0e6cb322de | |
|
33d1ef1c12 | |
|
1ac7849fe3 | |
|
35efc054c7 | |
|
a4d13552c0 | |
|
f86982a33c | |
|
e8f2bfaf5f | |
|
c0c5d93a48 | |
|
6acf26f973 | |
|
72bd204597 | |
|
f2bcd82160 | |
|
db72276b92 | |
|
cd1aa0133a | |
|
d166c951fa | |
|
c32d090812 | |
|
677a3f5dd6 | |
|
5c83f5e261 | |
|
571c6106a7 | |
|
97dd9964f3 | |
|
6bff48467b | |
|
98cad0e1b4 | |
|
d5b6d1584c | |
|
b3145acf60 | |
|
5a3e585883 | |
|
f44e3928b4 | |
|
b74496fb15 | |
|
c4534e9546 | |
|
70db362e2a | |
|
e9517b7915 | |
|
6424416ec2 | |
|
f0319da3d4 | |
|
94e9253aba | |
|
31564d8284 | |
|
0a418e886a | |
|
496e7008c4 | |
|
4f0bee4d5f | |
|
1896f67d7d | |
|
6be9cec16e | |
|
a99daea5ce | |
|
4329bc4073 | |
|
5ccd892fce | |
|
5ba465f3c1 | |
|
3d168637d2 | |
|
5edcd1fcef | |
|
7e1aa7cfb9 | |
|
5ebb39f82b | |
|
a089d1b261 | |
|
7ccbf90029 | |
|
0c85efc227 | |
|
80e37578b1 | |
|
5426ada8f3 | |
|
fae9f0e3ff | |
|
414560396a | |
|
d5f6fd59b1 | |
|
97a599c885 | |
|
18c31e3a42 | |
|
d969d314b3 | |
|
b1e58fa0b8 | |
|
f483ca37f5 | |
|
1a0bd102e8 | |
|
16de532213 | |
|
0236b2bcdb | |
|
0b8aae4f0f | |
|
eea82c993f | |
|
3e6c9b1dde | |
|
c5175395f7 | |
|
208dc05cdb | |
|
85358464ce | |
|
5c23d3343d | |
|
ec1fba2d50 | |
|
f5d637454a | |
|
5d9b941471 | |
|
d1b722c0f3 | |
|
e7338f7c92 | |
|
a8c293bc3a | |
|
ada0b75e79 | |
|
cd013d6cf8 | |
|
84f7a7db32 | |
|
2ab5ddc5dc | |
|
7a1411c283 | |
|
d8c9407792 | |
|
e36e0b43d5 | |
|
1363b4a9b5 | |
|
f2a660712e | |
|
5be9b380e5 | |
|
0cd17dfe29 | |
|
4af1eb6fd3 | |
|
1b06ea2af5 | |
|
0b382154c8 | |
|
04831c8dcd | |
|
6a5344ef67 | |
|
3393d989d9 | |
|
d2a36b95d6 | |
|
cacd7a914f | |
|
62c80f65fe | |
|
bfe92977de | |
|
5490a1cf23 | |
|
40261c9217 | |
|
ea22552f7d | |
|
740935a204 | |
|
40a98fe4ec | |
|
745ed18e1c | |
|
12cf3aa060 | |
|
fc8c9d8748 | |
|
d50ad908d7 | |
|
b1e9b43294 | |
|
543c9782be | |
|
8a42a77519 | |
|
4e55f26a41 | |
|
f2bdaa0454 | |
|
f6392d2d5c | |
|
1da34cf894 | |
|
8c687dcb7e | |
|
43e4088690 | |
|
e04a139a7e | |
|
1a4f73c37e | |
|
6311915310 | |
|
d76131c8e7 | |
|
bb83fd85b5 | |
|
06de3fde9a | |
|
fcd4a2fad7 | |
|
56ad6b6b44 | |
|
51c9e35848 | |
|
82c8252a72 | |
|
2dfdade8c6 | |
|
de4dd5b2c4 | |
|
9d019d9ebd | |
|
e258778fbb | |
|
c731887ba5 | |
|
8cb4bafeba | |
|
06fa7e9f56 | |
|
3af167442b | |
|
6c795d071d | |
|
99baed7038 | |
|
782f226a27 | |
|
7b4abdb0ca | |
|
397ca25d77 | |
|
4d1c7181d8 | |
|
ac5868787a | |
|
e92721e597 | |
|
7bd3455427 | |
|
83dd6d33bb | |
|
2eabb0d09d | |
|
d2446ba3f1 | |
|
47d0b40e81 | |
|
186151db68 | |
|
adf718d647 | |
|
c782905c29 | |
|
eeb5530f61 | |
|
e291a0415b | |
|
a1021f9dc3 | |
|
790b959054 | |
|
990830c395 | |
|
1cd0ce17a5 | |
|
df5fdf9595 | |
|
1a625efab6 | |
|
330d4e3043 | |
|
06be8ea6f4 | |
|
5544fd047d | |
|
29e6a45277 | |
|
aaae85b4df | |
|
1b9d5bcd46 | |
|
ca9c05a17f | |
|
0c12ad2b7b | |
|
d5e47d7240 | |
|
fedcc44672 | |
|
afff3e4776 | |
|
8dad073cd9 | |
|
d802de67fc | |
|
33f66d3b3b | |
|
3c9b1077f2 | |
|
4c1b209034 | |
|
5744aa9063 | |
|
d51781fe5c | |
|
d2c2d0fb39 | |
|
35a3ad1867 | |
|
510dfbdd23 | |
|
a9e470098e | |
|
223e3a5da5 | |
|
345a7c1f9e | |
|
20cad6f581 | |
|
e2509daa49 | |
|
d8a07aece2 | |
|
59157fb1a3 | |
|
6fb6728fae | |
|
e02eee26e3 | |
|
d3ebf69bb8 | |
|
5fc1a68efa | |
|
3e9b78d6ef | |
|
e055bee1b5 | |
|
1c860043c3 | |
|
7d4dfe3ee3 | |
|
f3cb8af809 | |
|
341702741d | |
|
cb82e03294 | |
|
f7911edd60 | |
|
214f0b5587 | |
|
6308351a45 | |
|
0e8da5a556 | |
|
8fb21c5fb4 | |
|
b85ba98d85 | |
|
ad7729cfb7 | |
|
4796069ff8 | |
|
a43127dd2b | |
|
04865ae530 | |
|
e2fdb5ce45 | |
|
3b3409beff | |
|
c6cdada9e3 | |
|
56726e2c3f | |
|
08974d8213 | |
|
72a2dfebc9 | |
|
3e2fade8c3 | |
|
3ab09a3dd8 | |
|
b17231a2c5 | |
|
bcfdd31734 | |
|
cb41e27ae3 | |
|
10f9650a2f | |
|
e05c07799d | |
|
71cda72b8a | |
|
755c1b9f30 | |
|
6a198f90df | |
|
aa0734bf4c | |
|
442737c27c | |
|
e1106a7eb0 | |
|
1dcd7a1402 | |
|
108284df8e | |
|
51260fd22d | |
|
901b9adb8a | |
|
39fbb4ac05 | |
|
e31cb5bb9e | |
|
2673eb0f8e | |
|
776d1e5fa3 | |
|
0cf9ec4759 | |
|
7f832d4b16 | |
|
17dee96166 | |
|
4e62b81595 | |
|
d6711d83b3 | |
|
004cccf3c2 | |
|
f83f20070b | |
|
969ed8c89c | |
|
ab872f2622 | |
|
59807b90e6 | |
|
4b2b5829dd | |
|
3d81d18439 | |
|
e3814c5a2e | |
|
ba23449ce5 | |
|
0f268583c9 | |
|
86cb2242e7 | |
|
b64c1dc907 | |
|
de312f9940 | |
|
88b535d3fb | |
|
d5f2af6739 | |
|
7ab7c688c3 | |
|
5fb760bab1 | |
|
3ba323f470 | |
|
d30580d5d4 | |
|
e2f2ff0763 | |
|
363e85e363 | |
|
647ee245e0 | |
|
f268f7cd65 | |
|
28c02fc9e9 | |
|
48357831cd | |
|
db3acce70c | |
|
fadda43d13 | |
|
d87fa860e6 | |
|
c34f00f759 | |
|
254d4d75a2 | |
|
ae68667f5e | |
|
7bede2528f | |
|
f0d3d085c6 | |
|
c00109074a | |
|
61af2a0554 | |
|
210a4f61cb | |
|
e2c2e8bead | |
|
b834a78376 | |
|
ae1b0c4cac | |
|
65ed08409b | |
|
fc06558687 | |
|
81cf14fbc1 | |
|
4be130b71b | |
|
ff2f43bdc5 | |
|
d1b6161687 | |
|
6903e058d5 | |
|
e9cd16aaac | |
|
55bff96807 | |
|
83b38897e6 | |
|
6e4c4158fb | |
|
88828bbee7 | |
|
d6e585e8c0 | |
|
b5cfd7612b | |
|
13a36e8f06 | |
|
951c648311 | |
|
ee63ebc7ac | |
|
50480989de | |
|
7e29efbc4e | |
|
09406f4f92 | |
|
ce4bb43dee | |
|
2aee86fc2b | |
|
19b82fa726 | |
|
1a9bb949ff | |
|
d6efc7e957 | |
|
a5a27cb239 | |
|
61bb34942f | |
|
7f1894c5be | |
|
59c69de63d | |
|
5b97841699 | |
|
85194fa94d | |
|
7b360a7bb3 | |
|
cdd92ab4ed | |
|
53b8442309 | |
|
b897f7c25f | |
|
97e34d716d | |
|
7503bd4b9e | |
|
44cb787577 | |
|
08c1bb33c7 | |
|
9c06bd580b | |
|
b57f6dcbf1 | |
|
da7d08862e | |
|
188e8f1481 | |
|
e0d30e4112 | |
|
fffd4b17ee | |
|
b84bc0921c | |
|
b60237d455 | |
|
c328f9c75a | |
|
c856191659 | |
|
ffb957ff19 | |
|
81517dc3c7 | |
|
9c7dfb4daf | |
|
f53efaf832 | |
|
d82b1c7ed3 | |
|
a8fb0528c9 | |
|
bcc6929a18 | |
|
9e143c421a | |
|
4a57679f6f | |
|
8d32b56852 | |
|
a347b4a9bb | |
|
bdbb7d79fd | |
|
fdded6be9f | |
|
42f22b2d4c | |
|
98efa35183 | |
|
696bcc7ba6 | |
|
2f7672b489 | |
|
75e1e5ce51 | |
|
b014f50821 | |
|
b90f5fb85b | |
|
c27a8d359c | |
|
136b9e4b6e | |
|
bce1110b13 | |
|
a1ae03f9cf | |
|
e84be5e4de | |
|
80647c04f4 | |
|
f431325516 | |
|
427251a4f3 | |
|
650a97647a | |
|
24804d3f12 | |
|
04a835a282 | |
|
d89f8e0e66 | |
|
92493e826c | |
|
c11e4b9f15 |
|
@ -2,6 +2,12 @@
|
|||
<!DOCTYPE module PUBLIC
|
||||
"-//Puppy Crawl//DTD Check Configuration 1.3//EN"
|
||||
"http://www.puppycrawl.com/dtds/configuration_1_3.dtd">
|
||||
<!--
|
||||
Note: Checkstyle likes to introduce breaking changes like removing support for certain properties. Since this
|
||||
configuration is also used by CodeClimate, we should keep it in sync with the version that they use:
|
||||
https://github.com/codeclimate/codeclimate-checkstyle/blob/master/bin/install-checkstyle.sh
|
||||
https://docs.codeclimate.com/docs/checkstyle (currently outdated)
|
||||
-->
|
||||
|
||||
<module name="Checker">
|
||||
<property name="charset" value="UTF-8"/>
|
||||
|
@ -10,6 +16,11 @@
|
|||
|
||||
<module name="SuppressWarningsFilter" />
|
||||
|
||||
<module name="LineLength">
|
||||
<property name="max" value="120"/>
|
||||
<property name="ignorePattern" value="^package.*|^import.*|a href|href|http://|https://|ftp://"/>
|
||||
</module>
|
||||
|
||||
<module name="TreeWalker">
|
||||
<module name="SuppressWarningsHolder"/>
|
||||
<module name="OuterTypeFilename"/>
|
||||
|
@ -23,10 +34,6 @@
|
|||
<property name="allowByTailComment" value="true"/>
|
||||
<property name="allowNonPrintableEscapes" value="true"/>
|
||||
</module>
|
||||
<module name="LineLength">
|
||||
<property name="max" value="120"/>
|
||||
<property name="ignorePattern" value="^package.*|^import.*|a href|href|http://|https://|ftp://"/>
|
||||
</module>
|
||||
<module name="TodoComment">
|
||||
<!-- Allow comments which have an issue number as they are accounted for in the issue tracker -->
|
||||
<property name="format" value="TODO(?! #\d+:)|FIXME"/>
|
||||
|
@ -142,23 +149,27 @@
|
|||
<property name="allowSamelineMultipleAnnotations" value="true"/>
|
||||
</module>
|
||||
<module name="NonEmptyAtclauseDescription"/>
|
||||
<module name="JavadocTagContinuationIndentation"/>
|
||||
<module name="JavadocTagContinuationIndentation">
|
||||
<property name="offset" value="2"/>
|
||||
</module>
|
||||
<module name="AtclauseOrder">
|
||||
<property name="tagOrder" value="@param, @return, @throws, @deprecated"/>
|
||||
<property name="target" value="CLASS_DEF, INTERFACE_DEF, ENUM_DEF, METHOD_DEF, CTOR_DEF, VARIABLE_DEF"/>
|
||||
</module>
|
||||
<module name="JavadocMethod">
|
||||
<property name="scope" value="package"/>
|
||||
<property name="allowMissingThrowsTags" value="true"/>
|
||||
<property name="minLineCount" value="4"/>
|
||||
<property name="allowedAnnotations" value="Override, Test, SectionComments, EventHandler, Before, BeforeClass"/>
|
||||
<property name="allowedAnnotations" value="Override, EventHandler"/>
|
||||
<property name="tokens" value="METHOD_DEF, ANNOTATION_FIELD_DEF"/> <!-- exclude CTOR_DEF -->
|
||||
</module>
|
||||
<module name="JavadocMethod">
|
||||
<module name="MissingJavadocMethod">
|
||||
<property name="scope" value="package"/>
|
||||
<property name="minLineCount" value="4"/>
|
||||
<property name="allowedAnnotations" value="Override, EventHandler"/>
|
||||
<property name="tokens" value="METHOD_DEF, ANNOTATION_FIELD_DEF"/> <!-- exclude CTOR_DEF -->
|
||||
</module>
|
||||
<module name="MissingJavadocMethod">
|
||||
<property name="scope" value="private"/>
|
||||
<property name="allowMissingThrowsTags" value="true"/>
|
||||
<property name="minLineCount" value="16"/>
|
||||
<property name="allowedAnnotations" value="Override, Test, SectionComments, EventHandler"/>
|
||||
<property name="allowedAnnotations" value="Override, EventHandler"/>
|
||||
<property name="tokens" value="METHOD_DEF, ANNOTATION_FIELD_DEF"/> <!-- exclude CTOR_DEF -->
|
||||
</module>
|
||||
<!-- TODO Checkstyle/#4089: need "allowedAnnotations" property to skip @Comment fields
|
||||
|
@ -181,6 +192,12 @@
|
|||
<module name="MissingOverride"/>
|
||||
<module name="EqualsHashCode"/>
|
||||
<module name="EqualsAvoidNull"/>
|
||||
<module name="Regexp">
|
||||
<property name="format" value="\.to(Lower|Upper)Case\(\)"/>
|
||||
<property name="illegalPattern" value="true"/>
|
||||
<property name="ignoreComments" value="true"/>
|
||||
<property name="message" value="Use toLowerCase/toUpperCase with Locale"/>
|
||||
</module>
|
||||
</module>
|
||||
<module name="FileTabCharacter"/>
|
||||
</module>
|
||||
|
|
|
@ -0,0 +1,83 @@
|
|||
name: Bug report
|
||||
description: Create a report to help us improve
|
||||
labels: 'Type: bug'
|
||||
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
Before reporting an issue make sure you are running the latest build of the plugin and checked for duplicate issues!
|
||||
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: What behaviour is observed?
|
||||
description: A clear and concise description of what the behavior is.
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Expected behaviour
|
||||
description: A clear and concise description of what you expected to happen.
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: To Reproduce
|
||||
description: Steps to reproduce this behaviour
|
||||
placeholder: |
|
||||
1. Go to '...'
|
||||
2. Click on '...'
|
||||
3. Scroll down to '...'
|
||||
4. See error
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Plugin list
|
||||
description: This can be found by running `/pl`
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: dropdown
|
||||
attributes:
|
||||
label: Server Implementation
|
||||
description: Which server implementation are you using?
|
||||
multiple: false
|
||||
options:
|
||||
- Standalone server (no proxy)
|
||||
- BungeeCord
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: dropdown
|
||||
attributes:
|
||||
label: Database Implementation
|
||||
description: Which database implementation are you using?
|
||||
multiple: false
|
||||
options:
|
||||
- SQLite
|
||||
- MySQL
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: input
|
||||
attributes:
|
||||
label: AuthMe Version
|
||||
description: What version of AuthMe are you running? (`/authme version`)
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: input
|
||||
attributes:
|
||||
label: Error log (if applicable)
|
||||
description: If you are reporting a console error, upload any relevant log excerpts to either https://paste.gg/ or https://gist.github.com, save and the paste the link in this box.
|
||||
|
||||
- type: input
|
||||
attributes:
|
||||
label: Configuration
|
||||
description: Link of your config.yml file (remember to delete any sensitive data), upload any relevant log excerpts to either https://paste.gg/ or https://gist.github.com, save and the paste the link in this box.
|
||||
validations:
|
||||
required: true
|
|
@ -0,0 +1 @@
|
|||
blank_issues_enabled: false
|
|
@ -0,0 +1,28 @@
|
|||
name: Feature request
|
||||
description: Suggest an idea for AuthMe
|
||||
labels: 'Type: enhancement'
|
||||
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
Thanks for taking the time to fill out this feature request for AuthMe! Fill out the following form to your best ability to help us understand your feature request and greately improve the change of it getting added.
|
||||
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: What feature do you want to see added?
|
||||
description: A clear and concise description of your feature request.
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Are there any alternatives?
|
||||
description: List any alternatives you might have tried
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Anything else?
|
||||
description: You can provide additional context below.
|
|
@ -0,0 +1,14 @@
|
|||
version: 2
|
||||
updates:
|
||||
- package-ecosystem: maven
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: daily
|
||||
open-pull-requests-limit: 10
|
||||
ignore:
|
||||
- dependency-name: com.google.code.gson:gson
|
||||
- dependency-name: com.google.guava:guava
|
||||
- dependency-name: org.apache.logging.log4j:log4j-core
|
||||
- dependency-name: com.zaxxer:HikariCP
|
||||
- dependency-name: "org.mockito:mockito-core" # Mockito 5 requires Java 11
|
||||
versions: ">= 5"
|
|
@ -0,0 +1,23 @@
|
|||
name: Java CI
|
||||
|
||||
on:
|
||||
push:
|
||||
pull_request:
|
||||
branches:
|
||||
- master
|
||||
|
||||
jobs:
|
||||
build_and_test:
|
||||
strategy:
|
||||
matrix:
|
||||
jdkversion: [11]
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-java@v3
|
||||
with:
|
||||
distribution: 'temurin'
|
||||
java-version: ${{ matrix.jdkversion }}
|
||||
cache: 'maven'
|
||||
- name: Build with Maven
|
||||
run: mvn -V -B clean package --file pom.xml
|
37
.travis.yml
37
.travis.yml
|
@ -1,10 +1,35 @@
|
|||
sudo: false
|
||||
dist: trusty
|
||||
dist: focal
|
||||
|
||||
language: java
|
||||
jdk:
|
||||
- oraclejdk8
|
||||
- openjdk11
|
||||
|
||||
matrix:
|
||||
include:
|
||||
- env:
|
||||
- JDK_VERSION=8
|
||||
- env:
|
||||
- JDK_VERSION=11
|
||||
- env:
|
||||
- JDK_VERSION=17
|
||||
|
||||
before_install:
|
||||
- "[[ -d $HOME/.sdkman/ ]] && [[ -d $HOME/.sdkman/bin/ ]] || rm -rf $HOME/.sdkman/"
|
||||
- curl -s "https://get.sdkman.io" | bash
|
||||
- mkdir -p "$HOME/.sdkman/etc/"
|
||||
- echo sdkman_auto_answer=true > "$HOME/.sdkman/etc/config"
|
||||
- echo sdkman_auto_selfupdate=true >> "$HOME/.sdkman/etc/config"
|
||||
- source "$HOME/.sdkman/bin/sdkman-init.sh"
|
||||
|
||||
install:
|
||||
- sdk install java $(sdk list java | grep -o "$JDK_VERSION\.[0-9]*\.[0-9]*\-open" | head -1)
|
||||
- sdk install maven
|
||||
- export JAVA_HOME="$HOME/.sdkman/candidates/java/current"
|
||||
- export PATH=${JAVA_HOME}/bin:${PATH}
|
||||
- export MAVEN_HOME="$HOME/.sdkman/candidates/maven/current"
|
||||
- export M2_HOME="$MAVEN_HOME"
|
||||
- export PATH=${M2_HOME}/bin:${PATH}
|
||||
- env
|
||||
- mvn -v
|
||||
|
||||
cache:
|
||||
directories:
|
||||
- '$HOME/.m2/repository'
|
||||
- $HOME/.m2/repository
|
||||
|
|
40
README.md
40
README.md
|
@ -1,13 +1,14 @@
|
|||
# AuthMeReloaded
|
||||
**"The best authentication plugin for the Bukkit modding API!"**
|
||||
<img src="http://i63.tinypic.com/rtp06o.png" alt="AuthMeLogo" style="width: 250px;"/>
|
||||
|
||||
<img src="wallpaper.png?raw=true" alt="AuthMeLogo"/>
|
||||
|
||||
| Type | Badges |
|
||||
|-------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| **General:** | ![](https://tokei.rs/b1/github/AuthMe/AuthMeReloaded?category=code) ![](https://tokei.rs/b1/github/AuthMe/AuthMeReloaded?category=files) |
|
||||
| **Code quality:** | [![Code Climate](https://codeclimate.com/github/AuthMe/AuthMeReloaded/badges/gpa.svg)](https://codeclimate.com/github/AuthMe/AuthMeReloaded) [![Coverage status](https://coveralls.io/repos/AuthMe-Team/AuthMeReloaded/badge.svg?branch=master&service=github)](https://coveralls.io/github/AuthMe-Team/AuthMeReloaded?branch=master) |
|
||||
| **Jenkins CI:** | [![Jenkins Status](https://img.shields.io/website-up-down-green-red/http/shields.io.svg?label=ci.codemc.org)](https://ci.codemc.org/) [![Build Status](https://ci.codemc.org/buildStatus/icon?job=AuthMe/AuthMeReloaded)](https://ci.codemc.org/job/AuthMe/job/AuthMeReloaded) ![Build Tests](https://img.shields.io/jenkins/t/https/ci.codemc.org/job/AuthMe/job/AuthMeReloaded.svg) |
|
||||
| **Other CIs:** | [![Build Status](https://travis-ci.org/AuthMe/AuthMeReloaded.svg?branch=master)](https://travis-ci.org/AuthMe/AuthMeReloaded) |
|
||||
| **Other CIs:** | [![Build Status](https://www.travis-ci.com/AuthMe/AuthMeReloaded.svg?branch=master)](https://www.travis-ci.com/AuthMe/AuthMeReloaded) |
|
||||
|
||||
## Description
|
||||
|
||||
|
@ -24,16 +25,17 @@ You can also create your own translation file and, if you want, you can share it
|
|||
|
||||
#### Features:
|
||||
<ul>
|
||||
<li><strong>E-Mail Recovery System !!!</strong></li>
|
||||
<li><strong>E-Mail Recovery System!</strong></li>
|
||||
<li>Username spoofing protection.</li>
|
||||
<li>Countries Whitelist/Blacklist! <a href="https://dev.maxmind.com/geoip/legacy/codes/iso3166/">(country codes)</a></li>
|
||||
<li><strong>Built-in AntiBot System!</strong></li>
|
||||
<li><strong>ForceLogin Feature: Admins can login with all account via console command!</strong></li>
|
||||
<li><strong>Avoid the "Logged in from another location" message!</strong></li>
|
||||
<li>Two-factor (2FA) support!</li>
|
||||
<li>Session Login!</li>
|
||||
<li>Editable translations and messages!</li>
|
||||
<li><strong>MySQL and SQLite Backend support!</strong></li>
|
||||
<li>Supported password encryption algorithms: SHA256, BCRYPT, PBKDF2, <a href="https://github.com/CypherX/xAuth/wiki/Password-Hashing">xAuth</a></li>
|
||||
<li>Supported password encryption algorithms: SHA256, ARGON2, BCRYPT, PBKDF2, <a href="https://github.com/CypherX/xAuth/wiki/Password-Hashing">xAuth</a></li>
|
||||
<li>Supported alternative registration methods:<br>
|
||||
<ul>
|
||||
<li>PHPBB, VBulletin: PHPBB - MD5VB</li>
|
||||
|
@ -83,13 +85,30 @@ You can also create your own translation file and, if you want, you can share it
|
|||
|
||||
- **Support:**
|
||||
- [GitHub issue tracker](https://github.com/AuthMe/AuthMeReloaded/issues)
|
||||
- [Discord](https://discord.gg/Vn9eCyE)
|
||||
- [BukkitDev page](https://dev.bukkit.org/projects/authme-reloaded)
|
||||
- [Spigot page](https://www.spigotmc.org/resources/authmereloaded.6269/)
|
||||
- [Discord](https://discord.gg/Vn9eCyE)
|
||||
|
||||
- **Dev resources:**
|
||||
- <a href="https://ci.codemc.org/job/AuthMe/job/AuthMeReloaded/javadoc/">JavaDocs</a>
|
||||
- <a href="http://repo.codemc.org/repository/maven-public/">Maven Repository</a>
|
||||
```xml
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>codemc-repo</id>
|
||||
<url>https://repo.codemc.org/repository/maven-public/</url>
|
||||
</repository>
|
||||
</repositories>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>fr.xephi</groupId>
|
||||
<artifactId>authme</artifactId>
|
||||
<version>5.6.0-SNAPSHOT</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
```
|
||||
|
||||
- **Statistics:**
|
||||
![Graph](https://bstats.org/signatures/bukkit/AuthMe.svg)
|
||||
|
@ -97,26 +116,23 @@ You can also create your own translation file and, if you want, you can share it
|
|||
## Requirements
|
||||
|
||||
##### Compiling requirements:
|
||||
>- JDK 1.8
|
||||
>- JDK 11 (JDK 17 is recommended)
|
||||
>- Maven
|
||||
>- Git/Github (Optional)
|
||||
|
||||
##### How to compile the project:
|
||||
>- Clone the project with Git/Github
|
||||
>- Clone the project with Git/GitHub
|
||||
>- Execute command "mvn clean package"
|
||||
|
||||
##### Running requirements:
|
||||
>- Java 1.8
|
||||
>- TacoSpigot, PaperSpigot or Spigot (1.7.10, 1.8.X, 1.9.X, 1.10.X, 1.11.X, 1.12.X)<br>
|
||||
>- Java 8 (Java 17 is recommended)
|
||||
>- Paper or Spigot (1.8.X and up)<br>
|
||||
(In case you use Thermos, Cauldron or similar, you have to update the SpecialSource library to support Java 8 plugins.
|
||||
HowTo: https://github.com/games647/FastLogin/issues/111#issuecomment-272331347)
|
||||
>- ProtocolLib (optional, required by some features)
|
||||
|
||||
## Credits
|
||||
|
||||
##### Sponsor:
|
||||
[FastVM.io](https://fastvm.io) is leader in VPS hosting solutions. With its own DataCenter offers Anti-DDoS solutions at affordable prices.
|
||||
|
||||
##### Contributors:
|
||||
Team members: <a href="https://github.com/AuthMe/AuthMeReloaded/wiki/Development-team">developers</a>, <a href="https://github.com/AuthMe/AuthMeReloaded/wiki/Translators">translators</a>
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<!-- AUTO-GENERATED FILE! Do not edit this directly -->
|
||||
<!-- File auto-generated on Sun Apr 22 11:00:10 CEST 2018. See docs/commands/commands.tpl.md -->
|
||||
<!-- File auto-generated on Sun Apr 04 21:31:42 CEST 2021. See docs/commands/commands.tpl.md -->
|
||||
|
||||
## AuthMe Commands
|
||||
You can use the following commands to use the features of AuthMe. Mandatory arguments are marked with `< >`
|
||||
|
@ -24,6 +24,10 @@ brackets; optional arguments are enclosed in square brackets (`[ ]`).
|
|||
<br />Requires `authme.admin.changemail`
|
||||
- **/authme getip** <player>: Get the IP address of the specified online player.
|
||||
<br />Requires `authme.admin.getip`
|
||||
- **/authme totp** <player>: Returns whether the specified player has enabled two-factor authentication.
|
||||
<br />Requires `authme.admin.totpviewstatus`
|
||||
- **/authme disabletotp** <player>: Disable two-factor authentication for a player.
|
||||
<br />Requires `authme.admin.totpdisable`
|
||||
- **/authme spawn**: Teleport to the spawn.
|
||||
<br />Requires `authme.admin.spawn`
|
||||
- **/authme setspawn**: Change the player's spawn to your current position.
|
||||
|
@ -104,4 +108,4 @@ brackets; optional arguments are enclosed in square brackets (`[ ]`).
|
|||
|
||||
---
|
||||
|
||||
This page was automatically generated on the [AuthMe/AuthMeReloaded repository](https://github.com/AuthMe/AuthMeReloaded/tree/master/docs/) on Sun Apr 22 11:00:10 CEST 2018
|
||||
This page was automatically generated on the [AuthMe/AuthMeReloaded repository](https://github.com/AuthMe/AuthMeReloaded/tree/master/docs/) on Sun Apr 04 21:31:42 CEST 2021
|
||||
|
|
180
docs/config.md
180
docs/config.md
|
@ -1,72 +1,80 @@
|
|||
<!-- AUTO-GENERATED FILE! Do not edit this directly -->
|
||||
<!-- File auto-generated on Mon May 21 09:08:25 CEST 2018. See docs/config/config.tpl.md -->
|
||||
<!-- File auto-generated on Thu Jul 28 18:11:22 CEST 2022. See docs/config/config.tpl.md -->
|
||||
|
||||
## AuthMe Configuration
|
||||
The first time you run AuthMe it will create a config.yml file in the plugins/AuthMe folder,
|
||||
with which you can configure various settings. This following is the initial contents of
|
||||
The first time you run AuthMe it will create a config.yml file in the plugins/AuthMe folder,
|
||||
with which you can configure various settings. The following is the initial contents of
|
||||
the generated config.yml file.
|
||||
|
||||
```yml
|
||||
|
||||
DataSource:
|
||||
# What type of database do you want to use?
|
||||
# Valid values: SQLITE, MYSQL
|
||||
backend: 'SQLITE'
|
||||
# Valid values: SQLITE, MARIADB, MYSQL, POSTGRESQL
|
||||
backend: SQLITE
|
||||
# Enable the database caching system, should be disabled on bungeecord environments
|
||||
# or when a website integration is being used.
|
||||
caching: true
|
||||
# Database host address
|
||||
mySQLHost: '127.0.0.1'
|
||||
mySQLHost: 127.0.0.1
|
||||
# Database port
|
||||
mySQLPort: '3306'
|
||||
# Connect to MySQL database over SSL
|
||||
mySQLUseSSL: true
|
||||
# Verification of server's certificate.
|
||||
# We would not recommend to set this option to false.
|
||||
# Set this option to false at your own risk if and only if you know what you're doing
|
||||
mySQLCheckServerCertificate: true
|
||||
# Authorize client to retrieve RSA server public key.
|
||||
# Advanced option, ignore if you don't know what it means.
|
||||
mySQLAllowPublicKeyRetrieval: true
|
||||
# Username to connect to the MySQL database
|
||||
mySQLUsername: 'authme'
|
||||
mySQLUsername: authme
|
||||
# Password to connect to the MySQL database
|
||||
mySQLPassword: '12345'
|
||||
# Database Name, use with converters or as SQLITE database name
|
||||
mySQLDatabase: 'authme'
|
||||
mySQLDatabase: authme
|
||||
# Table of the database
|
||||
mySQLTablename: 'authme'
|
||||
mySQLTablename: authme
|
||||
# Column of IDs to sort data
|
||||
mySQLColumnId: 'id'
|
||||
mySQLColumnId: id
|
||||
# Column for storing or checking players nickname
|
||||
mySQLColumnName: 'username'
|
||||
mySQLColumnName: username
|
||||
# Column for storing or checking players RealName
|
||||
mySQLRealName: 'realname'
|
||||
mySQLRealName: realname
|
||||
# Column for storing players passwords
|
||||
mySQLColumnPassword: 'password'
|
||||
mySQLColumnPassword: password
|
||||
# Column for storing players passwords salts
|
||||
mySQLColumnSalt: ''
|
||||
# Column for storing players emails
|
||||
mySQLColumnEmail: 'email'
|
||||
mySQLColumnEmail: email
|
||||
# Column for storing if a player is logged in or not
|
||||
mySQLColumnLogged: 'isLogged'
|
||||
mySQLColumnLogged: isLogged
|
||||
# Column for storing if a player has a valid session or not
|
||||
mySQLColumnHasSession: 'hasSession'
|
||||
mySQLColumnHasSession: hasSession
|
||||
# Column for storing a player's TOTP key (for two-factor authentication)
|
||||
mySQLtotpKey: 'totp'
|
||||
mySQLtotpKey: totp
|
||||
# Column for storing the player's last IP
|
||||
mySQLColumnIp: 'ip'
|
||||
mySQLColumnIp: ip
|
||||
# Column for storing players lastlogins
|
||||
mySQLColumnLastLogin: 'lastlogin'
|
||||
mySQLColumnLastLogin: lastlogin
|
||||
# Column storing the registration date
|
||||
mySQLColumnRegisterDate: 'regdate'
|
||||
mySQLColumnRegisterDate: regdate
|
||||
# Column for storing the IP address at the time of registration
|
||||
mySQLColumnRegisterIp: 'regip'
|
||||
mySQLColumnRegisterIp: regip
|
||||
# Column for storing player LastLocation - X
|
||||
mySQLlastlocX: 'x'
|
||||
mySQLlastlocX: x
|
||||
# Column for storing player LastLocation - Y
|
||||
mySQLlastlocY: 'y'
|
||||
mySQLlastlocY: y
|
||||
# Column for storing player LastLocation - Z
|
||||
mySQLlastlocZ: 'z'
|
||||
mySQLlastlocZ: z
|
||||
# Column for storing player LastLocation - World Name
|
||||
mySQLlastlocWorld: 'world'
|
||||
mySQLlastlocWorld: world
|
||||
# Column for storing player LastLocation - Yaw
|
||||
mySQLlastlocYaw: 'yaw'
|
||||
mySQLlastlocYaw: yaw
|
||||
# Column for storing player LastLocation - Pitch
|
||||
mySQLlastlocPitch: 'pitch'
|
||||
mySQLlastlocPitch: pitch
|
||||
# Column for storing players uuids (optional)
|
||||
mySQLPlayerUUID: ''
|
||||
# Overrides the size of the DB Connection Pool, default = 10
|
||||
poolSize: 10
|
||||
# The maximum lifetime of a connection in the pool, default = 1800 seconds
|
||||
|
@ -82,21 +90,21 @@ ExternalBoardOptions:
|
|||
# Other MySQL columns where we need to put the username (case-sensitive)
|
||||
mySQLOtherUsernameColumns: []
|
||||
# How much log2 rounds needed in BCrypt (do not change if you do not know what it does)
|
||||
bCryptLog2Round: 10
|
||||
bCryptLog2Round: 12
|
||||
# phpBB table prefix defined during the phpBB installation process
|
||||
phpbbTablePrefix: 'phpbb_'
|
||||
phpbbTablePrefix: phpbb_
|
||||
# phpBB activated group ID; 2 is the default registered group defined by phpBB
|
||||
phpbbActivatedGroupId: 2
|
||||
# IP Board table prefix defined during the IP Board installation process
|
||||
IPBTablePrefix: 'ipb_'
|
||||
IPBTablePrefix: ipb_
|
||||
# IP Board default group ID; 3 is the default registered group defined by IP Board
|
||||
IPBActivatedGroupId: 3
|
||||
# Xenforo table prefix defined during the Xenforo installation process
|
||||
XFTablePrefix: 'xf_'
|
||||
XFTablePrefix: xf_
|
||||
# XenForo default group ID; 2 is the default registered group defined by Xenforo
|
||||
XFActivatedGroupId: 2
|
||||
# Wordpress prefix defined during WordPress installation
|
||||
wordpressTablePrefix: 'wp_'
|
||||
wordpressTablePrefix: wp_
|
||||
settings:
|
||||
sessions:
|
||||
# Do you want to enable the session feature?
|
||||
|
@ -111,20 +119,18 @@ settings:
|
|||
timeout: 10
|
||||
# Message language, available languages:
|
||||
# https://github.com/AuthMe/AuthMeReloaded/blob/master/docs/translations.md
|
||||
messagesLanguage: 'en'
|
||||
messagesLanguage: en
|
||||
# Forces authme to hook into Vault instead of a specific permission handler system.
|
||||
forceVaultHook: false
|
||||
# Log level: INFO, FINE, DEBUG. Use INFO for general messages,
|
||||
# FINE for some additional detailed ones (like password failed),
|
||||
# and DEBUG for debugging
|
||||
logLevel: 'FINE'
|
||||
logLevel: FINE
|
||||
# By default we schedule async tasks when talking to the database. If you want
|
||||
# typical communication with the database to happen synchronously, set this to false
|
||||
useAsyncTasks: true
|
||||
# By default we handle the AsyncPlayerPreLoginEvent which makes the plugin faster
|
||||
# but it is incompatible with any permission plugin not included in our compatibility list.
|
||||
# If you have issues with permission checks on player join please disable this option.
|
||||
useAsyncPreLoginEvent: true
|
||||
# The name of the server, used in some placeholders.
|
||||
serverName: Your Minecraft Server
|
||||
restrictions:
|
||||
# Can not authenticated players chat?
|
||||
# Keep in mind that this feature also blocks all commands not
|
||||
|
@ -134,14 +140,15 @@ settings:
|
|||
hideChat: false
|
||||
# Allowed commands for unauthenticated players
|
||||
allowCommands:
|
||||
- '/login'
|
||||
- '/register'
|
||||
- '/l'
|
||||
- '/reg'
|
||||
- '/email'
|
||||
- '/captcha'
|
||||
- '/2fa'
|
||||
- '/totp'
|
||||
- /login
|
||||
- /log
|
||||
- /l
|
||||
- /register
|
||||
- /reg
|
||||
- /email
|
||||
- /captcha
|
||||
- /2fa
|
||||
- /totp
|
||||
# Max number of allowed registrations per IP
|
||||
# The value 0 means an unlimited number of registrations!
|
||||
maxRegPerIp: 1
|
||||
|
@ -163,9 +170,9 @@ settings:
|
|||
# WorldNames where we need to force the spawn location
|
||||
# Case-sensitive!
|
||||
worlds:
|
||||
- 'world'
|
||||
- 'world_nether'
|
||||
- 'world_the_end'
|
||||
- world
|
||||
- world_nether
|
||||
- world_the_end
|
||||
# This option will save the quit location of the players.
|
||||
SaveQuitLocation: false
|
||||
# To activate the restricted user feature you need
|
||||
|
@ -207,7 +214,7 @@ settings:
|
|||
# permission: /authme.admin.accounts
|
||||
displayOtherAccounts: true
|
||||
# Spawn priority; values: authme, essentials, cmi, multiverse, default
|
||||
spawnPriority: 'authme,essentials,cmi,multiverse,default'
|
||||
spawnPriority: authme,essentials,cmi,multiverse,default
|
||||
# Maximum Login authorized by IP
|
||||
maxLoginPerIp: 0
|
||||
# Maximum Join authorized by IP
|
||||
|
@ -230,6 +237,14 @@ settings:
|
|||
# - 'npcPlayer'
|
||||
# - 'npcPlayer2'
|
||||
UnrestrictedName: []
|
||||
# Below you can list all inventories names that AuthMe will ignore
|
||||
# for registration or login. Configure it at your own risk!!
|
||||
# This option adds compatibility with some mods.
|
||||
# It is case-insensitive! Example:
|
||||
# UnrestrictedInventories:
|
||||
# - 'myCustomInventory1'
|
||||
# - 'myCustomInventory2'
|
||||
UnrestrictedInventories: []
|
||||
security:
|
||||
# Minimum length of password
|
||||
minPasswordLength: 5
|
||||
|
@ -240,7 +255,7 @@ settings:
|
|||
# PBKDF2DJANGO, WORDPRESS, ROYALAUTH, ARGON2, CUSTOM (for developers only). See full list at
|
||||
# https://github.com/AuthMe/AuthMeReloaded/blob/master/docs/hash_algorithms.md
|
||||
# If you use ARGON2, check that you have the argon2 c library on your system
|
||||
passwordHash: 'SHA256'
|
||||
passwordHash: SHA256
|
||||
# If a password check fails, AuthMe will also try to check with the following hash methods.
|
||||
# Use this setting when you change from one hash method to another.
|
||||
# AuthMe will update the password to the new hash. Example:
|
||||
|
@ -259,12 +274,12 @@ settings:
|
|||
# - 'help'
|
||||
unsafePasswords:
|
||||
- '123456'
|
||||
- 'password'
|
||||
- 'qwerty'
|
||||
- password
|
||||
- qwerty
|
||||
- '12345'
|
||||
- '54321'
|
||||
- '123456789'
|
||||
- 'help'
|
||||
- help
|
||||
registration:
|
||||
# Enable registration on the server?
|
||||
enabled: true
|
||||
|
@ -278,12 +293,12 @@ settings:
|
|||
# PASSWORD = account is registered with a password supplied by the user;
|
||||
# EMAIL = password is generated and sent to the email provided by the user.
|
||||
# More info at https://github.com/AuthMe/AuthMeReloaded/wiki/Registration
|
||||
type: 'PASSWORD'
|
||||
type: PASSWORD
|
||||
# Second argument the /register command should take: NONE = no 2nd argument
|
||||
# CONFIRMATION = must repeat first argument (pass or email)
|
||||
# EMAIL_OPTIONAL = for password register: 2nd argument can be empty or have email address
|
||||
# EMAIL_MANDATORY = for password register: 2nd argument MUST be an email address
|
||||
secondArg: 'CONFIRMATION'
|
||||
secondArg: CONFIRMATION
|
||||
# Do we force kick a player after a successful registration?
|
||||
# Do not use with login feature below
|
||||
forceKickAfterRegister: false
|
||||
|
@ -314,7 +329,7 @@ settings:
|
|||
removeJoinMessage: false
|
||||
# Should we remove leave messages altogether?
|
||||
removeLeaveMessage: false
|
||||
# Do we need to add potion effect Blinding before login/reigster?
|
||||
# Do we need to add potion effect Blinding before login/register?
|
||||
applyBlindEffect: false
|
||||
# Do we need to prevent people to login with another case?
|
||||
# If Xephi is registered, then Xephi can login, but not XEPHI/xephi/XePhI
|
||||
|
@ -339,7 +354,7 @@ GroupOptions:
|
|||
unregisteredPlayerGroup: ''
|
||||
Email:
|
||||
# Email SMTP server host
|
||||
mailSMTP: 'smtp.gmail.com'
|
||||
mailSMTP: smtp.gmail.com
|
||||
# Email SMTP server port
|
||||
mailPort: 465
|
||||
# Only affects port 25: enable TLS/STARTTLS?
|
||||
|
@ -355,7 +370,7 @@ Email:
|
|||
# Recovery password length
|
||||
RecoveryPasswordLength: 8
|
||||
# Mail Subject
|
||||
mailSubject: 'Your new AuthMe password'
|
||||
mailSubject: Your new AuthMe password
|
||||
# Like maxRegPerIP but with email
|
||||
maxRegPerEmail: 1
|
||||
# Recall players to add an email?
|
||||
|
@ -364,7 +379,7 @@ Email:
|
|||
delayRecall: 5
|
||||
# Blacklist these domains for emails
|
||||
emailBlacklisted:
|
||||
- '10minutemail.com'
|
||||
- 10minutemail.com
|
||||
# Whitelist ONLY these domains for emails
|
||||
emailWhitelisted: []
|
||||
# Send the new password drawn in an image?
|
||||
|
@ -387,16 +402,28 @@ Protection:
|
|||
enableProtection: false
|
||||
# Apply the protection also to registered usernames
|
||||
enableProtectionRegistered: true
|
||||
geoIpDatabase:
|
||||
# Enable GeoIp database
|
||||
enabled: true
|
||||
# The MaxMind clientId used to download the GeoIp database,
|
||||
# get one at https://www.maxmind.com/en/accounts/current/license-key
|
||||
# The EssentialsX project has a very useful tutorial on how to generate
|
||||
# the license key: https://github.com/EssentialsX/Wiki/blob/master/GeoIP.md
|
||||
clientId: ''
|
||||
# The MaxMind licenseKey used to download the GeoIp database.
|
||||
licenseKey: ''
|
||||
# Countries allowed to join the server and register. For country codes, see
|
||||
# https://dev.maxmind.com/geoip/legacy/codes/iso3166/
|
||||
# Use "LOCALHOST" for local addresses.
|
||||
# PLEASE USE QUOTES!
|
||||
countries:
|
||||
- 'US'
|
||||
- 'GB'
|
||||
- US
|
||||
- GB
|
||||
- LOCALHOST
|
||||
# Countries not allowed to join the server and register
|
||||
# PLEASE USE QUOTES!
|
||||
countriesBlacklist:
|
||||
- 'A1'
|
||||
- A1
|
||||
# Do we need to enable automatic antibot system?
|
||||
enableAntiBot: true
|
||||
# The interval in seconds
|
||||
|
@ -421,7 +448,7 @@ Purge:
|
|||
# Do we need to remove the Essentials/userdata/player.yml file during purge process?
|
||||
removeEssentialsFile: false
|
||||
# World in which the players.dat are stored
|
||||
defaultWorld: 'world'
|
||||
defaultWorld: world
|
||||
# Remove LimitedCreative/inventories/player.yml, player_creative.yml files during purge?
|
||||
removeLimitedCreativesInventories: false
|
||||
# Do we need to remove the AntiXRayData/PlayerData/player file during purge process?
|
||||
|
@ -498,7 +525,7 @@ limbo:
|
|||
# DISABLED: no disk storage,
|
||||
# INDIVIDUAL_FILES: each player data in its own file,
|
||||
# DISTRIBUTED_FILES: distributes players into different files based on their UUID, see below
|
||||
type: 'INDIVIDUAL_FILES'
|
||||
type: INDIVIDUAL_FILES
|
||||
# This setting only affects DISTRIBUTED_FILES persistence. The distributed file
|
||||
# persistence attempts to reduce the number of files by distributing players into various
|
||||
# buckets based on their UUID. This setting defines into how many files the players should
|
||||
|
@ -508,20 +535,20 @@ limbo:
|
|||
# 6.25 players per file (100 / 16).
|
||||
# Note: if you change this setting all data will be migrated. If you have a lot of data,
|
||||
# change this setting only on server restart, not with /authme reload.
|
||||
distributionSize: 'SIXTEEN'
|
||||
distributionSize: SIXTEEN
|
||||
# Whether the player is allowed to fly: RESTORE, ENABLE, DISABLE, NOTHING.
|
||||
# RESTORE sets back the old property from the player. NOTHING will prevent AuthMe
|
||||
# from modifying the 'allow flight' property on the player.
|
||||
restoreAllowFlight: 'RESTORE'
|
||||
restoreAllowFlight: RESTORE
|
||||
# Restore fly speed: RESTORE, DEFAULT, MAX_RESTORE, RESTORE_NO_ZERO.
|
||||
# RESTORE: restore the speed the player had;
|
||||
# DEFAULT: always set to default speed;
|
||||
# MAX_RESTORE: take the maximum of the player's current speed and the previous one
|
||||
# RESTORE_NO_ZERO: Like 'restore' but sets speed to default if the player's speed was 0
|
||||
restoreFlySpeed: 'RESTORE_NO_ZERO'
|
||||
restoreFlySpeed: RESTORE_NO_ZERO
|
||||
# Restore walk speed: RESTORE, DEFAULT, MAX_RESTORE, RESTORE_NO_ZERO.
|
||||
# See above for a description of the values.
|
||||
restoreWalkSpeed: 'RESTORE_NO_ZERO'
|
||||
restoreWalkSpeed: RESTORE_NO_ZERO
|
||||
BackupSystem:
|
||||
# General configuration for backups: if false, no backups are possible
|
||||
ActivateBackup: false
|
||||
|
@ -530,19 +557,19 @@ BackupSystem:
|
|||
# Create backup at every stop of server
|
||||
OnServerStop: true
|
||||
# Windows only: MySQL installation path
|
||||
MysqlWindowsPath: 'C:\Program Files\MySQL\MySQL Server 5.1\'
|
||||
MysqlWindowsPath: C:\Program Files\MySQL\MySQL Server 5.1\
|
||||
# Converter settings: see https://github.com/AuthMe/AuthMeReloaded/wiki/Converters
|
||||
Converter:
|
||||
Rakamak:
|
||||
# Rakamak file name
|
||||
fileName: 'users.rak'
|
||||
fileName: users.rak
|
||||
# Rakamak use IP?
|
||||
useIP: false
|
||||
# Rakamak IP file name
|
||||
ipFileName: 'UsersIp.rak'
|
||||
ipFileName: UsersIp.rak
|
||||
CrazyLogin:
|
||||
# CrazyLogin database file name
|
||||
fileName: 'accounts.db'
|
||||
fileName: accounts.db
|
||||
loginSecurity:
|
||||
# LoginSecurity: convert from SQLite; if false we use MySQL
|
||||
useSqlite: true
|
||||
|
@ -555,11 +582,12 @@ Converter:
|
|||
user: ''
|
||||
# LoginSecurity MySQL: password for database user
|
||||
password: ''
|
||||
|
||||
```
|
||||
|
||||
To change settings on a running server, save your changes to config.yml and use
|
||||
To change settings on a running server, save your changes to config.yml and use
|
||||
`/authme reload`.
|
||||
|
||||
---
|
||||
|
||||
This page was automatically generated on the [AuthMe/AuthMeReloaded repository](https://github.com/AuthMe/AuthMeReloaded/tree/master/docs/) on Mon May 21 09:08:25 CEST 2018
|
||||
This page was automatically generated on the [AuthMe/AuthMeReloaded repository](https://github.com/AuthMe/AuthMeReloaded/tree/master/docs/) on Thu Jul 28 18:11:22 CEST 2022
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<!-- AUTO-GENERATED FILE! Do not edit this directly -->
|
||||
<!-- File auto-generated on Sun Sep 02 20:38:48 CEST 2018. See docs/hashmethods/hash_algorithms.tpl.md -->
|
||||
<!-- File auto-generated on Sun Apr 04 21:31:44 CEST 2021. See docs/hashmethods/hash_algorithms.tpl.md -->
|
||||
|
||||
## Hash Algorithms
|
||||
AuthMe supports the following hash algorithms for storing your passwords safely.
|
||||
|
@ -80,4 +80,4 @@ or bad.
|
|||
|
||||
---
|
||||
|
||||
This page was automatically generated on the [AuthMe/AuthMeReloaded repository](https://github.com/AuthMe/AuthMeReloaded/tree/master/docs/) on Sun Sep 02 20:38:48 CEST 2018
|
||||
This page was automatically generated on the [AuthMe/AuthMeReloaded repository](https://github.com/AuthMe/AuthMeReloaded/tree/master/docs/) on Sun Apr 04 21:31:44 CEST 2021
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<!-- AUTO-GENERATED FILE! Do not edit this directly -->
|
||||
<!-- File auto-generated on Mon May 21 08:43:08 CEST 2018. See docs/permissions/permission_nodes.tpl.md -->
|
||||
<!-- File auto-generated on Sun Apr 04 21:31:44 CEST 2021. See docs/permissions/permission_nodes.tpl.md -->
|
||||
|
||||
## AuthMe Permission Nodes
|
||||
The following are the permission nodes that are currently supported by the latest dev builds.
|
||||
|
@ -28,12 +28,14 @@ The following are the permission nodes that are currently supported by the lates
|
|||
- **authme.admin.setspawn** – Administrator command to set the AuthMe spawn.
|
||||
- **authme.admin.spawn** – Administrator command to teleport to the AuthMe spawn.
|
||||
- **authme.admin.switchantibot** – Administrator command to toggle the AntiBot protection status.
|
||||
- **authme.admin.totpdisable** – Administrator command to disable the two-factor auth of a user.
|
||||
- **authme.admin.totpviewstatus** – Administrator command to see whether a player has enabled two-factor authentication.
|
||||
- **authme.admin.unregister** – Administrator command to unregister an existing user.
|
||||
- **authme.admin.updatemessages** – Permission to use the update messages command.
|
||||
- **authme.allowchatbeforelogin** – Permission to send chat messages before being logged in.
|
||||
- **authme.allowmultipleaccounts** – Permission to be able to register multiple accounts.
|
||||
- **authme.bypassbungeesend** – Permission node to bypass BungeeCord server teleportation.
|
||||
- **authme.bypassantibot** – Permission node to bypass AntiBot protection.
|
||||
- **authme.bypassbungeesend** – Permission node to bypass BungeeCord server teleportation.
|
||||
- **authme.bypasscountrycheck** – Permission to bypass the GeoIp country code check.
|
||||
- **authme.bypassforcesurvival** – Permission for users to bypass force-survival mode.
|
||||
- **authme.bypasspurge** – Permission to bypass the purging process.
|
||||
|
@ -71,4 +73,4 @@ The following are the permission nodes that are currently supported by the lates
|
|||
|
||||
---
|
||||
|
||||
This page was automatically generated on the [AuthMe/AuthMeReloaded repository](https://github.com/AuthMe/AuthMeReloaded/tree/master/docs/) on Mon May 21 08:43:08 CEST 2018
|
||||
This page was automatically generated on the [AuthMe/AuthMeReloaded repository](https://github.com/AuthMe/AuthMeReloaded/tree/master/docs/) on Sun Apr 04 21:31:44 CEST 2021
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<!-- AUTO-GENERATED FILE! Do not edit this directly -->
|
||||
<!-- File auto-generated on Thu Aug 02 21:12:10 CEST 2018. See docs/translations/translations.tpl.md -->
|
||||
<!-- File auto-generated on Wed Jun 21 12:14:29 CEST 2023. See docs/translations/translations.tpl.md -->
|
||||
|
||||
# AuthMe Translations
|
||||
The following translations are available in AuthMe. Set `messagesLanguage` to the language code
|
||||
|
@ -7,38 +7,41 @@ in your config.yml to use the language, or use another language code to start a
|
|||
|
||||
Code | Language | Translated |
|
||||
---- | -------- | ---------: | ------
|
||||
[en](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_en.yml) | English | 100% | <img src="https://placeholdit.imgix.net/~text?txtsize=5&bg=66ff66&w=100&h=5&txtpad=1" alt="bar" />
|
||||
[bg](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_bg.yml) | Bulgarian | 76% | <img src="https://placeholdit.imgix.net/~text?txtsize=5&bg=bb9900&w=76&h=5&txtpad=1" alt="bar" />
|
||||
[br](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_br.yml) | Brazilian | 80% | <img src="https://placeholdit.imgix.net/~text?txtsize=5&bg=aaaa11&w=80&h=5&txtpad=1" alt="bar" />
|
||||
[cz](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_cz.yml) | Czech | 80% | <img src="https://placeholdit.imgix.net/~text?txtsize=5&bg=aaaa11&w=80&h=5&txtpad=1" alt="bar" />
|
||||
[de](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_de.yml) | German | 80% | <img src="https://placeholdit.imgix.net/~text?txtsize=5&bg=aaaa11&w=80&h=5&txtpad=1" alt="bar" />
|
||||
[eo](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_eo.yml) | Esperanto | 80% | <img src="https://placeholdit.imgix.net/~text?txtsize=5&bg=aaaa11&w=80&h=5&txtpad=1" alt="bar" />
|
||||
[es](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_es.yml) | Spanish | 100% | <img src="https://placeholdit.imgix.net/~text?txtsize=5&bg=66ff66&w=100&h=5&txtpad=1" alt="bar" />
|
||||
[et](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_et.yml) | Estonian | 80% | <img src="https://placeholdit.imgix.net/~text?txtsize=5&bg=aaaa11&w=80&h=5&txtpad=1" alt="bar" />
|
||||
[eu](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_eu.yml) | Basque | 42% | <img src="https://placeholdit.imgix.net/~text?txtsize=5&bg=aa5500&w=42&h=5&txtpad=1" alt="bar" />
|
||||
[fi](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_fi.yml) | Finnish | 45% | <img src="https://placeholdit.imgix.net/~text?txtsize=5&bg=aa5500&w=45&h=5&txtpad=1" alt="bar" />
|
||||
[fr](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_fr.yml) | French | 89% | <img src="https://placeholdit.imgix.net/~text?txtsize=5&bg=88cc33&w=89&h=5&txtpad=1" alt="bar" />
|
||||
[gl](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_gl.yml) | Galician | 48% | <img src="https://placeholdit.imgix.net/~text?txtsize=5&bg=aa5500&w=48&h=5&txtpad=1" alt="bar" />
|
||||
[hu](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_hu.yml) | Hungarian | 87% | <img src="https://placeholdit.imgix.net/~text?txtsize=5&bg=99bb22&w=87&h=5&txtpad=1" alt="bar" />
|
||||
[id](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_id.yml) | Indonesian | 47% | <img src="https://placeholdit.imgix.net/~text?txtsize=5&bg=aa5500&w=47&h=5&txtpad=1" alt="bar" />
|
||||
[it](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_it.yml) | Italian | 100% | <img src="https://placeholdit.imgix.net/~text?txtsize=5&bg=66ff66&w=100&h=5&txtpad=1" alt="bar" />
|
||||
[ko](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_ko.yml) | Korean | 89% | <img src="https://placeholdit.imgix.net/~text?txtsize=5&bg=88cc33&w=89&h=5&txtpad=1" alt="bar" />
|
||||
[lt](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_lt.yml) | Lithuanian | 36% | <img src="https://placeholdit.imgix.net/~text?txtsize=5&bg=aa4400&w=36&h=5&txtpad=1" alt="bar" />
|
||||
[nl](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_nl.yml) | Dutch | 80% | <img src="https://placeholdit.imgix.net/~text?txtsize=5&bg=aaaa11&w=80&h=5&txtpad=1" alt="bar" />
|
||||
[pl](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_pl.yml) | Polish | 100% | <img src="https://placeholdit.imgix.net/~text?txtsize=5&bg=66ff66&w=100&h=5&txtpad=1" alt="bar" />
|
||||
[pt](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_pt.yml) | Portuguese | 100% | <img src="https://placeholdit.imgix.net/~text?txtsize=5&bg=66ff66&w=100&h=5&txtpad=1" alt="bar" />
|
||||
[ro](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_ro.yml) | Romanian | 80% | <img src="https://placeholdit.imgix.net/~text?txtsize=5&bg=aaaa11&w=80&h=5&txtpad=1" alt="bar" />
|
||||
[ru](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_ru.yml) | Russian | 93% | <img src="https://placeholdit.imgix.net/~text?txtsize=5&bg=77dd44&w=93&h=5&txtpad=1" alt="bar" />
|
||||
[sk](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_sk.yml) | Slovakian | 80% | <img src="https://placeholdit.imgix.net/~text?txtsize=5&bg=aaaa11&w=80&h=5&txtpad=1" alt="bar" />
|
||||
[tr](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_tr.yml) | Turkish | 100% | <img src="https://placeholdit.imgix.net/~text?txtsize=5&bg=66ff66&w=100&h=5&txtpad=1" alt="bar" />
|
||||
[uk](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_uk.yml) | Ukrainian | 63% | <img src="https://placeholdit.imgix.net/~text?txtsize=5&bg=bb7700&w=63&h=5&txtpad=1" alt="bar" />
|
||||
[vn](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_vn.yml) | Vietnamese | 77% | <img src="https://placeholdit.imgix.net/~text?txtsize=5&bg=bb9900&w=77&h=5&txtpad=1" alt="bar" />
|
||||
[zhcn](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_zhcn.yml) | Chinese (China) | 89% | <img src="https://placeholdit.imgix.net/~text?txtsize=5&bg=88cc33&w=89&h=5&txtpad=1" alt="bar" />
|
||||
[zhhk](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_zhhk.yml) | Chinese (Hong Kong) | 80% | <img src="https://placeholdit.imgix.net/~text?txtsize=5&bg=aaaa11&w=80&h=5&txtpad=1" alt="bar" />
|
||||
[zhmc](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_zhmc.yml) | Chinese (Macau) | 65% | <img src="https://placeholdit.imgix.net/~text?txtsize=5&bg=bb7700&w=65&h=5&txtpad=1" alt="bar" />
|
||||
[zhtw](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_zhtw.yml) | Chinese (Taiwan) | 87% | <img src="https://placeholdit.imgix.net/~text?txtsize=5&bg=99bb22&w=87&h=5&txtpad=1" alt="bar" />
|
||||
[en](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_en.yml) | English | 100% | <img src="https://via.placeholder.com/100x7/66ff66?text=%20" alt="100" />
|
||||
[bg](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_bg.yml) | Bulgarian | 99% | <img src="https://via.placeholder.com/99x7/66ee55?text=%20" alt="99" />
|
||||
[br](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_br.yml) | Brazilian | 100% | <img src="https://via.placeholder.com/100x7/66ff66?text=%20" alt="100" />
|
||||
[cz](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_cz.yml) | Czech | 100% | <img src="https://via.placeholder.com/100x7/66ff66?text=%20" alt="100" />
|
||||
[de](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_de.yml) | German | 99% | <img src="https://via.placeholder.com/99x7/66ee55?text=%20" alt="99" />
|
||||
[eo](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_eo.yml) | Esperanto | 79% | <img src="https://via.placeholder.com/79x7/bb9900?text=%20" alt="79" />
|
||||
[es](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_es.yml) | Spanish | 99% | <img src="https://via.placeholder.com/99x7/66ee55?text=%20" alt="99" />
|
||||
[et](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_et.yml) | Estonian | 100% | <img src="https://via.placeholder.com/100x7/66ff66?text=%20" alt="100" />
|
||||
[eu](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_eu.yml) | Basque | 100% | <img src="https://via.placeholder.com/100x7/66ff66?text=%20" alt="100" />
|
||||
[fi](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_fi.yml) | Finnish | 45% | <img src="https://via.placeholder.com/45x7/aa5500?text=%20" alt="45" />
|
||||
[fr](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_fr.yml) | French | 100% | <img src="https://via.placeholder.com/100x7/66ff66?text=%20" alt="100" />
|
||||
[gl](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_gl.yml) | Galician | 48% | <img src="https://via.placeholder.com/48x7/aa5500?text=%20" alt="48" />
|
||||
[hu](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_hu.yml) | Hungarian | 99% | <img src="https://via.placeholder.com/99x7/66ee55?text=%20" alt="99" />
|
||||
[id](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_id.yml) | Indonesian | 93% | <img src="https://via.placeholder.com/93x7/77dd44?text=%20" alt="93" />
|
||||
[it](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_it.yml) | Italian | 100% | <img src="https://via.placeholder.com/100x7/66ff66?text=%20" alt="100" />
|
||||
[ja](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_ja.yml) | Japanese | 100% | <img src="https://via.placeholder.com/100x7/66ff66?text=%20" alt="100" />
|
||||
[ko](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_ko.yml) | Korean | 99% | <img src="https://via.placeholder.com/99x7/66ee55?text=%20" alt="99" />
|
||||
[lt](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_lt.yml) | Lithuanian | 100% | <img src="https://via.placeholder.com/100x7/66ff66?text=%20" alt="100" />
|
||||
[nl](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_nl.yml) | Dutch | 100% | <img src="https://via.placeholder.com/100x7/66ff66?text=%20" alt="100" />
|
||||
[pl](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_pl.yml) | Polish | 100% | <img src="https://via.placeholder.com/100x7/66ff66?text=%20" alt="100" />
|
||||
[pt](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_pt.yml) | Portuguese | 100% | <img src="https://via.placeholder.com/100x7/66ff66?text=%20" alt="100" />
|
||||
[ro](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_ro.yml) | Romanian | 100% | <img src="https://via.placeholder.com/100x7/66ff66?text=%20" alt="100" />
|
||||
[ru](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_ru.yml) | Russian | 100% | <img src="https://via.placeholder.com/100x7/66ff66?text=%20" alt="100" />
|
||||
[si](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_si.yml) | Slovenian | 99% | <img src="https://via.placeholder.com/99x7/66ee55?text=%20" alt="99" />
|
||||
[sk](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_sk.yml) | Slovakian | 79% | <img src="https://via.placeholder.com/79x7/bb9900?text=%20" alt="79" />
|
||||
[sr](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_sr.yml) | Serbian | 99% | <img src="https://via.placeholder.com/99x7/66ee55?text=%20" alt="99" />
|
||||
[tr](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_tr.yml) | Turkish | 100% | <img src="https://via.placeholder.com/100x7/66ff66?text=%20" alt="100" />
|
||||
[uk](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_uk.yml) | Ukrainian | 100% | <img src="https://via.placeholder.com/100x7/66ff66?text=%20" alt="100" />
|
||||
[vn](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_vn.yml) | Vietnamese | 100% | <img src="https://via.placeholder.com/100x7/66ff66?text=%20" alt="100" />
|
||||
[zhcn](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_zhcn.yml) | Chinese (China) | 100% | <img src="https://via.placeholder.com/100x7/66ff66?text=%20" alt="100" />
|
||||
[zhhk](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_zhhk.yml) | Chinese (Hong Kong) | 99% | <img src="https://via.placeholder.com/99x7/66ee55?text=%20" alt="99" />
|
||||
[zhmc](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_zhmc.yml) | Chinese (Macau) | 64% | <img src="https://via.placeholder.com/64x7/bb7700?text=%20" alt="64" />
|
||||
[zhtw](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_zhtw.yml) | Chinese (Taiwan) | 100% | <img src="https://via.placeholder.com/100x7/66ff66?text=%20" alt="100" />
|
||||
|
||||
|
||||
---
|
||||
|
||||
This page was automatically generated on the [AuthMe/AuthMeReloaded repository](https://github.com/AuthMe/AuthMeReloaded/tree/master/docs/) on Thu Aug 02 21:12:10 CEST 2018
|
||||
This page was automatically generated on the [AuthMe/AuthMeReloaded repository](https://github.com/AuthMe/AuthMeReloaded/tree/master/docs/) on Wed Jun 21 12:14:29 CEST 2023
|
||||
|
|
546
pom.xml
546
pom.xml
|
@ -6,7 +6,7 @@
|
|||
|
||||
<groupId>fr.xephi</groupId>
|
||||
<artifactId>authme</artifactId>
|
||||
<version>5.5.0-SNAPSHOT</version>
|
||||
<version>5.6.0-SNAPSHOT</version>
|
||||
|
||||
<name>AuthMeReloaded</name>
|
||||
<description>The first authentication plugin for the Bukkit API!</description>
|
||||
|
@ -26,7 +26,7 @@
|
|||
|
||||
<ciManagement>
|
||||
<system>jenkins</system>
|
||||
<url>http://ci.codemc.org/job/AuthMe/job/AuthMeReloaded/</url>
|
||||
<url>https://ci.codemc.io/job/AuthMe/job/AuthMeReloaded/</url>
|
||||
</ciManagement>
|
||||
|
||||
<issueManagement>
|
||||
|
@ -37,18 +37,18 @@
|
|||
<distributionManagement>
|
||||
<snapshotRepository>
|
||||
<id>codemc-snapshots</id>
|
||||
<url>https://repo.codemc.org/repository/maven-snapshots/</url>
|
||||
<url>https://repo.codemc.io/repository/maven-snapshots/</url>
|
||||
</snapshotRepository>
|
||||
<repository>
|
||||
<id>codemc-releases</id>
|
||||
<url>https://repo.codemc.org/repository/maven-releases/</url>
|
||||
<url>https://repo.codemc.io/repository/maven-releases/</url>
|
||||
</repository>
|
||||
</distributionManagement>
|
||||
|
||||
<licenses>
|
||||
<license>
|
||||
<name>The GNU General Public Licence version 3 (GPLv3)</name>
|
||||
<url>http://www.gnu.org/licenses/gpl-3.0.html</url>
|
||||
<url>https://www.gnu.org/licenses/gpl-3.0.html</url>
|
||||
<distribution>repo</distribution>
|
||||
</license>
|
||||
</licenses>
|
||||
|
@ -60,11 +60,14 @@
|
|||
<!-- Environment properties -->
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
|
||||
<java.version>1.8</java.version>
|
||||
<maven.minimumVersion>3.3.9</maven.minimumVersion>
|
||||
<java.source>1.8</java.source>
|
||||
<java.target>1.8</java.target>
|
||||
<java.apiVersion>8</java.apiVersion>
|
||||
<java.compiler.minimumVersion>11</java.compiler.minimumVersion>
|
||||
<maven.minimumVersion>3.6.3</maven.minimumVersion>
|
||||
|
||||
<!-- Dependencies versions -->
|
||||
<spigot.version>1.13.2-R0.1-SNAPSHOT</spigot.version>
|
||||
<spigot.version>1.19.2-R0.1-SNAPSHOT</spigot.version>
|
||||
|
||||
<!-- Versioning properties -->
|
||||
<project.outputName>AuthMe</project.outputName>
|
||||
|
@ -76,7 +79,7 @@
|
|||
<pluginDescription.name>${project.outputName}</pluginDescription.name>
|
||||
<pluginDescription.version>${project.versionCode}</pluginDescription.version>
|
||||
<pluginDescription.main>${project.groupId}.${project.artifactId}.${pluginDescription.name}</pluginDescription.main>
|
||||
<pluginDescription.authors>Xephi, sgdc3, DNx5, timvisee, games647, ljacqu, Gnat008</pluginDescription.authors>
|
||||
<pluginDescription.authors>sgdc3, games647, Hex3l, krusic22</pluginDescription.authors>
|
||||
</properties>
|
||||
|
||||
<!-- Jenkins profile -->
|
||||
|
@ -105,6 +108,21 @@
|
|||
<project.skipExtendedHashTests>true</project.skipExtendedHashTests>
|
||||
</properties>
|
||||
</profile>
|
||||
<!-- Skip javadoc generation for faster local build -->
|
||||
<profile>
|
||||
<id>skipJavadocGeneration</id>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-javadoc-plugin</artifactId>
|
||||
<configuration>
|
||||
<skip>true</skip>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</profile>
|
||||
</profiles>
|
||||
|
||||
<build>
|
||||
|
@ -131,12 +149,22 @@
|
|||
</resource>
|
||||
</resources>
|
||||
|
||||
<pluginManagement>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-javadoc-plugin</artifactId>
|
||||
<version>3.4.1</version>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</pluginManagement>
|
||||
|
||||
<plugins>
|
||||
<!-- Enforce build environment -->
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-enforcer-plugin</artifactId>
|
||||
<version>1.4.1</version>
|
||||
<version>3.2.1</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>enforce-environment</id>
|
||||
|
@ -146,8 +174,11 @@
|
|||
<configuration>
|
||||
<rules>
|
||||
<requireMavenVersion>
|
||||
<version>3.3.9</version>
|
||||
<version>${maven.minimumVersion}</version>
|
||||
</requireMavenVersion>
|
||||
<requireJavaVersion>
|
||||
<version>[11,)</version>
|
||||
</requireJavaVersion>
|
||||
</rules>
|
||||
<fail>true</fail>
|
||||
</configuration>
|
||||
|
@ -158,29 +189,30 @@
|
|||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-clean-plugin</artifactId>
|
||||
<version>3.1.0</version>
|
||||
<version>3.2.0</version>
|
||||
</plugin>
|
||||
<!-- Include resource files -->
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-resources-plugin</artifactId>
|
||||
<version>3.1.0</version>
|
||||
<version>3.3.0</version>
|
||||
</plugin>
|
||||
<!-- Compile and include classes -->
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.8.0</version>
|
||||
<version>3.10.1</version>
|
||||
<configuration>
|
||||
<source>${java.version}</source>
|
||||
<target>${java.version}</target>
|
||||
<source>${java.source}</source>
|
||||
<target>${java.target}</target>
|
||||
<release>${java.apiVersion}</release>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<!-- Generate test coverage reports -->
|
||||
<plugin>
|
||||
<groupId>org.jacoco</groupId>
|
||||
<artifactId>jacoco-maven-plugin</artifactId>
|
||||
<version>0.8.2</version>
|
||||
<version>0.8.11</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>pre-unit-test</id>
|
||||
|
@ -200,7 +232,7 @@
|
|||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<version>2.22.1</version>
|
||||
<version>2.22.2</version>
|
||||
<configuration>
|
||||
<!-- Force the right file encoding during unit testing -->
|
||||
<!-- Set language to English in order to get consistent results for localized time formatting -->
|
||||
|
@ -216,15 +248,16 @@
|
|||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-jar-plugin</artifactId>
|
||||
<version>3.1.0</version>
|
||||
<version>3.3.0</version>
|
||||
</plugin>
|
||||
<!-- Generate a jar containing the source javadoc -->
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-javadoc-plugin</artifactId>
|
||||
<version>3.0.1</version>
|
||||
<configuration>
|
||||
<finalName>${project.finalNameBase}</finalName>
|
||||
<!-- In sync with the source/target properties of the maven-compiler-plugin -->
|
||||
<source>8</source>
|
||||
</configuration>
|
||||
<executions>
|
||||
<execution>
|
||||
|
@ -239,7 +272,7 @@
|
|||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-source-plugin</artifactId>
|
||||
<version>3.0.1</version>
|
||||
<version>3.2.1</version>
|
||||
<configuration>
|
||||
<finalName>${project.finalNameBase}</finalName>
|
||||
</configuration>
|
||||
|
@ -256,13 +289,60 @@
|
|||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-shade-plugin</artifactId>
|
||||
<version>3.2.1</version>
|
||||
<version>3.4.1</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>shaded-jar</id>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>shade</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<artifactSet>
|
||||
<excludes>
|
||||
<!-- Guava -->
|
||||
<exclude>com.google.guava:guava</exclude>
|
||||
<exclude>com.google.guava:failureaccess</exclude>
|
||||
<exclude>com.google.guava:listenablefuture</exclude>
|
||||
<exclude>com.google.errorprone:error_prone_annotations</exclude>
|
||||
<exclude>com.google.j2objc:j2objc-annotations</exclude>
|
||||
<!-- Gson -->
|
||||
<exclude>com.google.code.gson:gson</exclude>
|
||||
</excludes>
|
||||
</artifactSet>
|
||||
</configuration>
|
||||
</execution>
|
||||
<execution>
|
||||
<id>shaded-jar-legacy</id>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>shade</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<finalName>${project.finalNameBase}-legacy</finalName>
|
||||
<relocations>
|
||||
<relocation>
|
||||
<pattern>com.google.common</pattern>
|
||||
<shadedPattern>fr.xephi.authme.libs.com.google.common</shadedPattern>
|
||||
</relocation>
|
||||
<relocation>
|
||||
<pattern>com.google.thirdparty</pattern>
|
||||
<shadedPattern>fr.xephi.authme.libs.com.google.thirdparty</shadedPattern>
|
||||
</relocation>
|
||||
<relocation>
|
||||
<pattern>com.google.j2objc</pattern>
|
||||
<shadedPattern>fr.xephi.authme.libs.com.google.j2objc</shadedPattern>
|
||||
</relocation>
|
||||
<relocation>
|
||||
<pattern>com.google.errorprone</pattern>
|
||||
<shadedPattern>fr.xephi.authme.libs.com.google.errorprone</shadedPattern>
|
||||
</relocation>
|
||||
<relocation>
|
||||
<pattern>com.google.gson</pattern>
|
||||
<shadedPattern>fr.xephi.authme.libs.com.google.gson</shadedPattern>
|
||||
</relocation>
|
||||
</relocations>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
<configuration>
|
||||
|
@ -275,14 +355,9 @@
|
|||
|
||||
<!--
|
||||
Relocate all lib we use in order to fix class loading errors if we use different versions
|
||||
than already loaded libs (i.e. by Mojang -> gson)
|
||||
than already loaded libs
|
||||
-->
|
||||
<relocations>
|
||||
<!-- Include all google libraries, because they are not available before 1.12 -->
|
||||
<relocation>
|
||||
<pattern>com.google</pattern>
|
||||
<shadedPattern>fr.xephi.authme.libs.com.google</shadedPattern>
|
||||
</relocation>
|
||||
<relocations combine.children="append">
|
||||
<relocation>
|
||||
<pattern>ch.jalu</pattern>
|
||||
<shadedPattern>fr.xephi.authme.libs.ch.jalu</shadedPattern>
|
||||
|
@ -311,6 +386,18 @@
|
|||
<pattern>de.rtner</pattern>
|
||||
<shadedPattern>fr.xephi.authme.libs.de.rtner</shadedPattern>
|
||||
</relocation>
|
||||
<relocation>
|
||||
<pattern>org.picketbox</pattern>
|
||||
<shadedPattern>fr.xephi.authme.libs.org.picketbox</shadedPattern>
|
||||
</relocation>
|
||||
<relocation>
|
||||
<pattern>org.jboss.crypto</pattern>
|
||||
<shadedPattern>fr.xephi.authme.libs.org.jboss.crypto</shadedPattern>
|
||||
</relocation>
|
||||
<relocation>
|
||||
<pattern>org.jboss.security</pattern>
|
||||
<shadedPattern>fr.xephi.authme.libs.org.jboss.security</shadedPattern>
|
||||
</relocation>
|
||||
<relocation>
|
||||
<pattern>de.mkammerer</pattern>
|
||||
<shadedPattern>fr.xephi.authme.libs.de.mkammerer</shadedPattern>
|
||||
|
@ -336,7 +423,20 @@
|
|||
<pattern>org.bstats</pattern>
|
||||
<shadedPattern>fr.xephi.authme.libs.org.bstats</shadedPattern>
|
||||
</relocation>
|
||||
<relocation>
|
||||
<pattern>org.mariadb.jdbc</pattern>
|
||||
<shadedPattern>fr.xephi.authme.libs.org.mariadb.jdbc</shadedPattern>
|
||||
</relocation>
|
||||
<relocation>
|
||||
<pattern>com.mysql</pattern>
|
||||
<shadedPattern>fr.xephi.authme.libs.com.mysql</shadedPattern>
|
||||
</relocation>
|
||||
<relocation>
|
||||
<pattern>com.google.protobuf</pattern>
|
||||
<shadedPattern>fr.xephi.authme.libs.com.google.protobuf</shadedPattern>
|
||||
</relocation>
|
||||
</relocations>
|
||||
|
||||
<filters>
|
||||
<!-- Ignore manifest signatures for shading the project into an uber-jar to fix -->
|
||||
<!-- "Invalid signature file digest for Manifest main attributes" -->
|
||||
|
@ -346,28 +446,40 @@
|
|||
<exclude>META-INF/*.SF</exclude>
|
||||
<exclude>META-INF/*.DSA</exclude>
|
||||
<exclude>META-INF/*.RSA</exclude>
|
||||
<exclude>META-INF/*.RSA</exclude>
|
||||
<exclude>META-INF/*.MF</exclude>
|
||||
<exclude>META-INF/DEPENDENCIES</exclude>
|
||||
<exclude>META-INF/**/module-info.class</exclude>
|
||||
</excludes>
|
||||
</filter>
|
||||
</filters>
|
||||
|
||||
<transformers>
|
||||
<transformer implementation="org.apache.maven.plugins.shade.resource.ApacheLicenseResourceTransformer"/>
|
||||
<transformer implementation="org.apache.maven.plugins.shade.resource.ApacheNoticeResourceTransformer">
|
||||
<addHeader>false</addHeader>
|
||||
</transformer>
|
||||
<transformer implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer"/>
|
||||
</transformers>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<!-- Install the jars as artifacts into the local repository -->
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-install-plugin</artifactId>
|
||||
<version>2.5.2</version>
|
||||
<version>3.1.0</version>
|
||||
</plugin>
|
||||
<!-- Deploy the jars as artifacts into the remote repository -->
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-deploy-plugin</artifactId>
|
||||
<version>2.8.2</version>
|
||||
<version>3.0.0</version>
|
||||
</plugin>
|
||||
<!-- Handle documentation generation, required by other plugins -->
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-site-plugin</artifactId>
|
||||
<version>3.7.1</version>
|
||||
<version>3.12.1</version>
|
||||
</plugin>
|
||||
<!-- Publish coveralls test coverage reports, not included in the build cycle by default -->
|
||||
<plugin>
|
||||
|
@ -378,45 +490,108 @@
|
|||
<!-- The secret token is provided with a command-line parameter -->
|
||||
<failOnServiceError>false</failOnServiceError>
|
||||
</configuration>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>javax.xml.bind</groupId>
|
||||
<artifactId>jaxb-api</artifactId>
|
||||
<version>2.3.1</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
<repositories>
|
||||
<!-- Apache snapshots repo -->
|
||||
<repository>
|
||||
<id>apache-snapshots</id>
|
||||
<url>https://repository.apache.org/content/repositories/snapshots/</url>
|
||||
<releases>
|
||||
<enabled>false</enabled>
|
||||
</releases>
|
||||
<snapshots>
|
||||
<enabled>true</enabled>
|
||||
</snapshots>
|
||||
</repository>
|
||||
|
||||
<!-- SpigotAPI Repo -->
|
||||
<repository>
|
||||
<id>spigotmc-repo</id>
|
||||
<url>https://hub.spigotmc.org/nexus/content/repositories/snapshots</url>
|
||||
<releases>
|
||||
<enabled>false</enabled>
|
||||
</releases>
|
||||
<snapshots>
|
||||
<enabled>true</enabled>
|
||||
</snapshots>
|
||||
</repository>
|
||||
|
||||
<!-- CodeMC Repo (Contains many required libraries) -->
|
||||
<repository>
|
||||
<id>codemc-repo</id>
|
||||
<url>https://repo.codemc.org/repository/maven-public/</url>
|
||||
<url>https://repo.codemc.io/repository/maven-public/</url>
|
||||
<releases>
|
||||
<enabled>true</enabled>
|
||||
</releases>
|
||||
<snapshots>
|
||||
<enabled>true</enabled>
|
||||
</snapshots>
|
||||
</repository>
|
||||
|
||||
<!-- EssentialsX Repo -->
|
||||
<repository>
|
||||
<id>enderzone-repo</id>
|
||||
<url>https://ci.ender.zone/plugin/repository/everything</url>
|
||||
<id>essentialsx-repo</id>
|
||||
<url>https://repo.essentialsx.net/releases/</url>
|
||||
<releases>
|
||||
<enabled>true</enabled>
|
||||
</releases>
|
||||
<snapshots>
|
||||
<enabled>true</enabled>
|
||||
</snapshots>
|
||||
</repository>
|
||||
|
||||
<!-- ProtocolLib Repo -->
|
||||
<repository>
|
||||
<id>dmulloy2-repo</id>
|
||||
<url>http://repo.dmulloy2.net/content/groups/public/</url>
|
||||
<id>dmulloy2-repo-releases</id>
|
||||
<url>https://repo.dmulloy2.net/nexus/repository/releases/</url>
|
||||
<releases>
|
||||
<enabled>true</enabled>
|
||||
</releases>
|
||||
<snapshots>
|
||||
<enabled>false</enabled>
|
||||
</snapshots>
|
||||
</repository>
|
||||
<repository>
|
||||
<id>dmulloy2-repo-snapshots</id>
|
||||
<url>https://repo.dmulloy2.net/nexus/repository/snapshots/</url>
|
||||
<releases>
|
||||
<enabled>false</enabled>
|
||||
</releases>
|
||||
<snapshots>
|
||||
<enabled>true</enabled>
|
||||
</snapshots>
|
||||
</repository>
|
||||
|
||||
<!-- Multiverse Repo -->
|
||||
<repository>
|
||||
<id>onarandombox-repo</id>
|
||||
<url>http://repo.onarandombox.com/content/groups/public</url>
|
||||
<id>onarandombox-repo-releases</id>
|
||||
<url>https://repo.onarandombox.com/content/repositories/multiverse/</url>
|
||||
<releases>
|
||||
<enabled>true</enabled>
|
||||
</releases>
|
||||
<snapshots>
|
||||
<enabled>false</enabled>
|
||||
</snapshots>
|
||||
</repository>
|
||||
|
||||
<!-- Vault Repo -->
|
||||
<repository>
|
||||
<id>vault-repo</id>
|
||||
<url>http://nexus.hc.to/content/repositories/pub_releases</url>
|
||||
<id>onarandombox-repo-snapshots</id>
|
||||
<url>https://repo.onarandombox.com/content/repositories/multiverse-snapshots/</url>
|
||||
<releases>
|
||||
<enabled>false</enabled>
|
||||
</releases>
|
||||
<snapshots>
|
||||
<enabled>true</enabled>
|
||||
</snapshots>
|
||||
</repository>
|
||||
</repositories>
|
||||
|
||||
|
@ -439,28 +614,12 @@
|
|||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
<!-- GSON (required to provide 1.7.10 and below compatibility) -->
|
||||
<dependency>
|
||||
<groupId>com.google.code.gson</groupId>
|
||||
<artifactId>gson</artifactId>
|
||||
<version>2.8.5</version>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
<!-- Guava (required to allow compatibility with any version since 1.7.10) -->
|
||||
<dependency>
|
||||
<groupId>com.google.guava</groupId>
|
||||
<artifactId>guava</artifactId>
|
||||
<version>27.0.1-jre</version>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
<!-- MaxMind GEO IP with our modifications to use GSON in replacement of the big Jackson dependency -->
|
||||
<!-- GSON is already included and therefore it reduces the file size in comparison to the original version -->
|
||||
<dependency>
|
||||
<groupId>com.maxmind.db</groupId>
|
||||
<artifactId>maxmind-db-gson</artifactId>
|
||||
<version>2.0.2-SNAPSHOT</version>
|
||||
<version>2.0.3</version>
|
||||
<optional>true</optional>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
|
@ -482,7 +641,7 @@
|
|||
<dependency>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-email</artifactId>
|
||||
<version>1.5</version>
|
||||
<version>1.6-SNAPSHOT</version>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
|
@ -490,7 +649,7 @@
|
|||
<dependency>
|
||||
<groupId>org.apache.logging.log4j</groupId>
|
||||
<artifactId>log4j-core</artifactId>
|
||||
<version>2.5</version>
|
||||
<version>2.8.1</version> <!-- Log4J version bundled in 1.12.2 -->
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
|
@ -498,7 +657,7 @@
|
|||
<dependency>
|
||||
<groupId>com.zaxxer</groupId>
|
||||
<artifactId>HikariCP</artifactId>
|
||||
<version>3.2.0</version>
|
||||
<version>4.0.3</version> <!-- Latest java 8 release -->
|
||||
<optional>true</optional>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
|
@ -511,7 +670,7 @@
|
|||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-simple</artifactId>
|
||||
<version>1.7.25</version>
|
||||
<version>1.7.36</version> <!-- We can't update to 2.x as long as we use HikariCP for java 8 -->
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
|
@ -519,7 +678,21 @@
|
|||
<dependency>
|
||||
<groupId>de.rtner</groupId>
|
||||
<artifactId>PBKDF2</artifactId>
|
||||
<version>1.1.2</version>
|
||||
<version>1.1.4</version>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
<!-- MySQL connector, shaded into the legacy jar -->
|
||||
<dependency>
|
||||
<groupId>com.mysql</groupId>
|
||||
<artifactId>mysql-connector-j</artifactId>
|
||||
<version>8.2.0</version>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.mariadb.jdbc</groupId>
|
||||
<artifactId>mariadb-java-client</artifactId>
|
||||
<version>3.3.0</version>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
|
@ -527,7 +700,7 @@
|
|||
<dependency>
|
||||
<groupId>de.mkammerer</groupId>
|
||||
<artifactId>argon2-jvm-nolibs</artifactId>
|
||||
<version>2.5</version>
|
||||
<version>2.11</version>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
|
@ -535,11 +708,11 @@
|
|||
<dependency>
|
||||
<groupId>com.warrenstrange</groupId>
|
||||
<artifactId>googleauth</artifactId>
|
||||
<version>1.2.0</version>
|
||||
<version>1.5.0</version>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
<!-- Spigot API, http://www.spigotmc.org/ -->
|
||||
<!-- Spigot API, https://www.spigotmc.org/ -->
|
||||
<dependency>
|
||||
<groupId>org.spigotmc</groupId>
|
||||
<artifactId>spigot-api</artifactId>
|
||||
|
@ -550,24 +723,36 @@
|
|||
<artifactId>junit</artifactId>
|
||||
<groupId>junit</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>persistence-api</artifactId>
|
||||
<groupId>javax.persistence</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>guava</artifactId>
|
||||
<groupId>com.google.guava</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>bungeecord-chat</artifactId>
|
||||
<groupId>net.md-5</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>gson</artifactId>
|
||||
<groupId>com.google.code.gson</groupId>
|
||||
<groupId>com.googlecode.json-simple</groupId>
|
||||
<artifactId>json-simple</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<!-- Keep in sync with spigot 1.19 -->
|
||||
<dependency>
|
||||
<groupId>com.google.guava</groupId>
|
||||
<artifactId>guava</artifactId>
|
||||
<version>31.0.1-jre</version>
|
||||
<optional>true</optional>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>org.checkerframework</groupId>
|
||||
<artifactId>checker-qual</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<!-- Keep in sync with spigot 1.19 -->
|
||||
<dependency>
|
||||
<groupId>com.google.code.gson</groupId>
|
||||
<artifactId>gson</artifactId>
|
||||
<version>2.8.9</version>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
<!-- Bukkit Libraries -->
|
||||
|
||||
|
@ -575,7 +760,7 @@
|
|||
<dependency>
|
||||
<groupId>ch.jalu</groupId>
|
||||
<artifactId>configme</artifactId>
|
||||
<version>1.0.1</version>
|
||||
<version>1.3.0</version>
|
||||
<optional>true</optional>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
|
@ -589,15 +774,15 @@
|
|||
<dependency>
|
||||
<groupId>org.bstats</groupId>
|
||||
<artifactId>bstats-bukkit</artifactId>
|
||||
<version>1.4</version>
|
||||
<version>3.0.0</version>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
<!-- ProtocolLib -->
|
||||
<dependency>
|
||||
<groupId>com.comphenix.protocol</groupId>
|
||||
<artifactId>ProtocolLib-API</artifactId>
|
||||
<version>4.4.0</version>
|
||||
<artifactId>ProtocolLib</artifactId>
|
||||
<version>4.8.0</version>
|
||||
<scope>provided</scope>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
|
@ -608,14 +793,18 @@
|
|||
<artifactId>BukkitExecutors</artifactId>
|
||||
<groupId>com.comphenix.executors</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>byte-buddy</artifactId>
|
||||
<groupId>net.bytebuddy</groupId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
|
||||
<!-- LuckPerms plugin -->
|
||||
<dependency>
|
||||
<groupId>me.lucko.luckperms</groupId>
|
||||
<artifactId>luckperms-api</artifactId>
|
||||
<version>4.3</version>
|
||||
<groupId>net.luckperms</groupId>
|
||||
<artifactId>api</artifactId>
|
||||
<version>5.4</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
|
@ -626,98 +815,32 @@
|
|||
<version>1.23.5-SNAPSHOT</version>
|
||||
<scope>provided</scope>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>org.bukkit</groupId>
|
||||
<artifactId>bukkit</artifactId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<groupId>net.gravitydevelopment.updater</groupId>
|
||||
<artifactId>updater</artifactId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>commons-dbcp</artifactId>
|
||||
<groupId>commons-dbcp</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>AccountsClient</artifactId>
|
||||
<artifactId>accounts-client</artifactId>
|
||||
<groupId>com.mojang</groupId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
|
||||
<!-- bPermissions plugin -->
|
||||
<dependency>
|
||||
<groupId>de.bananaco</groupId>
|
||||
<artifactId>bPermissions</artifactId>
|
||||
<version>2.12-DEV</version>
|
||||
<scope>provided</scope>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>org.bukkit</groupId>
|
||||
<artifactId>bukkit</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
|
||||
<!-- zPermissions plugin -->
|
||||
<dependency>
|
||||
<groupId>org.tyrannyofheaven.bukkit</groupId>
|
||||
<artifactId>zPermissions</artifactId>
|
||||
<version>1.4-SNAPSHOT</version>
|
||||
<version>1.4.3-SNAPSHOT</version>
|
||||
<scope>provided</scope>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>org.bukkit</groupId>
|
||||
<artifactId>bukkit</artifactId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<groupId>com.sk89q</groupId>
|
||||
<artifactId>worldguard</artifactId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<groupId>com.sk89q</groupId>
|
||||
<artifactId>worldedit</artifactId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>VaultAPI</artifactId>
|
||||
<groupId>net.milkbowl.vault</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>uuidprovider</artifactId>
|
||||
<groupId>net.kaikk.mc</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>ToHPluginUtils</artifactId>
|
||||
<groupId>org.tyrannyofheaven.bukkit</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>Residence</artifactId>
|
||||
<groupId>com.bekvon.bukkit</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>Factions</artifactId>
|
||||
<groupId>com.massivecraft</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>mcore</artifactId>
|
||||
<groupId>com.massivecraft</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>Factoid</artifactId>
|
||||
<groupId>me.tabinol.factoid</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>ebean</artifactId>
|
||||
<groupId>org.avaje</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>persistence-api</artifactId>
|
||||
<groupId>javax.persistence</groupId>
|
||||
<artifactId>ebean</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
|
||||
<!-- Vault, http://dev.bukkit.org/bukkit-plugins/vault/ -->
|
||||
<!-- Vault, https://dev.bukkit.org/bukkit-plugins/vault/ -->
|
||||
<dependency>
|
||||
<groupId>net.milkbowl.vault</groupId>
|
||||
<artifactId>VaultAPI</artifactId>
|
||||
|
@ -735,11 +858,11 @@
|
|||
</exclusions>
|
||||
</dependency>
|
||||
|
||||
<!-- Multi World plugin, http://www.spigotmc.org/resources/multiverse-core.390/ -->
|
||||
<!-- Multi World plugin, https://www.spigotmc.org/resources/multiverse-core.390/ -->
|
||||
<dependency>
|
||||
<groupId>com.onarandombox.multiversecore</groupId>
|
||||
<artifactId>Multiverse-Core</artifactId>
|
||||
<version>2.6.0</version>
|
||||
<version>4.3.1</version>
|
||||
<type>jar</type>
|
||||
<scope>provided</scope>
|
||||
<exclusions>
|
||||
|
@ -800,17 +923,59 @@
|
|||
|
||||
<!-- EssentialsX plugin -->
|
||||
<dependency>
|
||||
<groupId>net.ess3</groupId>
|
||||
<groupId>net.essentialsx</groupId>
|
||||
<artifactId>EssentialsX</artifactId>
|
||||
<version>2.15.0</version>
|
||||
<version>2.20.1</version>
|
||||
<scope>provided</scope>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>io.papermc</groupId>
|
||||
<artifactId>paperlib</artifactId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<groupId>org.bstats</groupId>
|
||||
<artifactId>bstats-bukkit</artifactId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<groupId>net.essentialsx</groupId>
|
||||
<artifactId>BaseProviders</artifactId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<groupId>net.essentialsx</groupId>
|
||||
<artifactId>PaperProvider</artifactId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<groupId>net.essentialsx</groupId>
|
||||
<artifactId>NMSReflectionProvider</artifactId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<groupId>net.essentialsx</groupId>
|
||||
<artifactId>1_8Provider</artifactId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<groupId>net.essentialsx</groupId>
|
||||
<artifactId>1_12Provider</artifactId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<groupId>org.spigotmc</groupId>
|
||||
<artifactId>spigot-api</artifactId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<groupId>org.spongepowered</groupId>
|
||||
<artifactId>configurate-yaml</artifactId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<groupId>org.checkerframework</groupId>
|
||||
<artifactId>checker-qual</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
|
||||
<!-- BCrypt implementation -->
|
||||
<dependency>
|
||||
<groupId>at.favre.lib</groupId>
|
||||
<artifactId>bcrypt</artifactId>
|
||||
<version>0.6.0</version>
|
||||
<version>0.10.2</version>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
|
@ -818,42 +983,8 @@
|
|||
<dependency>
|
||||
<groupId>de.luricos.bukkit</groupId>
|
||||
<artifactId>xAuth</artifactId>
|
||||
<version>2.6</version>
|
||||
<version>2.6.1-SNAPSHOT</version>
|
||||
<scope>provided</scope>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>org.bukkit</groupId>
|
||||
<artifactId>bukkit</artifactId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<groupId>org.bukkit</groupId>
|
||||
<artifactId>craftbukkit</artifactId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>updater</artifactId>
|
||||
<groupId>net.gravitydevelopment.updater</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>lombok</artifactId>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>EssentialsGroupManager</artifactId>
|
||||
<groupId>net.ess3</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>PermissionsEx</artifactId>
|
||||
<groupId>ru.tehkode</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>AccountsClient</artifactId>
|
||||
<groupId>com.mojang</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>log4j-core</artifactId>
|
||||
<groupId>org.apache.logging.log4j</groupId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
|
@ -866,7 +997,14 @@
|
|||
<dependency>
|
||||
<groupId>org.postgresql</groupId>
|
||||
<artifactId>postgresql</artifactId>
|
||||
<version>42.2.5</version>
|
||||
<version>42.7.2</version>
|
||||
<optional>true</optional>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>org.checkerframework</groupId>
|
||||
<artifactId>checker-qual</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
|
||||
<!-- Unit Testing Libraries -->
|
||||
|
@ -875,7 +1013,7 @@
|
|||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<scope>test</scope>
|
||||
<version>4.12</version>
|
||||
<version>4.13.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
|
@ -889,7 +1027,7 @@
|
|||
<groupId>org.mockito</groupId>
|
||||
<artifactId>mockito-core</artifactId>
|
||||
<scope>test</scope>
|
||||
<version>2.23.4</version>
|
||||
<version>4.8.1</version>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<artifactId>hamcrest-core</artifactId>
|
||||
|
@ -898,17 +1036,25 @@
|
|||
</exclusions>
|
||||
</dependency>
|
||||
|
||||
<!-- Required to mock the LuckPerms API-->
|
||||
<dependency>
|
||||
<groupId>org.checkerframework</groupId>
|
||||
<artifactId>checker-qual</artifactId>
|
||||
<version>3.40.0</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<!-- JDBC drivers for datasource integration tests -->
|
||||
<dependency>
|
||||
<groupId>org.xerial</groupId>
|
||||
<artifactId>sqlite-jdbc</artifactId>
|
||||
<version>3.25.2</version>
|
||||
<version>3.44.0.0</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.h2database</groupId>
|
||||
<artifactId>h2</artifactId>
|
||||
<version>1.4.197</version>
|
||||
<version>2.2.220</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
|
|
|
@ -121,7 +121,7 @@ settings:
|
|||
# If the server change fails the player will be kicked.
|
||||
target: LoginLobby1
|
||||
failKickMessage: 'Failed to connect to the lobby! Please try to join the server again!'
|
||||
|
||||
|
||||
# Variables:
|
||||
# %p playername
|
||||
bungee_commands:
|
||||
|
@ -174,7 +174,7 @@ settings:
|
|||
# Registration settings.
|
||||
# ===========================
|
||||
|
||||
registration:
|
||||
registration:
|
||||
# After how many time unregistered players should be kicked?
|
||||
# Set to 0 to disable. (default: 30)
|
||||
timeout: 30
|
||||
|
@ -205,12 +205,12 @@ settings:
|
|||
# Login settings.
|
||||
# ===========================
|
||||
|
||||
login:
|
||||
login:
|
||||
# After how many time unlogged players should be kicked?
|
||||
# Set to 0 to disable. (default: 30)
|
||||
timeout: 30
|
||||
|
||||
|
||||
|
||||
|
||||
# ===========================
|
||||
# Encryption parameters.
|
||||
|
@ -235,7 +235,7 @@ settings:
|
|||
unlogged_restrictions:
|
||||
# Deny chat messages send for unlogged users.
|
||||
deny_chat: true
|
||||
# Hide chat to unlogged users.
|
||||
# Hide chat to unlogged users.
|
||||
# Only player messages, plugins will be able to send messages to the player anyway.
|
||||
hide_chat: false
|
||||
|
||||
|
@ -257,16 +257,16 @@ settings:
|
|||
# Should unlogged players have speed = 0?
|
||||
# After the login the walking/flying speeed will be reset to the default value.
|
||||
removeSpeed: true
|
||||
|
||||
|
||||
# End is there atm xD
|
||||
|
||||
|
||||
# This option will save the quit location of the players.
|
||||
SaveQuitLocation: false
|
||||
# Should not logged in players be teleported to the spawn?
|
||||
# After the authentication, if SaveQuitLocation is enabled,
|
||||
# they will be teleported back to their normal position.
|
||||
teleportUnAuthedToSpawn: false
|
||||
|
||||
|
||||
# If enabled, after the login, if the ForceSpawnOnTheseWorlds setting contains
|
||||
# the player's world, he will be teleported to the world spawnpoint.
|
||||
# The quit location of the player will be overwritten.
|
||||
|
@ -306,22 +306,22 @@ settings:
|
|||
# ===========================
|
||||
# Address restrictions
|
||||
# ===========================
|
||||
|
||||
|
||||
# Max number of registrations per IP (default: 1)
|
||||
maxRegPerIp: 1
|
||||
# Maximum allowed number of Logins per IP, 0 to disable (default: 0)
|
||||
maxLoginPerIp: 0
|
||||
# Maximum allowed number of Joins per IP, 0 to disable (default: 0)
|
||||
maxJoinPerIp: 0
|
||||
|
||||
|
||||
# When this setting is enabled, online players can't be kicked out
|
||||
# due to "Logged in from another Location"
|
||||
# This setting will prevent potetial security exploits.
|
||||
# This setting will prevent potential security exploits.
|
||||
ForceSingleSession: true
|
||||
|
||||
|
||||
# To activate the restricted user feature you need
|
||||
# to enable this option and configure the
|
||||
# AllowedRestrctedUser field.
|
||||
# AllowedRestrictedUser field.
|
||||
AllowRestrictedUser: false
|
||||
# The restricted user feature will kick players listed below
|
||||
# if they dont match of the defined ip address.
|
||||
|
@ -332,35 +332,35 @@ settings:
|
|||
- playername;127.0.0.
|
||||
# Ban ip when the ip is not the ip registered in database
|
||||
banUnsafedIP: false
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# ===============================
|
||||
# Other restrictions
|
||||
# ===============================
|
||||
|
||||
|
||||
# Should we protect the player inventory before logging in?
|
||||
# Warning: Requires the latest version of ProtocolLib!
|
||||
ProtectInventoryBeforeLogIn: true
|
||||
|
||||
|
||||
# Should unregistered players be kicked immediately?
|
||||
kickNonRegistered: false
|
||||
# Should players be kicked on wrong password?
|
||||
kickOnWrongPassword: false
|
||||
|
||||
|
||||
# Should we display all other accounts of a player when he joins?
|
||||
# Required permission: authme.admin.accounts
|
||||
displayOtherAccounts: true
|
||||
|
||||
|
||||
# ===============================
|
||||
# Restrictions compatibility
|
||||
# ===============================
|
||||
|
||||
|
||||
# Spawn Priority. Avariable values : authme, essentials, multiverse, default
|
||||
spawnPriority: authme,essentials,multiverse,default
|
||||
# AuthMe will NEVER teleport players!
|
||||
noTeleport: false
|
||||
|
||||
|
||||
GameMode:
|
||||
# Do you want to set player's gamemode to survival when he joins?
|
||||
# This enables also the settings below.
|
||||
|
@ -369,9 +369,9 @@ settings:
|
|||
ResetInventoryIfCreative: false
|
||||
# Do you want to force the survival mode ONLY after the /login process?
|
||||
ForceOnlyAfterLogin: false
|
||||
|
||||
|
||||
# sgdc3: Ok, our configuration is shit.... xD Today I will stop there
|
||||
|
||||
|
||||
|
||||
registration:
|
||||
# enable registration on the server?
|
||||
|
|
|
@ -70,6 +70,27 @@ abstract class AuthMeController {
|
|||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Changes password for player.
|
||||
*
|
||||
* @param string $username the username
|
||||
* @param string $password the password
|
||||
* @return bool true whether or not password change was successful
|
||||
*/
|
||||
function changePassword($username, $password) {
|
||||
$mysqli = $this->getAuthmeMySqli();
|
||||
if ($mysqli !== null) {
|
||||
$hash = $this->hash($password);
|
||||
$stmt = $mysqli->prepare('UPDATE ' . self::AUTHME_TABLE . ' SET password=? '
|
||||
. 'WHERE username=?');
|
||||
$username_low = strtolower($username);
|
||||
$stmt->bind_param('ss', $hash, $username_low);
|
||||
return $stmt->execute();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Hashes the given password.
|
||||
|
|
|
@ -16,11 +16,10 @@ import fr.xephi.authme.listener.BlockListener;
|
|||
import fr.xephi.authme.listener.EntityListener;
|
||||
import fr.xephi.authme.listener.PlayerListener;
|
||||
import fr.xephi.authme.listener.PlayerListener111;
|
||||
import fr.xephi.authme.listener.PlayerListener16;
|
||||
import fr.xephi.authme.listener.PlayerListener18;
|
||||
import fr.xephi.authme.listener.PlayerListener19;
|
||||
import fr.xephi.authme.listener.PlayerListener19Spigot;
|
||||
import fr.xephi.authme.listener.ServerListener;
|
||||
import fr.xephi.authme.output.ConsoleLoggerFactory;
|
||||
import fr.xephi.authme.security.crypts.Sha256;
|
||||
import fr.xephi.authme.service.BackupService;
|
||||
import fr.xephi.authme.service.BukkitService;
|
||||
|
@ -33,7 +32,6 @@ import fr.xephi.authme.settings.properties.SecuritySettings;
|
|||
import fr.xephi.authme.task.CleanupTask;
|
||||
import fr.xephi.authme.task.purge.PurgeService;
|
||||
import fr.xephi.authme.util.ExceptionUtils;
|
||||
import org.apache.commons.lang.SystemUtils;
|
||||
import org.bukkit.Server;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandSender;
|
||||
|
@ -44,6 +42,7 @@ import org.bukkit.plugin.java.JavaPluginLoader;
|
|||
import org.bukkit.scheduler.BukkitScheduler;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import static fr.xephi.authme.service.BukkitService.TICKS_PER_MINUTE;
|
||||
import static fr.xephi.authme.util.Utils.isClassLoaded;
|
||||
|
@ -58,7 +57,7 @@ public class AuthMe extends JavaPlugin {
|
|||
private static final String LOG_FILENAME = "authme.log";
|
||||
private static final int CLEANUP_INTERVAL = 5 * TICKS_PER_MINUTE;
|
||||
|
||||
// Default version and build number values
|
||||
// Version and build number values
|
||||
private static String pluginVersion = "N/D";
|
||||
private static String pluginBuildNumber = "Unknown";
|
||||
|
||||
|
@ -69,6 +68,7 @@ public class AuthMe extends JavaPlugin {
|
|||
private BukkitService bukkitService;
|
||||
private Injector injector;
|
||||
private BackupService backupService;
|
||||
private ConsoleLogger logger;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
|
@ -80,8 +80,7 @@ public class AuthMe extends JavaPlugin {
|
|||
* Constructor for unit testing.
|
||||
*/
|
||||
@VisibleForTesting
|
||||
@SuppressWarnings("deprecation") // the super constructor is deprecated to mark it for unit testing only
|
||||
protected AuthMe(JavaPluginLoader loader, PluginDescriptionFile description, File dataFolder, File file) {
|
||||
AuthMe(JavaPluginLoader loader, PluginDescriptionFile description, File dataFolder, File file) {
|
||||
super(loader, description, dataFolder, file);
|
||||
}
|
||||
|
||||
|
@ -120,9 +119,22 @@ public class AuthMe extends JavaPlugin {
|
|||
// Load the plugin version data from the plugin description file
|
||||
loadPluginInfo(getDescription().getVersion());
|
||||
|
||||
// Set the Logger instance and log file path
|
||||
ConsoleLogger.initialize(getLogger(), new File(getDataFolder(), LOG_FILENAME));
|
||||
logger = ConsoleLoggerFactory.get(AuthMe.class);
|
||||
|
||||
// Check server version
|
||||
if (!isClassLoaded("org.spigotmc.event.player.PlayerSpawnLocationEvent")
|
||||
|| !isClassLoaded("org.bukkit.event.player.PlayerInteractAtEntityEvent")) {
|
||||
logger.warning("You are running an unsupported server version (" + getServerNameVersionSafe() + "). "
|
||||
+ "AuthMe requires Spigot 1.8.X or later!");
|
||||
stopOrUnload();
|
||||
return;
|
||||
}
|
||||
|
||||
// Prevent running AuthMeBridge due to major exploit issues
|
||||
if(getServer().getPluginManager().isPluginEnabled("AuthMeBridge")) {
|
||||
ConsoleLogger.warning("Detected AuthMeBridge, support for it has been dropped as it was "
|
||||
if (getServer().getPluginManager().isPluginEnabled("AuthMeBridge")) {
|
||||
logger.warning("Detected AuthMeBridge, support for it has been dropped as it was "
|
||||
+ "causing exploit issues, please use AuthMeBungee instead! Aborting!");
|
||||
stopOrUnload();
|
||||
return;
|
||||
|
@ -134,9 +146,10 @@ public class AuthMe extends JavaPlugin {
|
|||
} catch (Throwable th) {
|
||||
YamlParseException yamlParseException = ExceptionUtils.findThrowableInCause(YamlParseException.class, th);
|
||||
if (yamlParseException == null) {
|
||||
ConsoleLogger.logException("Aborting initialization of AuthMe:", th);
|
||||
logger.logException("Aborting initialization of AuthMe:", th);
|
||||
th.printStackTrace();
|
||||
} else {
|
||||
ConsoleLogger.logException("File '" + yamlParseException.getFile() + "' contains invalid YAML. "
|
||||
logger.logException("File '" + yamlParseException.getFile() + "' contains invalid YAML. "
|
||||
+ "Please run its contents through http://yamllint.com", yamlParseException);
|
||||
}
|
||||
stopOrUnload();
|
||||
|
@ -146,28 +159,22 @@ public class AuthMe extends JavaPlugin {
|
|||
// Show settings warnings
|
||||
injector.getSingleton(SettingsWarner.class).logWarningsForMisconfigurations();
|
||||
|
||||
// Schedule clean up task
|
||||
CleanupTask cleanupTask = injector.getSingleton(CleanupTask.class);
|
||||
cleanupTask.runTaskTimerAsynchronously(this, CLEANUP_INTERVAL, CLEANUP_INTERVAL);
|
||||
|
||||
// Do a backup on start
|
||||
backupService.doBackup(BackupService.BackupCause.START);
|
||||
|
||||
// Set up Metrics
|
||||
OnStartupTasks.sendMetrics(this, settings);
|
||||
|
||||
// Sponsor messages
|
||||
ConsoleLogger.info("Development builds are available on our jenkins, thanks to FastVM.io");
|
||||
ConsoleLogger.info("Do you want a good vps for your game server? Look at our sponsor FastVM.io leader "
|
||||
+ "as virtual server provider!");
|
||||
|
||||
// Successful message
|
||||
ConsoleLogger.info("AuthMe " + getPluginVersion() + " build n." + getPluginBuildNumber()
|
||||
+ " correctly enabled!");
|
||||
logger.info("AuthMe " + getPluginVersion() + " build n." + getPluginBuildNumber() + " successfully enabled!");
|
||||
|
||||
// Purge on start if enabled
|
||||
PurgeService purgeService = injector.getSingleton(PurgeService.class);
|
||||
purgeService.runAutoPurge();
|
||||
|
||||
// Schedule clean up task
|
||||
CleanupTask cleanupTask = injector.getSingleton(CleanupTask.class);
|
||||
cleanupTask.runTaskTimerAsynchronously(this, CLEANUP_INTERVAL, CLEANUP_INTERVAL);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -190,15 +197,6 @@ public class AuthMe extends JavaPlugin {
|
|||
* Initialize the plugin and all the services.
|
||||
*/
|
||||
private void initialize() {
|
||||
// Set the Logger instance and log file path
|
||||
ConsoleLogger.setLogger(getLogger());
|
||||
ConsoleLogger.setLogFile(new File(getDataFolder(), LOG_FILENAME));
|
||||
|
||||
// Check java version
|
||||
if (!SystemUtils.isJavaVersionAtLeast(1.8f)) {
|
||||
throw new IllegalStateException("You need Java 1.8 or above to run this plugin!");
|
||||
}
|
||||
|
||||
// Create plugin folder
|
||||
getDataFolder().mkdir();
|
||||
|
||||
|
@ -216,8 +214,8 @@ public class AuthMe extends JavaPlugin {
|
|||
|
||||
// Get settings and set up logger
|
||||
settings = injector.getSingleton(Settings.class);
|
||||
ConsoleLogger.setLoggingOptions(settings);
|
||||
OnStartupTasks.setupConsoleFilter(settings, getLogger());
|
||||
ConsoleLoggerFactory.reloadSettings(settings);
|
||||
OnStartupTasks.setupConsoleFilter(getLogger());
|
||||
|
||||
// Set all service fields on the AuthMe class
|
||||
instantiateServices(injector);
|
||||
|
@ -225,7 +223,6 @@ public class AuthMe extends JavaPlugin {
|
|||
// Convert deprecated PLAINTEXT hash entries
|
||||
MigrationService.changePlainTextToSha256(settings, database, new Sha256());
|
||||
|
||||
//TODO: does this still make sense? -sgdc3
|
||||
// If the server is empty (fresh start) just set all the players as unlogged
|
||||
if (bukkitService.getOnlinePlayers().isEmpty()) {
|
||||
database.purgeLogged();
|
||||
|
@ -272,16 +269,6 @@ public class AuthMe extends JavaPlugin {
|
|||
pluginManager.registerEvents(injector.getSingleton(EntityListener.class), this);
|
||||
pluginManager.registerEvents(injector.getSingleton(ServerListener.class), this);
|
||||
|
||||
// Try to register 1.6 player listeners
|
||||
if (isClassLoaded("org.bukkit.event.player.PlayerEditBookEvent")) {
|
||||
pluginManager.registerEvents(injector.getSingleton(PlayerListener16.class), this);
|
||||
}
|
||||
|
||||
// Try to register 1.8 player listeners
|
||||
if (isClassLoaded("org.bukkit.event.player.PlayerInteractAtEntityEvent")) {
|
||||
pluginManager.registerEvents(injector.getSingleton(PlayerListener18.class), this);
|
||||
}
|
||||
|
||||
// Try to register 1.9 player listeners
|
||||
if (isClassLoaded("org.bukkit.event.player.PlayerSwapHandItemsEvent")) {
|
||||
pluginManager.registerEvents(injector.getSingleton(PlayerListener19.class), this);
|
||||
|
@ -303,7 +290,7 @@ public class AuthMe extends JavaPlugin {
|
|||
*/
|
||||
public void stopOrUnload() {
|
||||
if (settings == null || settings.getProperty(SecuritySettings.STOP_SERVER_ON_PROBLEM)) {
|
||||
ConsoleLogger.warning("THE SERVER IS GOING TO SHUT DOWN AS DEFINED IN THE CONFIGURATION!");
|
||||
getLogger().warning("THE SERVER IS GOING TO SHUT DOWN AS DEFINED IN THE CONFIGURATION!");
|
||||
setEnabled(false);
|
||||
getServer().shutdown();
|
||||
} else {
|
||||
|
@ -330,8 +317,9 @@ public class AuthMe extends JavaPlugin {
|
|||
new TaskCloser(this, database).run();
|
||||
|
||||
// Disabled correctly
|
||||
ConsoleLogger.info("AuthMe " + this.getDescription().getVersion() + " disabled!");
|
||||
ConsoleLogger.close();
|
||||
Consumer<String> infoLogMethod = logger == null ? getLogger()::info : logger::info;
|
||||
infoLogMethod.accept("AuthMe " + this.getDescription().getVersion() + " disabled!");
|
||||
ConsoleLogger.closeFileWriter();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -341,7 +329,6 @@ public class AuthMe extends JavaPlugin {
|
|||
* @param cmd The command (Bukkit).
|
||||
* @param commandLabel The command label (Bukkit).
|
||||
* @param args The command arguments (Bukkit).
|
||||
*
|
||||
* @return True if the command was executed, false otherwise.
|
||||
*/
|
||||
@Override
|
||||
|
@ -356,4 +343,13 @@ public class AuthMe extends JavaPlugin {
|
|||
// Handle the command
|
||||
return commandHandler.processCommand(sender, commandLabel, args);
|
||||
}
|
||||
|
||||
private String getServerNameVersionSafe() {
|
||||
try {
|
||||
Server server = getServer();
|
||||
return server.getName() + " v. " + server.getVersion();
|
||||
} catch (Throwable ignore) {
|
||||
return "-";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,77 +7,93 @@ import fr.xephi.authme.settings.properties.PluginSettings;
|
|||
import fr.xephi.authme.settings.properties.SecuritySettings;
|
||||
import fr.xephi.authme.util.ExceptionUtils;
|
||||
|
||||
import java.io.Closeable;
|
||||
import java.io.File;
|
||||
import java.io.FileWriter;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.text.DateFormat;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Arrays;
|
||||
import java.util.Date;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.text.MessageFormat;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.time.format.DateTimeFormatterBuilder;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* The plugin's static logger.
|
||||
* AuthMe logger.
|
||||
*/
|
||||
public final class ConsoleLogger {
|
||||
|
||||
private static final String NEW_LINE = System.getProperty("line.separator");
|
||||
private static final DateFormat DATE_FORMAT = new SimpleDateFormat("[MM-dd HH:mm:ss]");
|
||||
private static Logger logger;
|
||||
private static LogLevel logLevel = LogLevel.INFO;
|
||||
private static boolean useLogging = false;
|
||||
private static File logFile;
|
||||
private static FileWriter fileWriter;
|
||||
/** Formatter which formats dates to something like "[08-16 21:18:46]" for any given LocalDateTime. */
|
||||
private static final DateTimeFormatter DATE_FORMAT = new DateTimeFormatterBuilder()
|
||||
.appendLiteral('[')
|
||||
.appendPattern("MM-dd HH:mm:ss")
|
||||
.appendLiteral(']')
|
||||
.toFormatter();
|
||||
|
||||
private ConsoleLogger() {
|
||||
// Outside references
|
||||
private static File logFile;
|
||||
private static Logger logger;
|
||||
|
||||
// Shared state
|
||||
private static OutputStreamWriter fileWriter;
|
||||
|
||||
// Individual state
|
||||
private final String name;
|
||||
private LogLevel logLevel = LogLevel.INFO;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param name the name of this logger (the fully qualified class name using it)
|
||||
*/
|
||||
public ConsoleLogger(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
// --------
|
||||
// Configurations
|
||||
// --------
|
||||
|
||||
/**
|
||||
* Set the logger to use.
|
||||
*
|
||||
* @param logger The logger
|
||||
*/
|
||||
public static void setLogger(Logger logger) {
|
||||
public static void initialize(Logger logger, File logFile) {
|
||||
ConsoleLogger.logger = logger;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the file to log to if enabled.
|
||||
*
|
||||
* @param logFile The log file
|
||||
*/
|
||||
public static void setLogFile(File logFile) {
|
||||
ConsoleLogger.logFile = logFile;
|
||||
}
|
||||
|
||||
/**
|
||||
* Load the required settings.
|
||||
* Sets logging settings which are shared by all logger instances.
|
||||
*
|
||||
* @param settings The settings instance
|
||||
* @param settings the settings to read from
|
||||
*/
|
||||
public static void setLoggingOptions(Settings settings) {
|
||||
ConsoleLogger.logLevel = settings.getProperty(PluginSettings.LOG_LEVEL);
|
||||
ConsoleLogger.useLogging = settings.getProperty(SecuritySettings.USE_LOGGING);
|
||||
public static void initializeSharedSettings(Settings settings) {
|
||||
boolean useLogging = settings.getProperty(SecuritySettings.USE_LOGGING);
|
||||
if (useLogging) {
|
||||
if (fileWriter == null) {
|
||||
try {
|
||||
fileWriter = new FileWriter(logFile, true);
|
||||
} catch (IOException e) {
|
||||
ConsoleLogger.logException("Failed to create the log file:", e);
|
||||
}
|
||||
}
|
||||
initializeFileWriter();
|
||||
} else {
|
||||
close();
|
||||
closeFileWriter();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets logging settings which are individual to all loggers.
|
||||
*
|
||||
* @param settings the settings to read from
|
||||
*/
|
||||
public void initializeSettings(Settings settings) {
|
||||
this.logLevel = settings.getProperty(PluginSettings.LOG_LEVEL);
|
||||
}
|
||||
|
||||
public LogLevel getLogLevel() {
|
||||
return logLevel;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
|
||||
// --------
|
||||
// Logging methods
|
||||
|
@ -88,7 +104,7 @@ public final class ConsoleLogger {
|
|||
*
|
||||
* @param message The message to log
|
||||
*/
|
||||
public static void warning(String message) {
|
||||
public void warning(String message) {
|
||||
logger.warning(message);
|
||||
writeLog("[WARN] " + message);
|
||||
}
|
||||
|
@ -100,7 +116,7 @@ public final class ConsoleLogger {
|
|||
* @param message The message to accompany the exception
|
||||
* @param th The Throwable to log
|
||||
*/
|
||||
public static void logException(String message, Throwable th) {
|
||||
public void logException(String message, Throwable th) {
|
||||
warning(message + " " + ExceptionUtils.formatException(th));
|
||||
writeLog(Throwables.getStackTraceAsString(th));
|
||||
}
|
||||
|
@ -110,7 +126,7 @@ public final class ConsoleLogger {
|
|||
*
|
||||
* @param message The message to log
|
||||
*/
|
||||
public static void info(String message) {
|
||||
public void info(String message) {
|
||||
logger.info(message);
|
||||
writeLog("[INFO] " + message);
|
||||
}
|
||||
|
@ -123,7 +139,7 @@ public final class ConsoleLogger {
|
|||
*
|
||||
* @param message The message to log
|
||||
*/
|
||||
public static void fine(String message) {
|
||||
public void fine(String message) {
|
||||
if (logLevel.includes(LogLevel.FINE)) {
|
||||
logger.info(message);
|
||||
writeLog("[FINE] " + message);
|
||||
|
@ -142,24 +158,9 @@ public final class ConsoleLogger {
|
|||
*
|
||||
* @param message The message to log
|
||||
*/
|
||||
public static void debug(String message) {
|
||||
public void debug(String message) {
|
||||
if (logLevel.includes(LogLevel.DEBUG)) {
|
||||
String debugMessage = "[DEBUG] " + message;
|
||||
logger.info(debugMessage);
|
||||
writeLog(debugMessage);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Log the DEBUG message from the supplier if enabled.
|
||||
*
|
||||
* @param msgSupplier the message supplier
|
||||
*/
|
||||
public static void debug(Supplier<String> msgSupplier) {
|
||||
if (logLevel.includes(LogLevel.DEBUG)) {
|
||||
String debugMessage = "[DEBUG] " + msgSupplier.get();
|
||||
logger.info(debugMessage);
|
||||
writeLog(debugMessage);
|
||||
logAndWriteWithDebugPrefix(message);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -169,11 +170,10 @@ public final class ConsoleLogger {
|
|||
* @param message the message
|
||||
* @param param1 parameter to replace in the message
|
||||
*/
|
||||
public static void debug(String message, Object param1) {
|
||||
// Avoids array creation if DEBUG level is disabled
|
||||
public void debug(String message, Object param1) {
|
||||
if (logLevel.includes(LogLevel.DEBUG)) {
|
||||
String debugMessage = "[DEBUG] " + message;
|
||||
logger.log(Level.INFO, debugMessage, param1);
|
||||
writeLog(debugMessage + " {" + param1 + "}");
|
||||
debug(message, new Object[]{param1});
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -185,7 +185,7 @@ public final class ConsoleLogger {
|
|||
* @param param2 second param to replace in message
|
||||
*/
|
||||
// Avoids array creation if DEBUG level is disabled
|
||||
public static void debug(String message, Object param1, Object param2) {
|
||||
public void debug(String message, Object param1, Object param2) {
|
||||
if (logLevel.includes(LogLevel.DEBUG)) {
|
||||
debug(message, new Object[]{param1, param2});
|
||||
}
|
||||
|
@ -197,30 +197,44 @@ public final class ConsoleLogger {
|
|||
* @param message the message
|
||||
* @param params the params to replace in the message
|
||||
*/
|
||||
public static void debug(String message, Object... params) {
|
||||
public void debug(String message, Object... params) {
|
||||
if (logLevel.includes(LogLevel.DEBUG)) {
|
||||
String debugMessage = "[DEBUG] " + message;
|
||||
logger.log(Level.INFO, debugMessage, params);
|
||||
writeLog(debugMessage + " {"
|
||||
+ Arrays.stream(params).map(String::valueOf).collect(Collectors.joining(", ")) + "}");
|
||||
logAndWriteWithDebugPrefix(MessageFormat.format(message, params));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Log the DEBUG message from the supplier if enabled.
|
||||
*
|
||||
* @param msgSupplier the message supplier
|
||||
*/
|
||||
public void debug(Supplier<String> msgSupplier) {
|
||||
if (logLevel.includes(LogLevel.DEBUG)) {
|
||||
logAndWriteWithDebugPrefix(msgSupplier.get());
|
||||
}
|
||||
}
|
||||
|
||||
private void logAndWriteWithDebugPrefix(String message) {
|
||||
String debugMessage = "[DEBUG] " + message;
|
||||
logger.info(debugMessage);
|
||||
writeLog(debugMessage);
|
||||
}
|
||||
|
||||
// --------
|
||||
// Helpers
|
||||
// --------
|
||||
|
||||
/**
|
||||
* Close all file handles.
|
||||
* Closes the file writer.
|
||||
*/
|
||||
public static void close() {
|
||||
public static void closeFileWriter() {
|
||||
if (fileWriter != null) {
|
||||
try {
|
||||
fileWriter.flush();
|
||||
fileWriter.close();
|
||||
fileWriter = null;
|
||||
} catch (IOException ignored) {
|
||||
} finally {
|
||||
closeSafely(fileWriter);
|
||||
fileWriter = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -231,11 +245,8 @@ public final class ConsoleLogger {
|
|||
* @param message The message to write to the log
|
||||
*/
|
||||
private static void writeLog(String message) {
|
||||
if (useLogging) {
|
||||
String dateTime;
|
||||
synchronized (DATE_FORMAT) {
|
||||
dateTime = DATE_FORMAT.format(new Date());
|
||||
}
|
||||
if (fileWriter != null) {
|
||||
String dateTime = DATE_FORMAT.format(LocalDateTime.now());
|
||||
try {
|
||||
fileWriter.write(dateTime);
|
||||
fileWriter.write(": ");
|
||||
|
@ -246,4 +257,31 @@ public final class ConsoleLogger {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void closeSafely(Closeable closeable) {
|
||||
if (closeable != null) {
|
||||
try {
|
||||
closeable.close();
|
||||
} catch (IOException e) {
|
||||
logger.log(Level.SEVERE, "Failed to close resource", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Populates the {@link #fileWriter} field if it is null, handling any exceptions that might
|
||||
* arise during its creation.
|
||||
*/
|
||||
private static void initializeFileWriter() {
|
||||
if (fileWriter == null) {
|
||||
FileOutputStream fos = null;
|
||||
try {
|
||||
fos = new FileOutputStream(logFile, true);
|
||||
fileWriter = new OutputStreamWriter(fos, StandardCharsets.UTF_8);
|
||||
} catch (Exception e) {
|
||||
closeSafely(fos);
|
||||
logger.log(Level.SEVERE, "Failed to create writer to AuthMe log file", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,6 +21,8 @@ import java.time.Instant;
|
|||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* The current API of AuthMe.
|
||||
|
@ -132,6 +134,20 @@ public class AuthMeApi {
|
|||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the AuthMe info of the given player's name, or empty optional if the player doesn't exist.
|
||||
*
|
||||
* @param playerName The player name to look up
|
||||
* @return AuthMe player info, or empty optional if the player doesn't exist
|
||||
*/
|
||||
public Optional<AuthMePlayer> getPlayerInfo(String playerName) {
|
||||
PlayerAuth auth = playerCache.getAuth(playerName);
|
||||
if (auth == null) {
|
||||
auth = dataSource.getAuth(playerName);
|
||||
}
|
||||
return AuthMePlayerImpl.fromPlayerAuth(auth);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the last ip address of a player.
|
||||
*
|
||||
|
@ -163,7 +179,6 @@ public class AuthMeApi {
|
|||
* Get the last (AuthMe) login date of a player.
|
||||
*
|
||||
* @param playerName The name of the player to process
|
||||
*
|
||||
* @return The date of the last login, or null if the player doesn't exist or has never logged in
|
||||
* @deprecated Use Java 8's Instant method {@link #getLastLoginTime(String)}
|
||||
*/
|
||||
|
@ -203,7 +218,7 @@ public class AuthMeApi {
|
|||
* @return true if player is registered, false otherwise
|
||||
*/
|
||||
public boolean isRegistered(String playerName) {
|
||||
String player = playerName.toLowerCase();
|
||||
String player = playerName.toLowerCase(Locale.ROOT);
|
||||
return dataSource.isAuthAvailable(player);
|
||||
}
|
||||
|
||||
|
@ -227,7 +242,7 @@ public class AuthMeApi {
|
|||
* @return true if the player was registered successfully
|
||||
*/
|
||||
public boolean registerPlayer(String playerName, String password) {
|
||||
String name = playerName.toLowerCase();
|
||||
String name = playerName.toLowerCase(Locale.ROOT);
|
||||
if (isRegistered(name)) {
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,65 @@
|
|||
package fr.xephi.authme.api.v3;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* Read-only player info exposed in the AuthMe API. The data in this object is copied from the
|
||||
* database and not updated afterwards. As such, it may become outdated if the player data changes
|
||||
* in AuthMe.
|
||||
*
|
||||
* @see AuthMeApi#getPlayerInfo
|
||||
*/
|
||||
public interface AuthMePlayer {
|
||||
|
||||
/**
|
||||
* @return the case-sensitive name of the player, e.g. "thePlayer3030" - never null
|
||||
*/
|
||||
String getName();
|
||||
|
||||
/**
|
||||
* Returns the UUID of the player as given by the server (may be offline UUID or not).
|
||||
* The UUID is not present if AuthMe is configured not to store the UUID or if the data is not
|
||||
* present (e.g. older record).
|
||||
*
|
||||
* @return player uuid, or empty optional if not available
|
||||
*/
|
||||
Optional<UUID> getUuid();
|
||||
|
||||
/**
|
||||
* Returns the email address associated with this player, or an empty optional if not available.
|
||||
*
|
||||
* @return player's email or empty optional
|
||||
*/
|
||||
Optional<String> getEmail();
|
||||
|
||||
/**
|
||||
* @return the registration date of the player's account - never null
|
||||
*/
|
||||
Instant getRegistrationDate();
|
||||
|
||||
/**
|
||||
* Returns the IP address with which the player's account was registered. Returns an empty optional
|
||||
* for older accounts, or if the account was registered by someone else (e.g. by an admin).
|
||||
*
|
||||
* @return the ip address used during the registration of the account, or empty optional
|
||||
*/
|
||||
Optional<String> getRegistrationIpAddress();
|
||||
|
||||
/**
|
||||
* Returns the last login date of the player. An empty optional is returned if the player never logged in.
|
||||
*
|
||||
* @return date the player last logged in successfully, or empty optional if not applicable
|
||||
*/
|
||||
Optional<Instant> getLastLoginDate();
|
||||
|
||||
/**
|
||||
* Returns the IP address the player last logged in with successfully. Returns an empty optional if the
|
||||
* player never logged in.
|
||||
*
|
||||
* @return ip address the player last logged in with successfully, or empty optional if not applicable
|
||||
*/
|
||||
Optional<String> getLastLoginIpAddress();
|
||||
|
||||
}
|
|
@ -0,0 +1,93 @@
|
|||
package fr.xephi.authme.api.v3;
|
||||
|
||||
import fr.xephi.authme.data.auth.PlayerAuth;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* Implementation of {@link AuthMePlayer}. This implementation is not part of the API and
|
||||
* may have breaking changes in subsequent releases.
|
||||
*/
|
||||
class AuthMePlayerImpl implements AuthMePlayer {
|
||||
|
||||
private String name;
|
||||
private UUID uuid;
|
||||
private String email;
|
||||
|
||||
private Instant registrationDate;
|
||||
private String registrationIpAddress;
|
||||
|
||||
private Instant lastLoginDate;
|
||||
private String lastLoginIpAddress;
|
||||
|
||||
AuthMePlayerImpl() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Maps the given player auth to an AuthMePlayer instance. Returns an empty optional if
|
||||
* the player auth is null.
|
||||
*
|
||||
* @param playerAuth the player auth or null
|
||||
* @return the mapped player auth, or empty optional if the argument was null
|
||||
*/
|
||||
static Optional<AuthMePlayer> fromPlayerAuth(PlayerAuth playerAuth) {
|
||||
if (playerAuth == null) {
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
AuthMePlayerImpl authMeUser = new AuthMePlayerImpl();
|
||||
authMeUser.name = playerAuth.getRealName();
|
||||
authMeUser.uuid = playerAuth.getUuid();
|
||||
authMeUser.email = nullIfDefault(playerAuth.getEmail(), PlayerAuth.DB_EMAIL_DEFAULT);
|
||||
Long lastLoginMillis = nullIfDefault(playerAuth.getLastLogin(), PlayerAuth.DB_LAST_LOGIN_DEFAULT);
|
||||
authMeUser.registrationDate = toInstant(playerAuth.getRegistrationDate());
|
||||
authMeUser.registrationIpAddress = playerAuth.getRegistrationIp();
|
||||
authMeUser.lastLoginDate = toInstant(lastLoginMillis);
|
||||
authMeUser.lastLoginIpAddress = nullIfDefault(playerAuth.getLastIp(), PlayerAuth.DB_LAST_IP_DEFAULT);
|
||||
return Optional.of(authMeUser);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public Optional<UUID> getUuid() {
|
||||
return Optional.ofNullable(uuid);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<String> getEmail() {
|
||||
return Optional.ofNullable(email);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Instant getRegistrationDate() {
|
||||
return registrationDate;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<String> getRegistrationIpAddress() {
|
||||
return Optional.ofNullable(registrationIpAddress);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<Instant> getLastLoginDate() {
|
||||
return Optional.ofNullable( lastLoginDate);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<String> getLastLoginIpAddress() {
|
||||
return Optional.ofNullable(lastLoginIpAddress);
|
||||
}
|
||||
|
||||
private static Instant toInstant(Long epochMillis) {
|
||||
return epochMillis == null ? null : Instant.ofEpochMilli(epochMillis);
|
||||
}
|
||||
|
||||
private static <T> T nullIfDefault(T value, T defaultValue) {
|
||||
return defaultValue.equals(value) ? null : value;
|
||||
}
|
||||
}
|
|
@ -226,8 +226,8 @@ public class CommandDescription {
|
|||
*/
|
||||
public CommandDescription build() {
|
||||
checkArgument(!Utils.isCollectionEmpty(labels), "Labels may not be empty");
|
||||
checkArgument(!StringUtils.isEmpty(description), "Description may not be empty");
|
||||
checkArgument(!StringUtils.isEmpty(detailedDescription), "Detailed description may not be empty");
|
||||
checkArgument(!StringUtils.isBlank(description), "Description may not be empty");
|
||||
checkArgument(!StringUtils.isBlank(detailedDescription), "Detailed description may not be empty");
|
||||
checkArgument(executableCommand != null, "Executable command must be set");
|
||||
// parents and permissions may be null; arguments may be empty
|
||||
|
||||
|
|
|
@ -131,7 +131,7 @@ public class CommandHandler {
|
|||
private static List<String> skipEmptyArguments(String[] args) {
|
||||
List<String> cleanArguments = new ArrayList<>();
|
||||
for (String argument : args) {
|
||||
if (!StringUtils.isEmpty(argument)) {
|
||||
if (!StringUtils.isBlank(argument)) {
|
||||
cleanArguments.add(argument);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,6 +24,8 @@ import fr.xephi.authme.command.executable.authme.SetFirstSpawnCommand;
|
|||
import fr.xephi.authme.command.executable.authme.SetSpawnCommand;
|
||||
import fr.xephi.authme.command.executable.authme.SpawnCommand;
|
||||
import fr.xephi.authme.command.executable.authme.SwitchAntiBotCommand;
|
||||
import fr.xephi.authme.command.executable.authme.TotpDisableAdminCommand;
|
||||
import fr.xephi.authme.command.executable.authme.TotpViewStatusCommand;
|
||||
import fr.xephi.authme.command.executable.authme.UnregisterAdminCommand;
|
||||
import fr.xephi.authme.command.executable.authme.UpdateHelpMessagesCommand;
|
||||
import fr.xephi.authme.command.executable.authme.VersionCommand;
|
||||
|
@ -290,6 +292,28 @@ public class CommandInitializer {
|
|||
.executableCommand(GetIpCommand.class)
|
||||
.register();
|
||||
|
||||
// Register totp command
|
||||
CommandDescription.builder()
|
||||
.parent(authmeBase)
|
||||
.labels("totp", "2fa")
|
||||
.description("See if a player has enabled TOTP")
|
||||
.detailedDescription("Returns whether the specified player has enabled two-factor authentication.")
|
||||
.withArgument("player", "Player name", MANDATORY)
|
||||
.permission(AdminPermission.VIEW_TOTP_STATUS)
|
||||
.executableCommand(TotpViewStatusCommand.class)
|
||||
.register();
|
||||
|
||||
// Register disable totp command
|
||||
CommandDescription.builder()
|
||||
.parent(authmeBase)
|
||||
.labels("disabletotp", "disable2fa", "deletetotp", "delete2fa")
|
||||
.description("Delete TOTP token of a player")
|
||||
.detailedDescription("Disable two-factor authentication for a player.")
|
||||
.withArgument("player", "Player name", MANDATORY)
|
||||
.permission(AdminPermission.DISABLE_TOTP)
|
||||
.executableCommand(TotpDisableAdminCommand.class)
|
||||
.register();
|
||||
|
||||
// Register the spawn command
|
||||
CommandDescription.builder()
|
||||
.parent(authmeBase)
|
||||
|
|
|
@ -11,6 +11,7 @@ import java.util.ArrayList;
|
|||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Set;
|
||||
|
||||
import static fr.xephi.authme.command.FoundResultStatus.INCORRECT_ARGUMENTS;
|
||||
|
@ -130,7 +131,7 @@ public class CommandMapper {
|
|||
}
|
||||
|
||||
private CommandDescription getBaseCommand(String label) {
|
||||
String baseLabel = label.toLowerCase();
|
||||
String baseLabel = label.toLowerCase(Locale.ROOT);
|
||||
if (baseLabel.startsWith("authme:")) {
|
||||
baseLabel = baseLabel.substring("authme:".length());
|
||||
}
|
||||
|
@ -157,7 +158,7 @@ public class CommandMapper {
|
|||
return null;
|
||||
}
|
||||
|
||||
final String label = parts.get(0).toLowerCase();
|
||||
final String label = parts.get(0).toLowerCase(Locale.ROOT);
|
||||
final int argumentCount = parts.size() - 1;
|
||||
|
||||
for (CommandDescription child : baseCommand.getChildren()) {
|
||||
|
|
|
@ -10,6 +10,7 @@ import org.bukkit.command.CommandSender;
|
|||
|
||||
import javax.inject.Inject;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
/**
|
||||
* Shows all accounts registered by the same IP address for the given player name or IP address.
|
||||
|
@ -32,40 +33,34 @@ public class AccountsCommand implements ExecutableCommand {
|
|||
|
||||
// Assumption: a player name cannot contain '.'
|
||||
if (playerName.contains(".")) {
|
||||
bukkitService.runTaskAsynchronously(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
List<String> accountList = dataSource.getAllAuthsByIp(playerName);
|
||||
if (accountList.isEmpty()) {
|
||||
sender.sendMessage("[AuthMe] This IP does not exist in the database.");
|
||||
} else if (accountList.size() == 1) {
|
||||
sender.sendMessage("[AuthMe] " + playerName + " is a single account player");
|
||||
} else {
|
||||
outputAccountsList(sender, playerName, accountList);
|
||||
}
|
||||
bukkitService.runTaskAsynchronously(() -> {
|
||||
List<String> accountList = dataSource.getAllAuthsByIp(playerName);
|
||||
if (accountList.isEmpty()) {
|
||||
sender.sendMessage("[AuthMe] This IP does not exist in the database.");
|
||||
} else if (accountList.size() == 1) {
|
||||
sender.sendMessage("[AuthMe] " + playerName + " is a single account player");
|
||||
} else {
|
||||
outputAccountsList(sender, playerName, accountList);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
bukkitService.runTaskAsynchronously(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
PlayerAuth auth = dataSource.getAuth(playerName.toLowerCase());
|
||||
if (auth == null) {
|
||||
commonService.send(sender, MessageKey.UNKNOWN_USER);
|
||||
return;
|
||||
} else if (auth.getLastIp() == null) {
|
||||
sender.sendMessage("No known last IP address for player");
|
||||
return;
|
||||
}
|
||||
bukkitService.runTaskAsynchronously(() -> {
|
||||
PlayerAuth auth = dataSource.getAuth(playerName.toLowerCase(Locale.ROOT));
|
||||
if (auth == null) {
|
||||
commonService.send(sender, MessageKey.UNKNOWN_USER);
|
||||
return;
|
||||
} else if (auth.getLastIp() == null) {
|
||||
sender.sendMessage("No known last IP address for player");
|
||||
return;
|
||||
}
|
||||
|
||||
List<String> accountList = dataSource.getAllAuthsByIp(auth.getLastIp());
|
||||
if (accountList.isEmpty()) {
|
||||
commonService.send(sender, MessageKey.UNKNOWN_USER);
|
||||
} else if (accountList.size() == 1) {
|
||||
sender.sendMessage("[AuthMe] " + playerName + " is a single account player");
|
||||
} else {
|
||||
outputAccountsList(sender, playerName, accountList);
|
||||
}
|
||||
List<String> accountList = dataSource.getAllAuthsByIp(auth.getLastIp());
|
||||
if (accountList.isEmpty()) {
|
||||
commonService.send(sender, MessageKey.UNKNOWN_USER);
|
||||
} else if (accountList.size() == 1) {
|
||||
sender.sendMessage("[AuthMe] " + playerName + " is a single account player");
|
||||
} else {
|
||||
outputAccountsList(sender, playerName, accountList);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
@ -14,6 +14,7 @@ import fr.xephi.authme.datasource.converter.RoyalAuthConverter;
|
|||
import fr.xephi.authme.datasource.converter.SqliteToSql;
|
||||
import fr.xephi.authme.datasource.converter.VAuthConverter;
|
||||
import fr.xephi.authme.datasource.converter.XAuthConverter;
|
||||
import fr.xephi.authme.output.ConsoleLoggerFactory;
|
||||
import fr.xephi.authme.message.MessageKey;
|
||||
import fr.xephi.authme.service.BukkitService;
|
||||
import fr.xephi.authme.service.CommonService;
|
||||
|
@ -21,6 +22,7 @@ import org.bukkit.command.CommandSender;
|
|||
|
||||
import javax.inject.Inject;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
|
@ -31,6 +33,8 @@ public class ConverterCommand implements ExecutableCommand {
|
|||
@VisibleForTesting
|
||||
static final Map<String, Class<? extends Converter>> CONVERTERS = getConverters();
|
||||
|
||||
private final ConsoleLogger logger = ConsoleLoggerFactory.get(ConverterCommand.class);
|
||||
|
||||
@Inject
|
||||
private CommonService commonService;
|
||||
|
||||
|
@ -52,15 +56,12 @@ public class ConverterCommand implements ExecutableCommand {
|
|||
final Converter converter = converterFactory.newInstance(converterClass);
|
||||
|
||||
// Run the convert job
|
||||
bukkitService.runTaskAsynchronously(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
converter.execute(sender);
|
||||
} catch (Exception e) {
|
||||
commonService.send(sender, MessageKey.ERROR);
|
||||
ConsoleLogger.logException("Error during conversion:", e);
|
||||
}
|
||||
bukkitService.runTaskAsynchronously(() -> {
|
||||
try {
|
||||
converter.execute(sender);
|
||||
} catch (Exception e) {
|
||||
commonService.send(sender, MessageKey.ERROR);
|
||||
logger.logException("Error during conversion:", e);
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -71,7 +72,7 @@ public class ConverterCommand implements ExecutableCommand {
|
|||
private static Class<? extends Converter> getConverterClassFromArgs(List<String> arguments) {
|
||||
return arguments.isEmpty()
|
||||
? null
|
||||
: CONVERTERS.get(arguments.get(0).toLowerCase());
|
||||
: CONVERTERS.get(arguments.get(0).toLowerCase(Locale.ROOT));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -9,6 +9,7 @@ import org.bukkit.command.CommandSender;
|
|||
import javax.inject.Inject;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
|
@ -29,7 +30,7 @@ public class PurgeBannedPlayersCommand implements ExecutableCommand {
|
|||
Set<OfflinePlayer> bannedPlayers = bukkitService.getBannedPlayers();
|
||||
Set<String> namedBanned = new HashSet<>(bannedPlayers.size());
|
||||
for (OfflinePlayer offlinePlayer : bannedPlayers) {
|
||||
namedBanned.add(offlinePlayer.getName().toLowerCase());
|
||||
namedBanned.add(offlinePlayer.getName().toLowerCase(Locale.ROOT));
|
||||
}
|
||||
|
||||
purgeService.purgePlayers(sender, namedBanned, bannedPlayers.toArray(new OfflinePlayer[bannedPlayers.size()]));
|
||||
|
|
|
@ -5,8 +5,6 @@ import fr.xephi.authme.data.auth.PlayerAuth;
|
|||
import fr.xephi.authme.datasource.DataSource;
|
||||
import fr.xephi.authme.message.MessageKey;
|
||||
import fr.xephi.authme.service.CommonService;
|
||||
import fr.xephi.authme.service.bungeecord.BungeeSender;
|
||||
import fr.xephi.authme.service.bungeecord.MessageType;
|
||||
import org.bukkit.command.CommandSender;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
@ -23,18 +21,15 @@ public class PurgeLastPositionCommand implements ExecutableCommand {
|
|||
@Inject
|
||||
private CommonService commonService;
|
||||
|
||||
@Inject
|
||||
private BungeeSender bungeeSender;
|
||||
|
||||
@Override
|
||||
public void executeCommand(final CommandSender sender, List<String> arguments) {
|
||||
public void executeCommand(CommandSender sender, List<String> arguments) {
|
||||
String playerName = arguments.isEmpty() ? sender.getName() : arguments.get(0);
|
||||
|
||||
if ("*".equals(playerName)) {
|
||||
for (PlayerAuth auth : dataSource.getAllAuths()) {
|
||||
resetLastPosition(auth);
|
||||
dataSource.updateQuitLoc(auth);
|
||||
bungeeSender.sendAuthMeBungeecordMessage(MessageType.REFRESH_QUITLOC, playerName);
|
||||
// TODO: send an update when a messaging service will be implemented (QUITLOC)
|
||||
}
|
||||
sender.sendMessage("All players last position locations are now reset");
|
||||
} else {
|
||||
|
@ -47,7 +42,7 @@ public class PurgeLastPositionCommand implements ExecutableCommand {
|
|||
|
||||
resetLastPosition(auth);
|
||||
dataSource.updateQuitLoc(auth);
|
||||
bungeeSender.sendAuthMeBungeecordMessage(MessageType.REFRESH_QUITLOC, playerName);
|
||||
// TODO: send an update when a messaging service will be implemented (QUITLOC)
|
||||
sender.sendMessage(playerName + "'s last position location is now reset");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,6 +9,7 @@ import org.bukkit.command.CommandSender;
|
|||
|
||||
import javax.inject.Inject;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
import static java.util.Collections.singletonList;
|
||||
|
||||
|
@ -29,14 +30,14 @@ public class PurgePlayerCommand implements ExecutableCommand {
|
|||
@Override
|
||||
public void executeCommand(CommandSender sender, List<String> arguments) {
|
||||
String option = arguments.size() > 1 ? arguments.get(1) : null;
|
||||
bukkitService.runTaskOptionallyAsync(
|
||||
bukkitService.runTaskAsynchronously(
|
||||
() -> executeCommand(sender, arguments.get(0), option));
|
||||
}
|
||||
|
||||
private void executeCommand(CommandSender sender, String name, String option) {
|
||||
if ("force".equals(option) || !dataSource.isAuthAvailable(name)) {
|
||||
OfflinePlayer offlinePlayer = bukkitService.getOfflinePlayer(name);
|
||||
purgeExecutor.executePurge(singletonList(offlinePlayer), singletonList(name.toLowerCase()));
|
||||
purgeExecutor.executePurge(singletonList(offlinePlayer), singletonList(name.toLowerCase(Locale.ROOT)));
|
||||
sender.sendMessage("Purged data for player " + name);
|
||||
} else {
|
||||
sender.sendMessage("This player is still registered! Are you sure you want to proceed? "
|
||||
|
|
|
@ -4,6 +4,7 @@ import fr.xephi.authme.ConsoleLogger;
|
|||
import fr.xephi.authme.command.ExecutableCommand;
|
||||
import fr.xephi.authme.data.auth.PlayerAuth;
|
||||
import fr.xephi.authme.datasource.DataSource;
|
||||
import fr.xephi.authme.output.ConsoleLoggerFactory;
|
||||
import fr.xephi.authme.message.MessageKey;
|
||||
import fr.xephi.authme.security.PasswordSecurity;
|
||||
import fr.xephi.authme.security.crypts.HashedPassword;
|
||||
|
@ -16,12 +17,15 @@ import org.bukkit.entity.Player;
|
|||
|
||||
import javax.inject.Inject;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
/**
|
||||
* Admin command to register a user.
|
||||
*/
|
||||
public class RegisterAdminCommand implements ExecutableCommand {
|
||||
|
||||
private final ConsoleLogger logger = ConsoleLoggerFactory.get(RegisterAdminCommand.class);
|
||||
|
||||
@Inject
|
||||
private PasswordSecurity passwordSecurity;
|
||||
|
||||
|
@ -42,7 +46,7 @@ public class RegisterAdminCommand implements ExecutableCommand {
|
|||
// Get the player name and password
|
||||
final String playerName = arguments.get(0);
|
||||
final String playerPass = arguments.get(1);
|
||||
final String playerNameLowerCase = playerName.toLowerCase();
|
||||
final String playerNameLowerCase = playerName.toLowerCase(Locale.ROOT);
|
||||
|
||||
// Command logic
|
||||
ValidationResult passwordValidation = validationService.validatePassword(playerPass, playerName);
|
||||
|
@ -70,7 +74,7 @@ public class RegisterAdminCommand implements ExecutableCommand {
|
|||
}
|
||||
|
||||
commonService.send(sender, MessageKey.REGISTER_SUCCESS);
|
||||
ConsoleLogger.info(sender.getName() + " registered " + playerName);
|
||||
logger.info(sender.getName() + " registered " + playerName);
|
||||
final Player player = bukkitService.getPlayerExact(playerName);
|
||||
if (player != null) {
|
||||
bukkitService.scheduleSyncTaskFromOptionallyAsyncTask(() ->
|
||||
|
|
|
@ -7,6 +7,7 @@ import fr.xephi.authme.command.ExecutableCommand;
|
|||
import fr.xephi.authme.datasource.DataSource;
|
||||
import fr.xephi.authme.initialization.Reloadable;
|
||||
import fr.xephi.authme.initialization.SettingsDependent;
|
||||
import fr.xephi.authme.output.ConsoleLoggerFactory;
|
||||
import fr.xephi.authme.message.MessageKey;
|
||||
import fr.xephi.authme.service.CommonService;
|
||||
import fr.xephi.authme.settings.Settings;
|
||||
|
@ -23,6 +24,8 @@ import java.util.List;
|
|||
*/
|
||||
public class ReloadCommand implements ExecutableCommand {
|
||||
|
||||
private final ConsoleLogger logger = ConsoleLoggerFactory.get(ReloadCommand.class);
|
||||
|
||||
@Inject
|
||||
private AuthMe plugin;
|
||||
|
||||
|
@ -48,7 +51,7 @@ public class ReloadCommand implements ExecutableCommand {
|
|||
public void executeCommand(CommandSender sender, List<String> arguments) {
|
||||
try {
|
||||
settings.reload();
|
||||
ConsoleLogger.setLoggingOptions(settings);
|
||||
ConsoleLoggerFactory.reloadSettings(settings);
|
||||
settingsWarner.logWarningsForMisconfigurations();
|
||||
|
||||
// We do not change database type for consistency issues, but we'll output a note in the logs
|
||||
|
@ -59,7 +62,7 @@ public class ReloadCommand implements ExecutableCommand {
|
|||
commonService.send(sender, MessageKey.CONFIG_RELOAD_SUCCESS);
|
||||
} catch (Exception e) {
|
||||
sender.sendMessage("Error occurred during reload of AuthMe: aborting");
|
||||
ConsoleLogger.logException("Aborting! Encountered exception during reload of AuthMe:", e);
|
||||
logger.logException("Aborting! Encountered exception during reload of AuthMe:", e);
|
||||
plugin.stopOrUnload();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,61 @@
|
|||
package fr.xephi.authme.command.executable.authme;
|
||||
|
||||
import fr.xephi.authme.ConsoleLogger;
|
||||
import fr.xephi.authme.command.ExecutableCommand;
|
||||
import fr.xephi.authme.data.auth.PlayerAuth;
|
||||
import fr.xephi.authme.datasource.DataSource;
|
||||
import fr.xephi.authme.message.MessageKey;
|
||||
import fr.xephi.authme.message.Messages;
|
||||
import fr.xephi.authme.output.ConsoleLoggerFactory;
|
||||
import fr.xephi.authme.service.BukkitService;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Command to disable two-factor authentication for a user.
|
||||
*/
|
||||
public class TotpDisableAdminCommand implements ExecutableCommand {
|
||||
|
||||
private final ConsoleLogger logger = ConsoleLoggerFactory.get(TotpDisableAdminCommand.class);
|
||||
|
||||
@Inject
|
||||
private DataSource dataSource;
|
||||
|
||||
@Inject
|
||||
private Messages messages;
|
||||
|
||||
@Inject
|
||||
private BukkitService bukkitService;
|
||||
|
||||
@Override
|
||||
public void executeCommand(CommandSender sender, List<String> arguments) {
|
||||
String player = arguments.get(0);
|
||||
|
||||
PlayerAuth auth = dataSource.getAuth(player);
|
||||
if (auth == null) {
|
||||
messages.send(sender, MessageKey.UNKNOWN_USER);
|
||||
} else if (auth.getTotpKey() == null) {
|
||||
sender.sendMessage(ChatColor.RED + "Player '" + player + "' does not have two-factor auth enabled");
|
||||
} else {
|
||||
removeTotpKey(sender, player);
|
||||
}
|
||||
}
|
||||
|
||||
private void removeTotpKey(CommandSender sender, String player) {
|
||||
if (dataSource.removeTotpKey(player)) {
|
||||
sender.sendMessage("Disabled two-factor authentication successfully for '" + player + "'");
|
||||
logger.info(sender.getName() + " disable two-factor authentication for '" + player + "'");
|
||||
|
||||
Player onlinePlayer = bukkitService.getPlayerExact(player);
|
||||
if (onlinePlayer != null) {
|
||||
messages.send(onlinePlayer, MessageKey.TWO_FACTOR_REMOVED_SUCCESS);
|
||||
}
|
||||
} else {
|
||||
messages.send(sender, MessageKey.ERROR);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
package fr.xephi.authme.command.executable.authme;
|
||||
|
||||
import fr.xephi.authme.command.ExecutableCommand;
|
||||
import fr.xephi.authme.data.auth.PlayerAuth;
|
||||
import fr.xephi.authme.datasource.DataSource;
|
||||
import fr.xephi.authme.message.MessageKey;
|
||||
import fr.xephi.authme.message.Messages;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.command.CommandSender;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Command to see whether a user has enabled two-factor authentication.
|
||||
*/
|
||||
public class TotpViewStatusCommand implements ExecutableCommand {
|
||||
|
||||
@Inject
|
||||
private DataSource dataSource;
|
||||
|
||||
@Inject
|
||||
private Messages messages;
|
||||
|
||||
@Override
|
||||
public void executeCommand(CommandSender sender, List<String> arguments) {
|
||||
String player = arguments.get(0);
|
||||
|
||||
PlayerAuth auth = dataSource.getAuth(player);
|
||||
if (auth == null) {
|
||||
messages.send(sender, MessageKey.UNKNOWN_USER);
|
||||
} else if (auth.getTotpKey() == null) {
|
||||
sender.sendMessage(ChatColor.RED + "Player '" + player + "' does NOT have two-factor auth enabled");
|
||||
} else {
|
||||
sender.sendMessage(ChatColor.DARK_GREEN + "Player '" + player + "' has enabled two-factor authentication");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -3,6 +3,7 @@ package fr.xephi.authme.command.executable.authme;
|
|||
import fr.xephi.authme.ConsoleLogger;
|
||||
import fr.xephi.authme.command.ExecutableCommand;
|
||||
import fr.xephi.authme.command.help.HelpMessagesService;
|
||||
import fr.xephi.authme.output.ConsoleLoggerFactory;
|
||||
import fr.xephi.authme.service.HelpTranslationGenerator;
|
||||
import org.bukkit.command.CommandSender;
|
||||
|
||||
|
@ -17,6 +18,8 @@ import java.util.List;
|
|||
*/
|
||||
public class UpdateHelpMessagesCommand implements ExecutableCommand {
|
||||
|
||||
private final ConsoleLogger logger = ConsoleLoggerFactory.get(UpdateHelpMessagesCommand.class);
|
||||
|
||||
@Inject
|
||||
private HelpTranslationGenerator helpTranslationGenerator;
|
||||
@Inject
|
||||
|
@ -30,7 +33,7 @@ public class UpdateHelpMessagesCommand implements ExecutableCommand {
|
|||
helpMessagesService.reloadMessagesFile();
|
||||
} catch (IOException e) {
|
||||
sender.sendMessage("Could not update help file: " + e.getMessage());
|
||||
ConsoleLogger.logException("Could not update help file:", e);
|
||||
logger.logException("Could not update help file:", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,7 +8,9 @@ import org.bukkit.command.CommandSender;
|
|||
import org.bukkit.entity.Player;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Collection;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
public class VersionCommand implements ExecutableCommand {
|
||||
|
@ -22,21 +24,25 @@ public class VersionCommand implements ExecutableCommand {
|
|||
sender.sendMessage(ChatColor.GOLD + "==========[ " + AuthMe.getPluginName() + " ABOUT ]==========");
|
||||
sender.sendMessage(ChatColor.GOLD + "Version: " + ChatColor.WHITE + AuthMe.getPluginName()
|
||||
+ " v" + AuthMe.getPluginVersion() + ChatColor.GRAY + " (build: " + AuthMe.getPluginBuildNumber() + ")");
|
||||
sender.sendMessage(ChatColor.GOLD + "Developers:");
|
||||
Collection<? extends Player> onlinePlayers = bukkitService.getOnlinePlayers();
|
||||
printDeveloper(sender, "Alexandre Vanhecke", "xephi59", "Original Author", onlinePlayers);
|
||||
printDeveloper(sender, "Lucas J.", "ljacqu", "Main Developer", onlinePlayers);
|
||||
printDeveloper(sender, "Gnat008", "gnat008", "Developer", onlinePlayers);
|
||||
printDeveloper(sender, "DNx5", "DNx5", "Developer", onlinePlayers);
|
||||
printDeveloper(sender, "games647", "games647", "Developer", onlinePlayers);
|
||||
printDeveloper(sender, "Tim Visee", "timvisee", "Developer", onlinePlayers);
|
||||
sender.sendMessage(ChatColor.GOLD + "Authors:");
|
||||
Collection<Player> onlinePlayers = bukkitService.getOnlinePlayers();
|
||||
printDeveloper(sender, "Gabriele C.", "sgdc3", "Project manager, Contributor", onlinePlayers);
|
||||
printDeveloper(sender, "Lucas J.", "ljacqu", "Main Developer", onlinePlayers);
|
||||
printDeveloper(sender, "games647", "games647", "Developer", onlinePlayers);
|
||||
printDeveloper(sender, "Hex3l", "Hex3l", "Developer", onlinePlayers);
|
||||
printDeveloper(sender, "krusic22", "krusic22", "Support", onlinePlayers);
|
||||
sender.sendMessage(ChatColor.GOLD + "Retired authors:");
|
||||
printDeveloper(sender, "Alexandre Vanhecke", "xephi59", "Original Author", onlinePlayers);
|
||||
printDeveloper(sender, "Gnat008", "gnat008", "Developer, Retired", onlinePlayers);
|
||||
printDeveloper(sender, "DNx5", "DNx5", "Developer, Retired", onlinePlayers);
|
||||
printDeveloper(sender, "Tim Visee", "timvisee", "Developer, Retired", onlinePlayers);
|
||||
sender.sendMessage(ChatColor.GOLD + "Website: " + ChatColor.WHITE
|
||||
+ "http://dev.bukkit.org/bukkit-plugins/authme-reloaded/");
|
||||
+ "https://github.com/AuthMe/AuthMeReloaded");
|
||||
sender.sendMessage(ChatColor.GOLD + "License: " + ChatColor.WHITE + "GNU GPL v3.0"
|
||||
+ ChatColor.GRAY + ChatColor.ITALIC + " (See LICENSE file)");
|
||||
sender.sendMessage(ChatColor.GOLD + "Copyright: " + ChatColor.WHITE
|
||||
+ "Copyright (c) AuthMe-Team 2017. All rights reserved.");
|
||||
+ "Copyright (c) AuthMe-Team " + new SimpleDateFormat("yyyy").format(new Date())
|
||||
+ ". Released under GPL v3 License.");
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -49,7 +55,7 @@ public class VersionCommand implements ExecutableCommand {
|
|||
* @param onlinePlayers The list of online players
|
||||
*/
|
||||
private static void printDeveloper(CommandSender sender, String name, String minecraftName, String function,
|
||||
Collection<? extends Player> onlinePlayers) {
|
||||
Collection<Player> onlinePlayers) {
|
||||
// Print the name
|
||||
StringBuilder msg = new StringBuilder();
|
||||
msg.append(" ")
|
||||
|
@ -77,7 +83,7 @@ public class VersionCommand implements ExecutableCommand {
|
|||
*
|
||||
* @return True if the player is online, false otherwise
|
||||
*/
|
||||
private static boolean isPlayerOnline(String minecraftName, Collection<? extends Player> onlinePlayers) {
|
||||
private static boolean isPlayerOnline(String minecraftName, Collection<Player> onlinePlayers) {
|
||||
for (Player player : onlinePlayers) {
|
||||
if (player.getName().equalsIgnoreCase(minecraftName)) {
|
||||
return true;
|
||||
|
|
|
@ -8,6 +8,7 @@ import fr.xephi.authme.datasource.DataSource;
|
|||
import fr.xephi.authme.initialization.HasCleanup;
|
||||
import fr.xephi.authme.initialization.Reloadable;
|
||||
import fr.xephi.authme.initialization.SettingsDependent;
|
||||
import fr.xephi.authme.output.ConsoleLoggerFactory;
|
||||
import fr.xephi.authme.permission.DebugSectionPermissions;
|
||||
import fr.xephi.authme.permission.PermissionNode;
|
||||
import org.bukkit.ChatColor;
|
||||
|
@ -54,6 +55,7 @@ class DataStatistics implements DebugSection {
|
|||
|
||||
outputDatabaseStats(sender);
|
||||
outputInjectorStats(sender);
|
||||
sender.sendMessage("Total logger instances: " + ConsoleLoggerFactory.getTotalLoggers());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -9,6 +9,7 @@ import org.bukkit.command.CommandSender;
|
|||
|
||||
import javax.inject.Inject;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.TreeMap;
|
||||
|
@ -45,7 +46,7 @@ public class DebugCommand implements ExecutableCommand {
|
|||
if (arguments.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
return getSections().get(arguments.get(0).toLowerCase());
|
||||
return getSections().get(arguments.get(0).toLowerCase(Locale.ROOT));
|
||||
}
|
||||
|
||||
private void sendAvailableSections(CommandSender sender) {
|
||||
|
|
|
@ -4,6 +4,7 @@ import fr.xephi.authme.ConsoleLogger;
|
|||
import fr.xephi.authme.data.limbo.LimboService;
|
||||
import fr.xephi.authme.datasource.CacheDataSource;
|
||||
import fr.xephi.authme.datasource.DataSource;
|
||||
import fr.xephi.authme.output.ConsoleLoggerFactory;
|
||||
import org.bukkit.Location;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
|
@ -19,6 +20,7 @@ import java.util.function.Function;
|
|||
*/
|
||||
final class DebugSectionUtils {
|
||||
|
||||
private static ConsoleLogger logger = ConsoleLoggerFactory.get(DebugSectionUtils.class);
|
||||
private static Field limboEntriesField;
|
||||
|
||||
private DebugSectionUtils() {
|
||||
|
@ -72,7 +74,7 @@ final class DebugSectionUtils {
|
|||
field.setAccessible(true);
|
||||
limboEntriesField = field;
|
||||
} catch (Exception e) {
|
||||
ConsoleLogger.logException("Could not retrieve LimboService entries field:", e);
|
||||
logger.logException("Could not retrieve LimboService entries field:", e);
|
||||
}
|
||||
}
|
||||
return limboEntriesField;
|
||||
|
@ -95,7 +97,7 @@ final class DebugSectionUtils {
|
|||
try {
|
||||
return function.apply((Map) limboEntriesField.get(limboService));
|
||||
} catch (Exception e) {
|
||||
ConsoleLogger.logException("Could not retrieve LimboService values:", e);
|
||||
logger.logException("Could not retrieve LimboService values:", e);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
|
@ -119,7 +121,7 @@ final class DebugSectionUtils {
|
|||
source.setAccessible(true);
|
||||
return (DataSource) source.get(dataSource);
|
||||
} catch (NoSuchFieldException | IllegalAccessException e) {
|
||||
ConsoleLogger.logException("Could not get source of CacheDataSource:", e);
|
||||
logger.logException("Could not get source of CacheDataSource:", e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@ import com.google.common.annotations.VisibleForTesting;
|
|||
import fr.xephi.authme.ConsoleLogger;
|
||||
import fr.xephi.authme.datasource.DataSource;
|
||||
import fr.xephi.authme.datasource.MySQL;
|
||||
import fr.xephi.authme.output.ConsoleLoggerFactory;
|
||||
import fr.xephi.authme.permission.DebugSectionPermissions;
|
||||
import fr.xephi.authme.permission.PermissionNode;
|
||||
import fr.xephi.authme.settings.Settings;
|
||||
|
@ -43,6 +44,8 @@ class MySqlDefaultChanger implements DebugSection {
|
|||
private static final String NOT_NULL_SUFFIX = ChatColor.DARK_AQUA + "@" + ChatColor.RESET;
|
||||
private static final String DEFAULT_VALUE_SUFFIX = ChatColor.GOLD + "#" + ChatColor.RESET;
|
||||
|
||||
private ConsoleLogger logger = ConsoleLoggerFactory.get(MySqlDefaultChanger.class);
|
||||
|
||||
@Inject
|
||||
private Settings settings;
|
||||
|
||||
|
@ -98,7 +101,7 @@ class MySqlDefaultChanger implements DebugSection {
|
|||
throw new IllegalStateException("Unknown operation '" + operation + "'");
|
||||
}
|
||||
} catch (SQLException | IllegalStateException e) {
|
||||
ConsoleLogger.logException("Failed to perform MySQL default altering operation:", e);
|
||||
logger.logException("Failed to perform MySQL default altering operation:", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -134,7 +137,7 @@ class MySqlDefaultChanger implements DebugSection {
|
|||
}
|
||||
|
||||
// Log success message
|
||||
ConsoleLogger.info("Changed MySQL column '" + columnName + "' to be NOT NULL, as initiated by '"
|
||||
logger.info("Changed MySQL column '" + columnName + "' to be NOT NULL, as initiated by '"
|
||||
+ sender.getName() + "'");
|
||||
}
|
||||
|
||||
|
@ -168,7 +171,7 @@ class MySqlDefaultChanger implements DebugSection {
|
|||
+ "') to be NULL, modifying " + updatedRows + " entries");
|
||||
|
||||
// Log success message
|
||||
ConsoleLogger.info("Changed MySQL column '" + columnName + "' to allow NULL, as initiated by '"
|
||||
logger.info("Changed MySQL column '" + columnName + "' to allow NULL, as initiated by '"
|
||||
+ sender.getName() + "'");
|
||||
}
|
||||
|
||||
|
@ -191,7 +194,7 @@ class MySqlDefaultChanger implements DebugSection {
|
|||
+ " (" + columnName + "): " + isNullText + ", " + defaultText);
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
ConsoleLogger.logException("Failed while showing column details:", e);
|
||||
logger.logException("Failed while showing column details:", e);
|
||||
sender.sendMessage("Failed while showing column details. See log for info");
|
||||
}
|
||||
|
||||
|
@ -228,7 +231,7 @@ class MySqlDefaultChanger implements DebugSection {
|
|||
}
|
||||
return String.join(ChatColor.RESET + ", ", formattedColumns);
|
||||
} catch (SQLException e) {
|
||||
ConsoleLogger.logException("Failed to construct column list:", e);
|
||||
logger.logException("Failed to construct column list:", e);
|
||||
return ChatColor.RED + "An error occurred! Please see the console for details.";
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package fr.xephi.authme.command.executable.authme.debug;
|
||||
|
||||
import fr.xephi.authme.data.limbo.UserGroup;
|
||||
import fr.xephi.authme.permission.DebugSectionPermissions;
|
||||
import fr.xephi.authme.permission.PermissionNode;
|
||||
import fr.xephi.authme.permission.PermissionsManager;
|
||||
|
@ -11,6 +12,8 @@ import org.bukkit.entity.Player;
|
|||
import javax.inject.Inject;
|
||||
import java.util.List;
|
||||
|
||||
import static java.util.stream.Collectors.toList;
|
||||
|
||||
/**
|
||||
* Outputs the permission groups of a player.
|
||||
*/
|
||||
|
@ -37,8 +40,11 @@ class PermissionGroups implements DebugSection {
|
|||
if (player == null) {
|
||||
sender.sendMessage("Player " + name + " could not be found");
|
||||
} else {
|
||||
sender.sendMessage("Player " + name + " has permission groups: "
|
||||
+ String.join(", ", permissionsManager.getGroups(player)));
|
||||
List<String> groupNames = permissionsManager.getGroups(player).stream()
|
||||
.map(UserGroup::getGroupName)
|
||||
.collect(toList());
|
||||
|
||||
sender.sendMessage("Player " + name + " has permission groups: " + String.join(", ", groupNames));
|
||||
sender.sendMessage("Primary group is: " + permissionsManager.getGroups(player));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -89,7 +89,7 @@ class PlayerAuthViewer implements DebugSection {
|
|||
* or empty string if the string is null or empty
|
||||
*/
|
||||
private static String safeSubstring(String str, int length) {
|
||||
if (StringUtils.isEmpty(str)) {
|
||||
if (StringUtils.isBlank(str)) {
|
||||
return "";
|
||||
} else if (str.length() < length) {
|
||||
return str.substring(0, str.length() / 2) + "...";
|
||||
|
|
|
@ -3,6 +3,7 @@ package fr.xephi.authme.command.executable.authme.debug;
|
|||
import ch.jalu.datasourcecolumns.data.DataSourceValue;
|
||||
import fr.xephi.authme.ConsoleLogger;
|
||||
import fr.xephi.authme.datasource.DataSource;
|
||||
import fr.xephi.authme.output.ConsoleLoggerFactory;
|
||||
import fr.xephi.authme.mail.SendMailSsl;
|
||||
import fr.xephi.authme.permission.DebugSectionPermissions;
|
||||
import fr.xephi.authme.permission.PermissionNode;
|
||||
|
@ -22,6 +23,8 @@ import java.util.List;
|
|||
*/
|
||||
class TestEmailSender implements DebugSection {
|
||||
|
||||
private final ConsoleLogger logger = ConsoleLoggerFactory.get(TestEmailSender.class);
|
||||
|
||||
@Inject
|
||||
private DataSource dataSource;
|
||||
|
||||
|
@ -110,7 +113,7 @@ class TestEmailSender implements DebugSection {
|
|||
try {
|
||||
htmlEmail = sendMailSsl.initializeMail(email);
|
||||
} catch (EmailException e) {
|
||||
ConsoleLogger.logException("Failed to create email for sample email:", e);
|
||||
logger.logException("Failed to create email for sample email:", e);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -12,6 +12,7 @@ import org.bukkit.entity.Player;
|
|||
|
||||
import javax.inject.Inject;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
/**
|
||||
* The command for a player to change his password with.
|
||||
|
@ -35,7 +36,7 @@ public class ChangePasswordCommand extends PlayerCommand {
|
|||
|
||||
@Override
|
||||
public void runCommand(Player player, List<String> arguments) {
|
||||
String name = player.getName().toLowerCase();
|
||||
String name = player.getName().toLowerCase(Locale.ROOT);
|
||||
|
||||
if (!playerCache.isAuthenticated(name)) {
|
||||
commonService.send(player, MessageKey.NOT_LOGGED_IN);
|
||||
|
|
|
@ -3,6 +3,7 @@ package fr.xephi.authme.command.executable.email;
|
|||
import fr.xephi.authme.ConsoleLogger;
|
||||
import fr.xephi.authme.command.PlayerCommand;
|
||||
import fr.xephi.authme.datasource.DataSource;
|
||||
import fr.xephi.authme.output.ConsoleLoggerFactory;
|
||||
import fr.xephi.authme.message.MessageKey;
|
||||
import fr.xephi.authme.security.PasswordSecurity;
|
||||
import fr.xephi.authme.security.crypts.HashedPassword;
|
||||
|
@ -20,6 +21,8 @@ import java.util.List;
|
|||
*/
|
||||
public class EmailSetPasswordCommand extends PlayerCommand {
|
||||
|
||||
private final ConsoleLogger logger = ConsoleLoggerFactory.get(EmailSetPasswordCommand.class);
|
||||
|
||||
@Inject
|
||||
private DataSource dataSource;
|
||||
|
||||
|
@ -46,7 +49,7 @@ public class EmailSetPasswordCommand extends PlayerCommand {
|
|||
HashedPassword hashedPassword = passwordSecurity.computeHash(password, name);
|
||||
dataSource.updatePassword(name, hashedPassword);
|
||||
recoveryService.removeFromSuccessfulRecovery(player);
|
||||
ConsoleLogger.info("Player '" + name + "' has changed their password from recovery");
|
||||
logger.info("Player '" + name + "' has changed their password from recovery");
|
||||
commonService.send(player, MessageKey.PASSWORD_CHANGED_SUCCESS);
|
||||
} else {
|
||||
commonService.send(player, result.getMessageKey(), result.getArgs());
|
||||
|
|
|
@ -5,6 +5,7 @@ import fr.xephi.authme.ConsoleLogger;
|
|||
import fr.xephi.authme.command.PlayerCommand;
|
||||
import fr.xephi.authme.data.auth.PlayerCache;
|
||||
import fr.xephi.authme.datasource.DataSource;
|
||||
import fr.xephi.authme.output.ConsoleLoggerFactory;
|
||||
import fr.xephi.authme.mail.EmailService;
|
||||
import fr.xephi.authme.message.MessageKey;
|
||||
import fr.xephi.authme.service.BukkitService;
|
||||
|
@ -22,6 +23,8 @@ import java.util.List;
|
|||
*/
|
||||
public class RecoverEmailCommand extends PlayerCommand {
|
||||
|
||||
private final ConsoleLogger logger = ConsoleLoggerFactory.get(RecoverEmailCommand.class);
|
||||
|
||||
@Inject
|
||||
private CommonService commonService;
|
||||
|
||||
|
@ -49,7 +52,7 @@ public class RecoverEmailCommand extends PlayerCommand {
|
|||
final String playerName = player.getName();
|
||||
|
||||
if (!emailService.hasAllInformation()) {
|
||||
ConsoleLogger.warning("Mail API is not set");
|
||||
logger.warning("Mail API is not set");
|
||||
commonService.send(player, MessageKey.INCOMPLETE_EMAIL_SETTINGS);
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@ package fr.xephi.authme.command.executable.register;
|
|||
import fr.xephi.authme.ConsoleLogger;
|
||||
import fr.xephi.authme.command.PlayerCommand;
|
||||
import fr.xephi.authme.data.captcha.RegistrationCaptchaManager;
|
||||
import fr.xephi.authme.output.ConsoleLoggerFactory;
|
||||
import fr.xephi.authme.mail.EmailService;
|
||||
import fr.xephi.authme.message.MessageKey;
|
||||
import fr.xephi.authme.process.Management;
|
||||
|
@ -34,6 +35,8 @@ import static fr.xephi.authme.settings.properties.RegistrationSettings.REGISTER_
|
|||
*/
|
||||
public class RegisterCommand extends PlayerCommand {
|
||||
|
||||
private final ConsoleLogger logger = ConsoleLoggerFactory.get(RegisterCommand.class);
|
||||
|
||||
@Inject
|
||||
private Management management;
|
||||
|
||||
|
@ -155,7 +158,7 @@ public class RegisterCommand extends PlayerCommand {
|
|||
private void handleEmailRegistration(Player player, List<String> arguments) {
|
||||
if (!emailService.hasAllInformation()) {
|
||||
commonService.send(player, MessageKey.INCOMPLETE_EMAIL_SETTINGS);
|
||||
ConsoleLogger.warning("Cannot register player '" + player.getName() + "': no email or password is set "
|
||||
logger.warning("Cannot register player '" + player.getName() + "': no email or password is set "
|
||||
+ "to send emails from. Please adjust your config at " + EmailSettings.MAIL_ACCOUNT.getPath());
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@ import fr.xephi.authme.command.PlayerCommand;
|
|||
import fr.xephi.authme.data.auth.PlayerAuth;
|
||||
import fr.xephi.authme.data.auth.PlayerCache;
|
||||
import fr.xephi.authme.datasource.DataSource;
|
||||
import fr.xephi.authme.output.ConsoleLoggerFactory;
|
||||
import fr.xephi.authme.message.MessageKey;
|
||||
import fr.xephi.authme.message.Messages;
|
||||
import fr.xephi.authme.security.totp.GenerateTotpService;
|
||||
|
@ -19,6 +20,8 @@ import java.util.List;
|
|||
*/
|
||||
public class ConfirmTotpCommand extends PlayerCommand {
|
||||
|
||||
private final ConsoleLogger logger = ConsoleLoggerFactory.get(ConfirmTotpCommand.class);
|
||||
|
||||
@Inject
|
||||
private GenerateTotpService generateTotpService;
|
||||
|
||||
|
@ -63,7 +66,7 @@ public class ConfirmTotpCommand extends PlayerCommand {
|
|||
messages.send(player, MessageKey.TWO_FACTOR_ENABLE_SUCCESS);
|
||||
auth.setTotpKey(totpDetails.getTotpKey());
|
||||
playerCache.updatePlayer(auth);
|
||||
ConsoleLogger.info("Player '" + player.getName() + "' has successfully added a TOTP key to their account");
|
||||
logger.info("Player '" + player.getName() + "' has successfully added a TOTP key to their account");
|
||||
} else {
|
||||
messages.send(player, MessageKey.ERROR);
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@ import fr.xephi.authme.command.PlayerCommand;
|
|||
import fr.xephi.authme.data.auth.PlayerAuth;
|
||||
import fr.xephi.authme.data.auth.PlayerCache;
|
||||
import fr.xephi.authme.datasource.DataSource;
|
||||
import fr.xephi.authme.output.ConsoleLoggerFactory;
|
||||
import fr.xephi.authme.message.MessageKey;
|
||||
import fr.xephi.authme.message.Messages;
|
||||
import fr.xephi.authme.security.totp.TotpAuthenticator;
|
||||
|
@ -18,6 +19,8 @@ import java.util.List;
|
|||
*/
|
||||
public class RemoveTotpCommand extends PlayerCommand {
|
||||
|
||||
private final ConsoleLogger logger = ConsoleLoggerFactory.get(RemoveTotpCommand.class);
|
||||
|
||||
@Inject
|
||||
private DataSource dataSource;
|
||||
|
||||
|
@ -51,7 +54,7 @@ public class RemoveTotpCommand extends PlayerCommand {
|
|||
auth.setTotpKey(null);
|
||||
playerCache.updatePlayer(auth);
|
||||
messages.send(player, MessageKey.TWO_FACTOR_REMOVED_SUCCESS);
|
||||
ConsoleLogger.info("Player '" + player.getName() + "' removed their TOTP key");
|
||||
logger.info("Player '" + player.getName() + "' removed their TOTP key");
|
||||
} else {
|
||||
messages.send(player, MessageKey.ERROR);
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@ import fr.xephi.authme.data.limbo.LimboPlayer;
|
|||
import fr.xephi.authme.data.limbo.LimboPlayerState;
|
||||
import fr.xephi.authme.data.limbo.LimboService;
|
||||
import fr.xephi.authme.datasource.DataSource;
|
||||
import fr.xephi.authme.output.ConsoleLoggerFactory;
|
||||
import fr.xephi.authme.message.MessageKey;
|
||||
import fr.xephi.authme.message.Messages;
|
||||
import fr.xephi.authme.process.login.AsynchronousLogin;
|
||||
|
@ -22,6 +23,8 @@ import java.util.List;
|
|||
*/
|
||||
public class TotpCodeCommand extends PlayerCommand {
|
||||
|
||||
private final ConsoleLogger logger = ConsoleLoggerFactory.get(TotpCodeCommand.class);
|
||||
|
||||
@Inject
|
||||
private LimboService limboService;
|
||||
|
||||
|
@ -57,7 +60,7 @@ public class TotpCodeCommand extends PlayerCommand {
|
|||
if (limbo != null && limbo.getState() == LimboPlayerState.TOTP_REQUIRED) {
|
||||
processCode(player, auth, arguments.get(0));
|
||||
} else {
|
||||
ConsoleLogger.debug(() -> "Aborting TOTP check for player '" + player.getName()
|
||||
logger.debug(() -> "Aborting TOTP check for player '" + player.getName()
|
||||
+ "'. Invalid limbo state: " + (limbo == null ? "no limbo" : limbo.getState()));
|
||||
messages.send(player, MessageKey.LOGIN_MESSAGE);
|
||||
}
|
||||
|
@ -66,10 +69,10 @@ public class TotpCodeCommand extends PlayerCommand {
|
|||
private void processCode(Player player, PlayerAuth auth, String inputCode) {
|
||||
boolean isCodeValid = totpAuthenticator.checkCode(auth, inputCode);
|
||||
if (isCodeValid) {
|
||||
ConsoleLogger.debug("Successfully checked TOTP code for `{0}`", player.getName());
|
||||
logger.debug("Successfully checked TOTP code for `{0}`", player.getName());
|
||||
asynchronousLogin.performLogin(player, auth);
|
||||
} else {
|
||||
ConsoleLogger.debug("Input TOTP code was invalid for player `{0}`", player.getName());
|
||||
logger.debug("Input TOTP code was invalid for player `{0}`", player.getName());
|
||||
messages.send(player, MessageKey.TWO_FACTOR_INVALID_CODE);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -31,7 +31,7 @@ public class UnregisterCommand extends PlayerCommand {
|
|||
@Override
|
||||
public void runCommand(Player player, List<String> arguments) {
|
||||
String playerPass = arguments.get(0);
|
||||
final String playerName = player.getName();
|
||||
String playerName = player.getName();
|
||||
|
||||
// Make sure the player is authenticated
|
||||
if (!playerCache.isAuthenticated(playerName)) {
|
||||
|
|
|
@ -3,6 +3,7 @@ package fr.xephi.authme.command.executable.verification;
|
|||
import fr.xephi.authme.ConsoleLogger;
|
||||
import fr.xephi.authme.command.PlayerCommand;
|
||||
import fr.xephi.authme.data.VerificationCodeManager;
|
||||
import fr.xephi.authme.output.ConsoleLoggerFactory;
|
||||
import fr.xephi.authme.message.MessageKey;
|
||||
import fr.xephi.authme.service.CommonService;
|
||||
import org.bukkit.entity.Player;
|
||||
|
@ -15,6 +16,8 @@ import java.util.List;
|
|||
*/
|
||||
public class VerificationCommand extends PlayerCommand {
|
||||
|
||||
private final ConsoleLogger logger = ConsoleLoggerFactory.get(VerificationCommand.class);
|
||||
|
||||
@Inject
|
||||
private CommonService commonService;
|
||||
|
||||
|
@ -26,7 +29,7 @@ public class VerificationCommand extends PlayerCommand {
|
|||
final String playerName = player.getName();
|
||||
|
||||
if (!codeManager.canSendMail()) {
|
||||
ConsoleLogger.warning("Mail API is not set");
|
||||
logger.warning("Mail API is not set");
|
||||
commonService.send(player, MessageKey.INCOMPLETE_EMAIL_SETTINGS);
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,49 @@
|
|||
package fr.xephi.authme.data;
|
||||
|
||||
import fr.xephi.authme.initialization.HasCleanup;
|
||||
import fr.xephi.authme.util.expiring.ExpiringSet;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import java.util.Locale;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public class ProxySessionManager implements HasCleanup {
|
||||
|
||||
private final ExpiringSet<String> activeProxySessions;
|
||||
|
||||
@Inject
|
||||
public ProxySessionManager() {
|
||||
long countTimeout = 5;
|
||||
activeProxySessions = new ExpiringSet<>(countTimeout, TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves the player in the set
|
||||
* @param name the player's name
|
||||
*/
|
||||
private void setActiveSession(String name) {
|
||||
activeProxySessions.add(name.toLowerCase(Locale.ROOT));
|
||||
}
|
||||
|
||||
/**
|
||||
* Process a proxy session message from AuthMeBungee
|
||||
* @param name the player to process
|
||||
*/
|
||||
public void processProxySessionMessage(String name) {
|
||||
setActiveSession(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns if the player should be logged in or not
|
||||
* @param name the name of the player to check
|
||||
* @return true if player has to be logged in, false otherwise
|
||||
*/
|
||||
public boolean shouldResumeSession(String name) {
|
||||
return activeProxySessions.contains(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void performCleanup() {
|
||||
activeProxySessions.removeExpiredEntries();
|
||||
}
|
||||
}
|
|
@ -16,6 +16,7 @@ import org.bukkit.entity.Player;
|
|||
|
||||
import javax.inject.Inject;
|
||||
import java.util.HashSet;
|
||||
import java.util.Locale;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
|
@ -82,7 +83,7 @@ public class VerificationCodeManager implements SettingsDependent, HasCleanup {
|
|||
* @return true if the player has been verified, false otherwise
|
||||
*/
|
||||
private boolean isPlayerVerified(String name) {
|
||||
return verifiedPlayers.contains(name.toLowerCase());
|
||||
return verifiedPlayers.contains(name.toLowerCase(Locale.ROOT));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -92,7 +93,7 @@ public class VerificationCodeManager implements SettingsDependent, HasCleanup {
|
|||
* @return true if the code exists, false otherwise
|
||||
*/
|
||||
public boolean hasCode(String name) {
|
||||
return (verificationCodes.get(name.toLowerCase()) != null);
|
||||
return (verificationCodes.get(name.toLowerCase(Locale.ROOT)) != null);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -135,7 +136,7 @@ public class VerificationCodeManager implements SettingsDependent, HasCleanup {
|
|||
final String email = emailResult.getValue();
|
||||
if (!Utils.isEmailEmpty(email)) {
|
||||
String code = RandomStringUtils.generateNum(6); // 6 digits code
|
||||
verificationCodes.put(name.toLowerCase(), code);
|
||||
verificationCodes.put(name.toLowerCase(Locale.ROOT), code);
|
||||
emailService.sendVerificationMail(name, email, code);
|
||||
}
|
||||
}
|
||||
|
@ -150,7 +151,7 @@ public class VerificationCodeManager implements SettingsDependent, HasCleanup {
|
|||
*/
|
||||
public boolean checkCode(String name, String code) {
|
||||
boolean correct = false;
|
||||
if (code.equals(verificationCodes.get(name.toLowerCase()))) {
|
||||
if (code.equals(verificationCodes.get(name.toLowerCase(Locale.ROOT)))) {
|
||||
verify(name);
|
||||
correct = true;
|
||||
}
|
||||
|
@ -163,7 +164,7 @@ public class VerificationCodeManager implements SettingsDependent, HasCleanup {
|
|||
* @param name the name of the player to generate a code for
|
||||
*/
|
||||
public void verify(String name) {
|
||||
verifiedPlayers.add(name.toLowerCase());
|
||||
verifiedPlayers.add(name.toLowerCase(Locale.ROOT));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -172,7 +173,7 @@ public class VerificationCodeManager implements SettingsDependent, HasCleanup {
|
|||
* @param name the name of the player to generate a code for
|
||||
*/
|
||||
public void unverify(String name){
|
||||
verifiedPlayers.remove(name.toLowerCase());
|
||||
verifiedPlayers.remove(name.toLowerCase(Locale.ROOT));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -3,15 +3,18 @@ package fr.xephi.authme.data.auth;
|
|||
import fr.xephi.authme.security.crypts.HashedPassword;
|
||||
import org.bukkit.Location;
|
||||
|
||||
import java.util.Locale;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
|
||||
import static com.google.common.base.MoreObjects.firstNonNull;
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
|
||||
/**
|
||||
* AuthMe player data.
|
||||
*/
|
||||
@SuppressWarnings("checkstyle:FinalClass") // Justification: class is mocked in multiple tests
|
||||
public class PlayerAuth {
|
||||
|
||||
/** Default email used in the database if the email column is defined to be NOT NULL. */
|
||||
|
@ -40,6 +43,7 @@ public class PlayerAuth {
|
|||
private String world;
|
||||
private float yaw;
|
||||
private float pitch;
|
||||
private UUID uuid;
|
||||
|
||||
/**
|
||||
* Hidden constructor.
|
||||
|
@ -51,7 +55,7 @@ public class PlayerAuth {
|
|||
|
||||
|
||||
public void setNickname(String nickname) {
|
||||
this.nickname = nickname.toLowerCase();
|
||||
this.nickname = nickname.toLowerCase(Locale.ROOT);
|
||||
}
|
||||
|
||||
public String getNickname() {
|
||||
|
@ -169,6 +173,14 @@ public class PlayerAuth {
|
|||
this.totpKey = totpKey;
|
||||
}
|
||||
|
||||
public UUID getUuid() {
|
||||
return uuid;
|
||||
}
|
||||
|
||||
public void setUuid(UUID uuid) {
|
||||
this.uuid = uuid;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (!(obj instanceof PlayerAuth)) {
|
||||
|
@ -193,7 +205,8 @@ public class PlayerAuth {
|
|||
+ " ! LastLogin : " + lastLogin
|
||||
+ " ! LastPosition : " + x + "," + y + "," + z + "," + world
|
||||
+ " ! Email : " + email
|
||||
+ " ! Password : {" + password.getHash() + ", " + password.getSalt() + "}";
|
||||
+ " ! Password : {" + password.getHash() + ", " + password.getSalt() + "}"
|
||||
+ " ! UUID : " + uuid;
|
||||
}
|
||||
|
||||
public static Builder builder() {
|
||||
|
@ -218,6 +231,7 @@ public class PlayerAuth {
|
|||
private String world;
|
||||
private float yaw;
|
||||
private float pitch;
|
||||
private UUID uuid;
|
||||
|
||||
/**
|
||||
* Creates a PlayerAuth object.
|
||||
|
@ -226,9 +240,9 @@ public class PlayerAuth {
|
|||
*/
|
||||
public PlayerAuth build() {
|
||||
PlayerAuth auth = new PlayerAuth();
|
||||
auth.nickname = checkNotNull(name).toLowerCase();
|
||||
auth.realName = firstNonNull(realName, "Player");
|
||||
auth.password = firstNonNull(password, new HashedPassword(""));
|
||||
auth.nickname = checkNotNull(name).toLowerCase(Locale.ROOT);
|
||||
auth.realName = Optional.ofNullable(realName).orElse("Player");
|
||||
auth.password = Optional.ofNullable(password).orElse(new HashedPassword(""));
|
||||
auth.totpKey = totpKey;
|
||||
auth.email = DB_EMAIL_DEFAULT.equals(email) ? null : email;
|
||||
auth.lastIp = lastIp; // Don't check against default value 127.0.0.1 as it may be a legit value
|
||||
|
@ -240,9 +254,10 @@ public class PlayerAuth {
|
|||
auth.x = x;
|
||||
auth.y = y;
|
||||
auth.z = z;
|
||||
auth.world = firstNonNull(world, "world");
|
||||
auth.world = Optional.ofNullable(world).orElse("world");
|
||||
auth.yaw = yaw;
|
||||
auth.pitch = pitch;
|
||||
auth.uuid = uuid;
|
||||
return auth;
|
||||
}
|
||||
|
||||
|
@ -349,5 +364,10 @@ public class PlayerAuth {
|
|||
this.registrationDate = date;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder uuid(UUID uuid) {
|
||||
this.uuid = uuid;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package fr.xephi.authme.data.auth;
|
||||
|
||||
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
|
@ -20,7 +21,7 @@ public class PlayerCache {
|
|||
* @param auth the player auth object to save
|
||||
*/
|
||||
public void updatePlayer(PlayerAuth auth) {
|
||||
cache.put(auth.getNickname().toLowerCase(), auth);
|
||||
cache.put(auth.getNickname().toLowerCase(Locale.ROOT), auth);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -29,7 +30,7 @@ public class PlayerCache {
|
|||
* @param user name of the player to remove
|
||||
*/
|
||||
public void removePlayer(String user) {
|
||||
cache.remove(user.toLowerCase());
|
||||
cache.remove(user.toLowerCase(Locale.ROOT));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -40,7 +41,7 @@ public class PlayerCache {
|
|||
* @return true if player is logged in, false otherwise.
|
||||
*/
|
||||
public boolean isAuthenticated(String user) {
|
||||
return cache.containsKey(user.toLowerCase());
|
||||
return cache.containsKey(user.toLowerCase(Locale.ROOT));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -51,7 +52,7 @@ public class PlayerCache {
|
|||
* @return the associated auth object, or null if not available
|
||||
*/
|
||||
public PlayerAuth getAuth(String user) {
|
||||
return cache.get(user.toLowerCase());
|
||||
return cache.get(user.toLowerCase(Locale.ROOT));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -3,6 +3,7 @@ package fr.xephi.authme.data.captcha;
|
|||
import fr.xephi.authme.util.RandomStringUtils;
|
||||
import fr.xephi.authme.util.expiring.ExpiringMap;
|
||||
|
||||
import java.util.Locale;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
|
@ -51,7 +52,7 @@ public class CaptchaCodeStorage {
|
|||
* @return the code the player is required to enter
|
||||
*/
|
||||
public String getCodeOrGenerateNew(String name) {
|
||||
String code = captchaCodes.get(name.toLowerCase());
|
||||
String code = captchaCodes.get(name.toLowerCase(Locale.ROOT));
|
||||
return code == null ? generateCode(name) : code;
|
||||
}
|
||||
|
||||
|
@ -63,7 +64,7 @@ public class CaptchaCodeStorage {
|
|||
*/
|
||||
private String generateCode(String name) {
|
||||
String code = RandomStringUtils.generate(captchaLength);
|
||||
captchaCodes.put(name.toLowerCase(), code);
|
||||
captchaCodes.put(name.toLowerCase(Locale.ROOT), code);
|
||||
return code;
|
||||
}
|
||||
|
||||
|
@ -76,7 +77,7 @@ public class CaptchaCodeStorage {
|
|||
* @return true if the code matches, false otherwise
|
||||
*/
|
||||
public boolean checkCode(String name, String code) {
|
||||
String nameLowerCase = name.toLowerCase();
|
||||
String nameLowerCase = name.toLowerCase(Locale.ROOT);
|
||||
String savedCode = captchaCodes.get(nameLowerCase);
|
||||
if (savedCode != null && savedCode.equalsIgnoreCase(code)) {
|
||||
captchaCodes.remove(nameLowerCase);
|
||||
|
|
|
@ -8,6 +8,7 @@ import fr.xephi.authme.util.expiring.TimedCounter;
|
|||
import org.bukkit.entity.Player;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import java.util.Locale;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
|
@ -36,14 +37,14 @@ public class LoginCaptchaManager implements CaptchaManager, SettingsDependent, H
|
|||
*/
|
||||
public void increaseLoginFailureCount(String name) {
|
||||
if (isEnabled) {
|
||||
String playerLower = name.toLowerCase();
|
||||
String playerLower = name.toLowerCase(Locale.ROOT);
|
||||
playerCounts.increment(playerLower);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCaptchaRequired(String playerName) {
|
||||
return isEnabled && playerCounts.get(playerName.toLowerCase()) >= threshold;
|
||||
return isEnabled && playerCounts.get(playerName.toLowerCase(Locale.ROOT)) >= threshold;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -53,7 +54,7 @@ public class LoginCaptchaManager implements CaptchaManager, SettingsDependent, H
|
|||
|
||||
@Override
|
||||
public boolean checkCode(Player player, String code) {
|
||||
String nameLower = player.getName().toLowerCase();
|
||||
String nameLower = player.getName().toLowerCase(Locale.ROOT);
|
||||
boolean isCodeCorrect = captchaCodeStorage.checkCode(nameLower, code);
|
||||
if (isCodeCorrect) {
|
||||
playerCounts.remove(nameLower);
|
||||
|
@ -68,7 +69,7 @@ public class LoginCaptchaManager implements CaptchaManager, SettingsDependent, H
|
|||
*/
|
||||
public void resetLoginFailureCount(String name) {
|
||||
if (isEnabled) {
|
||||
playerCounts.remove(name.toLowerCase());
|
||||
playerCounts.remove(name.toLowerCase(Locale.ROOT));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -8,6 +8,7 @@ import fr.xephi.authme.util.expiring.ExpiringSet;
|
|||
import org.bukkit.entity.Player;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import java.util.Locale;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
|
@ -31,7 +32,7 @@ public class RegistrationCaptchaManager implements CaptchaManager, SettingsDepen
|
|||
|
||||
@Override
|
||||
public boolean isCaptchaRequired(String name) {
|
||||
return isEnabled && !verifiedNamesForRegistration.contains(name.toLowerCase());
|
||||
return isEnabled && !verifiedNamesForRegistration.contains(name.toLowerCase(Locale.ROOT));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -41,7 +42,7 @@ public class RegistrationCaptchaManager implements CaptchaManager, SettingsDepen
|
|||
|
||||
@Override
|
||||
public boolean checkCode(Player player, String code) {
|
||||
String nameLower = player.getName().toLowerCase();
|
||||
String nameLower = player.getName().toLowerCase(Locale.ROOT);
|
||||
boolean isCodeCorrect = captchaCodeStorage.checkCode(nameLower, code);
|
||||
if (isCodeCorrect) {
|
||||
verifiedNamesForRegistration.add(nameLower);
|
||||
|
|
|
@ -2,6 +2,7 @@ package fr.xephi.authme.data.limbo;
|
|||
|
||||
import fr.xephi.authme.ConsoleLogger;
|
||||
import fr.xephi.authme.initialization.Reloadable;
|
||||
import fr.xephi.authme.output.ConsoleLoggerFactory;
|
||||
import fr.xephi.authme.permission.PermissionsManager;
|
||||
import fr.xephi.authme.settings.Settings;
|
||||
import fr.xephi.authme.settings.properties.PluginSettings;
|
||||
|
@ -26,14 +27,16 @@ import java.util.Collections;
|
|||
*/
|
||||
class AuthGroupHandler implements Reloadable {
|
||||
|
||||
private final ConsoleLogger logger = ConsoleLoggerFactory.get(AuthGroupHandler.class);
|
||||
|
||||
@Inject
|
||||
private PermissionsManager permissionsManager;
|
||||
|
||||
@Inject
|
||||
private Settings settings;
|
||||
|
||||
private String unregisteredGroup;
|
||||
private String registeredGroup;
|
||||
private UserGroup unregisteredGroup;
|
||||
private UserGroup registeredGroup;
|
||||
|
||||
AuthGroupHandler() {
|
||||
}
|
||||
|
@ -50,7 +53,7 @@ class AuthGroupHandler implements Reloadable {
|
|||
return;
|
||||
}
|
||||
|
||||
Collection<String> previousGroups = limbo == null ? Collections.emptyList() : limbo.getGroups();
|
||||
Collection<UserGroup> previousGroups = limbo == null ? Collections.emptyList() : limbo.getGroups();
|
||||
|
||||
switch (groupType) {
|
||||
// Implementation note: some permission systems don't support players not being in any group,
|
||||
|
@ -78,7 +81,7 @@ class AuthGroupHandler implements Reloadable {
|
|||
throw new IllegalStateException("Encountered unhandled auth group type '" + groupType + "'");
|
||||
}
|
||||
|
||||
ConsoleLogger.debug(() -> player.getName() + " changed to "
|
||||
logger.debug(() -> player.getName() + " changed to "
|
||||
+ groupType + ": has groups " + permissionsManager.getGroups(player));
|
||||
}
|
||||
|
||||
|
@ -95,7 +98,7 @@ class AuthGroupHandler implements Reloadable {
|
|||
|
||||
// Make sure group support is available
|
||||
if (!permissionsManager.hasGroupSupport()) {
|
||||
ConsoleLogger.warning("The current permissions system doesn't have group support, unable to set group!");
|
||||
logger.warning("The current permissions system doesn't have group support, unable to set group!");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
@ -104,8 +107,8 @@ class AuthGroupHandler implements Reloadable {
|
|||
@Override
|
||||
@PostConstruct
|
||||
public void reload() {
|
||||
unregisteredGroup = settings.getProperty(PluginSettings.UNREGISTERED_GROUP);
|
||||
registeredGroup = settings.getProperty(PluginSettings.REGISTERED_GROUP);
|
||||
unregisteredGroup = new UserGroup(settings.getProperty(PluginSettings.UNREGISTERED_GROUP));
|
||||
registeredGroup = new UserGroup(settings.getProperty(PluginSettings.REGISTERED_GROUP));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@ import fr.xephi.authme.task.MessageTask;
|
|||
import org.bukkit.Location;
|
||||
import org.bukkit.scheduler.BukkitTask;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
|
||||
/**
|
||||
|
@ -17,7 +18,7 @@ public class LimboPlayer {
|
|||
|
||||
private final boolean canFly;
|
||||
private final boolean operator;
|
||||
private final Collection<String> groups;
|
||||
private final Collection<UserGroup> groups;
|
||||
private final Location loc;
|
||||
private final float walkSpeed;
|
||||
private final float flySpeed;
|
||||
|
@ -25,11 +26,11 @@ public class LimboPlayer {
|
|||
private MessageTask messageTask = null;
|
||||
private LimboPlayerState state = LimboPlayerState.PASSWORD_REQUIRED;
|
||||
|
||||
public LimboPlayer(Location loc, boolean operator, Collection<String> groups, boolean fly, float walkSpeed,
|
||||
public LimboPlayer(Location loc, boolean operator, Collection<UserGroup> groups, boolean fly, float walkSpeed,
|
||||
float flySpeed) {
|
||||
this.loc = loc;
|
||||
this.operator = operator;
|
||||
this.groups = groups;
|
||||
this.groups = new ArrayList<>(groups); // prevent bug #2413
|
||||
this.canFly = fly;
|
||||
this.walkSpeed = walkSpeed;
|
||||
this.flySpeed = flySpeed;
|
||||
|
@ -58,7 +59,7 @@ public class LimboPlayer {
|
|||
*
|
||||
* @return The permissions groups the player belongs to
|
||||
*/
|
||||
public Collection<String> getGroups() {
|
||||
public Collection<UserGroup> getGroups() {
|
||||
return groups;
|
||||
}
|
||||
|
||||
|
|
|
@ -2,12 +2,14 @@ package fr.xephi.authme.data.limbo;
|
|||
|
||||
import fr.xephi.authme.ConsoleLogger;
|
||||
import fr.xephi.authme.data.limbo.persistence.LimboPersistence;
|
||||
import fr.xephi.authme.output.ConsoleLoggerFactory;
|
||||
import fr.xephi.authme.settings.Settings;
|
||||
import fr.xephi.authme.settings.SpawnLoader;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
@ -22,6 +24,8 @@ import static fr.xephi.authme.settings.properties.LimboSettings.RESTORE_WALK_SPE
|
|||
*/
|
||||
public class LimboService {
|
||||
|
||||
private final ConsoleLogger logger = ConsoleLoggerFactory.get(LimboService.class);
|
||||
|
||||
private final Map<String, LimboPlayer> entries = new ConcurrentHashMap<>();
|
||||
|
||||
@Inject
|
||||
|
@ -52,17 +56,17 @@ public class LimboService {
|
|||
* @param isRegistered whether or not the player is registered
|
||||
*/
|
||||
public void createLimboPlayer(Player player, boolean isRegistered) {
|
||||
final String name = player.getName().toLowerCase();
|
||||
final String name = player.getName().toLowerCase(Locale.ROOT);
|
||||
|
||||
LimboPlayer limboFromDisk = persistence.getLimboPlayer(player);
|
||||
if (limboFromDisk != null) {
|
||||
ConsoleLogger.debug("LimboPlayer for `{0}` already exists on disk", name);
|
||||
logger.debug("LimboPlayer for `{0}` already exists on disk", name);
|
||||
}
|
||||
|
||||
LimboPlayer existingLimbo = entries.remove(name);
|
||||
if (existingLimbo != null) {
|
||||
existingLimbo.clearTasks();
|
||||
ConsoleLogger.debug("LimboPlayer for `{0}` already present in memory", name);
|
||||
logger.debug("LimboPlayer for `{0}` already present in memory", name);
|
||||
}
|
||||
|
||||
Location location = spawnLoader.getPlayerLocationOrSpawn(player);
|
||||
|
@ -86,7 +90,7 @@ public class LimboService {
|
|||
* @return the associated limbo player, or null if none available
|
||||
*/
|
||||
public LimboPlayer getLimboPlayer(String name) {
|
||||
return entries.get(name.toLowerCase());
|
||||
return entries.get(name.toLowerCase(Locale.ROOT));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -96,7 +100,7 @@ public class LimboService {
|
|||
* @return true if present, false otherwise
|
||||
*/
|
||||
public boolean hasLimboPlayer(String name) {
|
||||
return entries.containsKey(name.toLowerCase());
|
||||
return entries.containsKey(name.toLowerCase(Locale.ROOT));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -108,18 +112,18 @@ public class LimboService {
|
|||
* @param player the player whose data should be restored
|
||||
*/
|
||||
public void restoreData(Player player) {
|
||||
String lowerName = player.getName().toLowerCase();
|
||||
String lowerName = player.getName().toLowerCase(Locale.ROOT);
|
||||
LimboPlayer limbo = entries.remove(lowerName);
|
||||
|
||||
if (limbo == null) {
|
||||
ConsoleLogger.debug("No LimboPlayer found for `{0}` - cannot restore", lowerName);
|
||||
logger.debug("No LimboPlayer found for `{0}` - cannot restore", lowerName);
|
||||
} else {
|
||||
player.setOp(limbo.isOperator());
|
||||
settings.getProperty(RESTORE_ALLOW_FLIGHT).restoreAllowFlight(player, limbo);
|
||||
settings.getProperty(RESTORE_FLY_SPEED).restoreFlySpeed(player, limbo);
|
||||
settings.getProperty(RESTORE_WALK_SPEED).restoreWalkSpeed(player, limbo);
|
||||
limbo.clearTasks();
|
||||
ConsoleLogger.debug("Restored LimboPlayer stats for `{0}`", lowerName);
|
||||
logger.debug("Restored LimboPlayer stats for `{0}`", lowerName);
|
||||
persistence.removeLimboPlayer(player);
|
||||
}
|
||||
authGroupHandler.setGroup(player, limbo, AuthGroupType.LOGGED_IN);
|
||||
|
@ -175,9 +179,9 @@ public class LimboService {
|
|||
* @return Optional with the limbo player
|
||||
*/
|
||||
private Optional<LimboPlayer> getLimboOrLogError(Player player, String context) {
|
||||
LimboPlayer limbo = entries.get(player.getName().toLowerCase());
|
||||
LimboPlayer limbo = entries.get(player.getName().toLowerCase(Locale.ROOT));
|
||||
if (limbo == null) {
|
||||
ConsoleLogger.debug("No LimboPlayer found for `{0}`. Action: {1}", player.getName(), context);
|
||||
logger.debug("No LimboPlayer found for `{0}`. Action: {1}", player.getName(), context);
|
||||
}
|
||||
return Optional.ofNullable(limbo);
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package fr.xephi.authme.data.limbo;
|
||||
|
||||
import fr.xephi.authme.ConsoleLogger;
|
||||
import fr.xephi.authme.output.ConsoleLoggerFactory;
|
||||
import fr.xephi.authme.permission.PermissionsManager;
|
||||
import fr.xephi.authme.settings.Settings;
|
||||
import fr.xephi.authme.settings.properties.LimboSettings;
|
||||
|
@ -11,14 +12,18 @@ import org.bukkit.entity.Player;
|
|||
import javax.inject.Inject;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import static fr.xephi.authme.util.Utils.isCollectionEmpty;
|
||||
import static java.util.stream.Collectors.toList;
|
||||
|
||||
/**
|
||||
* Helper class for the LimboService.
|
||||
*/
|
||||
class LimboServiceHelper {
|
||||
|
||||
private final ConsoleLogger logger = ConsoleLoggerFactory.get(LimboServiceHelper.class);
|
||||
|
||||
@Inject
|
||||
private PermissionsManager permissionsManager;
|
||||
|
||||
|
@ -28,9 +33,9 @@ class LimboServiceHelper {
|
|||
/**
|
||||
* Creates a LimboPlayer with the given player's details.
|
||||
*
|
||||
* @param player the player to process
|
||||
* @param player the player to process
|
||||
* @param isRegistered whether the player is registered
|
||||
* @param location the player location
|
||||
* @param location the player location
|
||||
* @return limbo player with the player's data
|
||||
*/
|
||||
LimboPlayer createLimboPlayer(Player player, boolean isRegistered, Location location) {
|
||||
|
@ -39,10 +44,14 @@ class LimboServiceHelper {
|
|||
boolean flyEnabled = player.getAllowFlight();
|
||||
float walkSpeed = player.getWalkSpeed();
|
||||
float flySpeed = player.getFlySpeed();
|
||||
Collection<String> playerGroups = permissionsManager.hasGroupSupport()
|
||||
Collection<UserGroup> playerGroups = permissionsManager.hasGroupSupport()
|
||||
? permissionsManager.getGroups(player) : Collections.emptyList();
|
||||
ConsoleLogger.debug("Player `{0}` has groups `{1}`", player.getName(), String.join(", ", playerGroups));
|
||||
|
||||
List<String> groupNames = playerGroups.stream()
|
||||
.map(UserGroup::getGroupName)
|
||||
.collect(toList());
|
||||
|
||||
logger.debug("Player `{0}` has groups `{1}`", player.getName(), String.join(", ", groupNames));
|
||||
return new LimboPlayer(location, isOperator, playerGroups, flyEnabled, walkSpeed, flySpeed);
|
||||
}
|
||||
|
||||
|
@ -88,7 +97,7 @@ class LimboServiceHelper {
|
|||
boolean canFly = newLimbo.isCanFly() || oldLimbo.isCanFly();
|
||||
float flySpeed = Math.max(newLimbo.getFlySpeed(), oldLimbo.getFlySpeed());
|
||||
float walkSpeed = Math.max(newLimbo.getWalkSpeed(), oldLimbo.getWalkSpeed());
|
||||
Collection<String> groups = getLimboGroups(oldLimbo.getGroups(), newLimbo.getGroups());
|
||||
Collection<UserGroup> groups = getLimboGroups(oldLimbo.getGroups(), newLimbo.getGroups());
|
||||
Location location = firstNotNull(oldLimbo.getLocation(), newLimbo.getLocation());
|
||||
|
||||
return new LimboPlayer(location, isOperator, groups, canFly, walkSpeed, flySpeed);
|
||||
|
@ -98,9 +107,9 @@ class LimboServiceHelper {
|
|||
return first == null ? second : first;
|
||||
}
|
||||
|
||||
private static Collection<String> getLimboGroups(Collection<String> oldLimboGroups,
|
||||
Collection<String> newLimboGroups) {
|
||||
ConsoleLogger.debug("Limbo merge: new and old groups are `{0}` and `{1}`", newLimboGroups, oldLimboGroups);
|
||||
private Collection<UserGroup> getLimboGroups(Collection<UserGroup> oldLimboGroups,
|
||||
Collection<UserGroup> newLimboGroups) {
|
||||
logger.debug("Limbo merge: new and old groups are `{0}` and `{1}`", newLimboGroups, oldLimboGroups);
|
||||
return isCollectionEmpty(oldLimboGroups) ? newLimboGroups : oldLimboGroups;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,45 @@
|
|||
package fr.xephi.authme.data.limbo;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
public class UserGroup {
|
||||
|
||||
private String groupName;
|
||||
private Map<String, String> contextMap;
|
||||
|
||||
public UserGroup(String groupName) {
|
||||
this.groupName = groupName;
|
||||
}
|
||||
|
||||
public UserGroup(String groupName, Map<String, String> contextMap) {
|
||||
this.groupName = groupName;
|
||||
this.contextMap = contextMap;
|
||||
}
|
||||
|
||||
public String getGroupName() {
|
||||
return groupName;
|
||||
}
|
||||
|
||||
public Map<String, String> getContextMap() {
|
||||
return contextMap;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (o == null || getClass() != o.getClass()) {
|
||||
return false;
|
||||
}
|
||||
UserGroup userGroup = (UserGroup) o;
|
||||
return Objects.equals(groupName, userGroup.groupName)
|
||||
&& Objects.equals(contextMap, userGroup.contextMap);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(groupName, contextMap);
|
||||
}
|
||||
}
|
|
@ -1,6 +1,7 @@
|
|||
package fr.xephi.authme.data.limbo;
|
||||
|
||||
import fr.xephi.authme.ConsoleLogger;
|
||||
import fr.xephi.authme.output.ConsoleLoggerFactory;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
/**
|
||||
|
@ -15,14 +16,14 @@ public enum WalkFlySpeedRestoreType {
|
|||
RESTORE {
|
||||
@Override
|
||||
public void restoreFlySpeed(Player player, LimboPlayer limbo) {
|
||||
ConsoleLogger.debug("Restoring fly speed for LimboPlayer " + player.getName() + " to "
|
||||
logger.debug(() -> "Restoring fly speed for LimboPlayer " + player.getName() + " to "
|
||||
+ limbo.getFlySpeed() + " (RESTORE mode)");
|
||||
player.setFlySpeed(limbo.getFlySpeed());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void restoreWalkSpeed(Player player, LimboPlayer limbo) {
|
||||
ConsoleLogger.debug("Restoring walk speed for LimboPlayer " + player.getName() + " to "
|
||||
logger.debug(() -> "Restoring walk speed for LimboPlayer " + player.getName() + " to "
|
||||
+ limbo.getWalkSpeed() + " (RESTORE mode)");
|
||||
player.setWalkSpeed(limbo.getWalkSpeed());
|
||||
}
|
||||
|
@ -36,11 +37,11 @@ public enum WalkFlySpeedRestoreType {
|
|||
public void restoreFlySpeed(Player player, LimboPlayer limbo) {
|
||||
float limboFlySpeed = limbo.getFlySpeed();
|
||||
if (limboFlySpeed > 0.01f) {
|
||||
ConsoleLogger.debug("Restoring fly speed for LimboPlayer " + player.getName() + " to "
|
||||
logger.debug(() -> "Restoring fly speed for LimboPlayer " + player.getName() + " to "
|
||||
+ limboFlySpeed + " (RESTORE_NO_ZERO mode)");
|
||||
player.setFlySpeed(limboFlySpeed);
|
||||
} else {
|
||||
ConsoleLogger.debug("Restoring fly speed for LimboPlayer " + player.getName()
|
||||
logger.debug(() -> "Restoring fly speed for LimboPlayer " + player.getName()
|
||||
+ " to DEFAULT, it was 0! (RESTORE_NO_ZERO mode)");
|
||||
player.setFlySpeed(LimboPlayer.DEFAULT_FLY_SPEED);
|
||||
}
|
||||
|
@ -50,11 +51,11 @@ public enum WalkFlySpeedRestoreType {
|
|||
public void restoreWalkSpeed(Player player, LimboPlayer limbo) {
|
||||
float limboWalkSpeed = limbo.getWalkSpeed();
|
||||
if (limboWalkSpeed > 0.01f) {
|
||||
ConsoleLogger.debug("Restoring walk speed for LimboPlayer " + player.getName() + " to "
|
||||
logger.debug(() -> "Restoring walk speed for LimboPlayer " + player.getName() + " to "
|
||||
+ limboWalkSpeed + " (RESTORE_NO_ZERO mode)");
|
||||
player.setWalkSpeed(limboWalkSpeed);
|
||||
} else {
|
||||
ConsoleLogger.debug("Restoring walk speed for LimboPlayer " + player.getName() + ""
|
||||
logger.debug(() -> "Restoring walk speed for LimboPlayer " + player.getName() + ""
|
||||
+ " to DEFAULT, it was 0! (RESTORE_NO_ZERO mode)");
|
||||
player.setWalkSpeed(LimboPlayer.DEFAULT_WALK_SPEED);
|
||||
}
|
||||
|
@ -68,7 +69,7 @@ public enum WalkFlySpeedRestoreType {
|
|||
@Override
|
||||
public void restoreFlySpeed(Player player, LimboPlayer limbo) {
|
||||
float newSpeed = Math.max(player.getFlySpeed(), limbo.getFlySpeed());
|
||||
ConsoleLogger.debug("Restoring fly speed for LimboPlayer " + player.getName() + " to " + newSpeed
|
||||
logger.debug(() -> "Restoring fly speed for LimboPlayer " + player.getName() + " to " + newSpeed
|
||||
+ " (Current: " + player.getFlySpeed() + ", Limbo: " + limbo.getFlySpeed() + ") (MAX_RESTORE mode)");
|
||||
player.setFlySpeed(newSpeed);
|
||||
}
|
||||
|
@ -76,7 +77,7 @@ public enum WalkFlySpeedRestoreType {
|
|||
@Override
|
||||
public void restoreWalkSpeed(Player player, LimboPlayer limbo) {
|
||||
float newSpeed = Math.max(player.getWalkSpeed(), limbo.getWalkSpeed());
|
||||
ConsoleLogger.debug("Restoring walk speed for LimboPlayer " + player.getName() + " to " + newSpeed
|
||||
logger.debug(() -> "Restoring walk speed for LimboPlayer " + player.getName() + " to " + newSpeed
|
||||
+ " (Current: " + player.getWalkSpeed() + ", Limbo: " + limbo.getWalkSpeed() + ") (MAX_RESTORE mode)");
|
||||
player.setWalkSpeed(newSpeed);
|
||||
}
|
||||
|
@ -88,19 +89,21 @@ public enum WalkFlySpeedRestoreType {
|
|||
DEFAULT {
|
||||
@Override
|
||||
public void restoreFlySpeed(Player player, LimboPlayer limbo) {
|
||||
ConsoleLogger.debug("Restoring fly speed for LimboPlayer " + player.getName()
|
||||
logger.debug(() -> "Restoring fly speed for LimboPlayer " + player.getName()
|
||||
+ " to DEFAULT (DEFAULT mode)");
|
||||
player.setFlySpeed(LimboPlayer.DEFAULT_FLY_SPEED);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void restoreWalkSpeed(Player player, LimboPlayer limbo) {
|
||||
ConsoleLogger.debug("Restoring walk speed for LimboPlayer " + player.getName()
|
||||
logger.debug(() -> "Restoring walk speed for LimboPlayer " + player.getName()
|
||||
+ " to DEFAULT (DEFAULT mode)");
|
||||
player.setWalkSpeed(LimboPlayer.DEFAULT_WALK_SPEED);
|
||||
}
|
||||
};
|
||||
|
||||
private static final ConsoleLogger logger = ConsoleLoggerFactory.get(WalkFlySpeedRestoreType.class);
|
||||
|
||||
/**
|
||||
* Restores the fly speed from Limbo to Player according to the restoration type.
|
||||
*
|
||||
|
|
|
@ -7,11 +7,11 @@ import com.google.gson.GsonBuilder;
|
|||
import fr.xephi.authme.ConsoleLogger;
|
||||
import fr.xephi.authme.data.limbo.LimboPlayer;
|
||||
import fr.xephi.authme.initialization.DataFolder;
|
||||
import fr.xephi.authme.output.ConsoleLoggerFactory;
|
||||
import fr.xephi.authme.service.BukkitService;
|
||||
import fr.xephi.authme.settings.Settings;
|
||||
import fr.xephi.authme.settings.properties.LimboSettings;
|
||||
import fr.xephi.authme.util.FileUtils;
|
||||
import fr.xephi.authme.util.PlayerUtils;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
@ -34,6 +34,7 @@ class DistributedFilesPersistenceHandler implements LimboPersistenceHandler {
|
|||
|
||||
private static final Type LIMBO_MAP_TYPE = new TypeToken<Map<String, LimboPlayer>>(){}.getType();
|
||||
|
||||
private final ConsoleLogger logger = ConsoleLoggerFactory.get(DistributedFilesPersistenceHandler.class);
|
||||
private final File cacheFolder;
|
||||
private final Gson gson;
|
||||
private final SegmentNameBuilder segmentNameBuilder;
|
||||
|
@ -57,7 +58,7 @@ class DistributedFilesPersistenceHandler implements LimboPersistenceHandler {
|
|||
|
||||
@Override
|
||||
public LimboPlayer getLimboPlayer(Player player) {
|
||||
String uuid = PlayerUtils.getUuidOrName(player);
|
||||
String uuid = player.getUniqueId().toString();
|
||||
File file = getPlayerSegmentFile(uuid);
|
||||
Map<String, LimboPlayer> entries = readLimboPlayers(file);
|
||||
return entries == null ? null : entries.get(uuid);
|
||||
|
@ -65,7 +66,7 @@ class DistributedFilesPersistenceHandler implements LimboPersistenceHandler {
|
|||
|
||||
@Override
|
||||
public void saveLimboPlayer(Player player, LimboPlayer limbo) {
|
||||
String uuid = PlayerUtils.getUuidOrName(player);
|
||||
String uuid = player.getUniqueId().toString();
|
||||
File file = getPlayerSegmentFile(uuid);
|
||||
|
||||
Map<String, LimboPlayer> entries = null;
|
||||
|
@ -79,17 +80,17 @@ class DistributedFilesPersistenceHandler implements LimboPersistenceHandler {
|
|||
entries = new HashMap<>();
|
||||
}
|
||||
|
||||
entries.put(PlayerUtils.getUuidOrName(player), limbo);
|
||||
entries.put(uuid, limbo);
|
||||
saveEntries(entries, file);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeLimboPlayer(Player player) {
|
||||
String uuid = PlayerUtils.getUuidOrName(player);
|
||||
String uuid = player.getUniqueId().toString();
|
||||
File file = getPlayerSegmentFile(uuid);
|
||||
if (file.exists()) {
|
||||
Map<String, LimboPlayer> entries = readLimboPlayers(file);
|
||||
if (entries != null && entries.remove(PlayerUtils.getUuidOrName(player)) != null) {
|
||||
if (entries != null && entries.remove(uuid) != null) {
|
||||
saveEntries(entries, file);
|
||||
}
|
||||
}
|
||||
|
@ -104,7 +105,7 @@ class DistributedFilesPersistenceHandler implements LimboPersistenceHandler {
|
|||
try (FileWriter fw = new FileWriter(file)) {
|
||||
gson.toJson(entries, fw);
|
||||
} catch (Exception e) {
|
||||
ConsoleLogger.logException("Could not write to '" + file + "':", e);
|
||||
logger.logException("Could not write to '" + file + "':", e);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -116,7 +117,7 @@ class DistributedFilesPersistenceHandler implements LimboPersistenceHandler {
|
|||
try {
|
||||
return gson.fromJson(Files.asCharSource(file, StandardCharsets.UTF_8).read(), LIMBO_MAP_TYPE);
|
||||
} catch (Exception e) {
|
||||
ConsoleLogger.logException("Failed reading '" + file + "':", e);
|
||||
logger.logException("Failed reading '" + file + "':", e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
@ -165,7 +166,7 @@ class DistributedFilesPersistenceHandler implements LimboPersistenceHandler {
|
|||
private void saveToNewSegments(Map<String, LimboPlayer> limbosFromOldSegments) {
|
||||
Map<String, Map<String, LimboPlayer>> limboBySegment = groupBySegment(limbosFromOldSegments);
|
||||
|
||||
ConsoleLogger.info("Saving " + limbosFromOldSegments.size() + " LimboPlayers from old segments into "
|
||||
logger.info("Saving " + limbosFromOldSegments.size() + " LimboPlayers from old segments into "
|
||||
+ limboBySegment.size() + " current segments");
|
||||
for (Map.Entry<String, Map<String, LimboPlayer>> entry : limboBySegment.entrySet()) {
|
||||
File file = getSegmentFile(entry.getKey());
|
||||
|
@ -204,7 +205,7 @@ class DistributedFilesPersistenceHandler implements LimboPersistenceHandler {
|
|||
.filter(f -> isLimboJsonFile(f) && f.length() < 3)
|
||||
.peek(FileUtils::delete)
|
||||
.count();
|
||||
ConsoleLogger.debug("Limbo: Deleted {0} empty segment files", deletedFiles);
|
||||
logger.debug("Limbo: Deleted {0} empty segment files", deletedFiles);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -216,10 +217,10 @@ class DistributedFilesPersistenceHandler implements LimboPersistenceHandler {
|
|||
return name.startsWith("seg") && name.endsWith("-limbo.json");
|
||||
}
|
||||
|
||||
private static File[] listFiles(File folder) {
|
||||
private File[] listFiles(File folder) {
|
||||
File[] files = folder.listFiles();
|
||||
if (files == null) {
|
||||
ConsoleLogger.warning("Could not get files of '" + folder + "'");
|
||||
logger.warning("Could not get files of '" + folder + "'");
|
||||
return new File[0];
|
||||
}
|
||||
return files;
|
||||
|
|
|
@ -6,9 +6,9 @@ import com.google.gson.GsonBuilder;
|
|||
import fr.xephi.authme.ConsoleLogger;
|
||||
import fr.xephi.authme.data.limbo.LimboPlayer;
|
||||
import fr.xephi.authme.initialization.DataFolder;
|
||||
import fr.xephi.authme.output.ConsoleLoggerFactory;
|
||||
import fr.xephi.authme.service.BukkitService;
|
||||
import fr.xephi.authme.util.FileUtils;
|
||||
import fr.xephi.authme.util.PlayerUtils;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
@ -21,6 +21,8 @@ import java.nio.charset.StandardCharsets;
|
|||
*/
|
||||
class IndividualFilesPersistenceHandler implements LimboPersistenceHandler {
|
||||
|
||||
private final ConsoleLogger logger = ConsoleLoggerFactory.get(IndividualFilesPersistenceHandler.class);
|
||||
|
||||
private final Gson gson;
|
||||
private final File cacheDir;
|
||||
|
||||
|
@ -28,7 +30,7 @@ class IndividualFilesPersistenceHandler implements LimboPersistenceHandler {
|
|||
IndividualFilesPersistenceHandler(@DataFolder File dataFolder, BukkitService bukkitService) {
|
||||
cacheDir = new File(dataFolder, "playerdata");
|
||||
if (!cacheDir.exists() && !cacheDir.isDirectory() && !cacheDir.mkdir()) {
|
||||
ConsoleLogger.warning("Failed to create playerdata directory '" + cacheDir + "'");
|
||||
logger.warning("Failed to create playerdata directory '" + cacheDir + "'");
|
||||
}
|
||||
gson = new GsonBuilder()
|
||||
.registerTypeAdapter(LimboPlayer.class, new LimboPlayerSerializer())
|
||||
|
@ -39,7 +41,7 @@ class IndividualFilesPersistenceHandler implements LimboPersistenceHandler {
|
|||
|
||||
@Override
|
||||
public LimboPlayer getLimboPlayer(Player player) {
|
||||
String id = PlayerUtils.getUuidOrName(player);
|
||||
String id = player.getUniqueId().toString();
|
||||
File file = new File(cacheDir, id + File.separator + "data.json");
|
||||
if (!file.exists()) {
|
||||
return null;
|
||||
|
@ -49,21 +51,21 @@ class IndividualFilesPersistenceHandler implements LimboPersistenceHandler {
|
|||
String str = Files.asCharSource(file, StandardCharsets.UTF_8).read();
|
||||
return gson.fromJson(str, LimboPlayer.class);
|
||||
} catch (IOException e) {
|
||||
ConsoleLogger.logException("Could not read player data on disk for '" + player.getName() + "'", e);
|
||||
logger.logException("Could not read player data on disk for '" + player.getName() + "'", e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void saveLimboPlayer(Player player, LimboPlayer limboPlayer) {
|
||||
String id = PlayerUtils.getUuidOrName(player);
|
||||
String id = player.getUniqueId().toString();
|
||||
try {
|
||||
File file = new File(cacheDir, id + File.separator + "data.json");
|
||||
Files.createParentDirs(file);
|
||||
Files.touch(file);
|
||||
Files.write(gson.toJson(limboPlayer), file, StandardCharsets.UTF_8);
|
||||
} catch (IOException e) {
|
||||
ConsoleLogger.logException("Failed to write " + player.getName() + " data:", e);
|
||||
logger.logException("Failed to write " + player.getName() + " data:", e);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -75,7 +77,7 @@ class IndividualFilesPersistenceHandler implements LimboPersistenceHandler {
|
|||
*/
|
||||
@Override
|
||||
public void removeLimboPlayer(Player player) {
|
||||
String id = PlayerUtils.getUuidOrName(player);
|
||||
String id = player.getUniqueId().toString();
|
||||
File file = new File(cacheDir, id);
|
||||
if (file.exists()) {
|
||||
FileUtils.purgeDirectory(file);
|
||||
|
|
|
@ -4,6 +4,7 @@ import ch.jalu.injector.factory.Factory;
|
|||
import fr.xephi.authme.ConsoleLogger;
|
||||
import fr.xephi.authme.data.limbo.LimboPlayer;
|
||||
import fr.xephi.authme.initialization.SettingsDependent;
|
||||
import fr.xephi.authme.output.ConsoleLoggerFactory;
|
||||
import fr.xephi.authme.settings.Settings;
|
||||
import fr.xephi.authme.settings.properties.LimboSettings;
|
||||
import org.bukkit.entity.Player;
|
||||
|
@ -15,6 +16,8 @@ import javax.inject.Inject;
|
|||
*/
|
||||
public class LimboPersistence implements SettingsDependent {
|
||||
|
||||
private final ConsoleLogger logger = ConsoleLoggerFactory.get(LimboPersistence.class);
|
||||
|
||||
private final Factory<LimboPersistenceHandler> handlerFactory;
|
||||
|
||||
private LimboPersistenceHandler handler;
|
||||
|
@ -35,7 +38,7 @@ public class LimboPersistence implements SettingsDependent {
|
|||
try {
|
||||
return handler.getLimboPlayer(player);
|
||||
} catch (Exception e) {
|
||||
ConsoleLogger.logException("Could not get LimboPlayer for '" + player.getName() + "'", e);
|
||||
logger.logException("Could not get LimboPlayer for '" + player.getName() + "'", e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
@ -50,7 +53,7 @@ public class LimboPersistence implements SettingsDependent {
|
|||
try {
|
||||
handler.saveLimboPlayer(player, limbo);
|
||||
} catch (Exception e) {
|
||||
ConsoleLogger.logException("Could not save LimboPlayer for '" + player.getName() + "'", e);
|
||||
logger.logException("Could not save LimboPlayer for '" + player.getName() + "'", e);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -63,7 +66,7 @@ public class LimboPersistence implements SettingsDependent {
|
|||
try {
|
||||
handler.removeLimboPlayer(player);
|
||||
} catch (Exception e) {
|
||||
ConsoleLogger.logException("Could not remove LimboPlayer for '" + player.getName() + "'", e);
|
||||
logger.logException("Could not remove LimboPlayer for '" + player.getName() + "'", e);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -72,7 +75,7 @@ public class LimboPersistence implements SettingsDependent {
|
|||
LimboPersistenceType persistenceType = settings.getProperty(LimboSettings.LIMBO_PERSISTENCE_TYPE);
|
||||
// If we're changing from an existing handler, output a quick hint that nothing is converted.
|
||||
if (handler != null && handler.getType() != persistenceType) {
|
||||
ConsoleLogger.info("Limbo persistence type has changed! Note that the data is not converted.");
|
||||
logger.info("Limbo persistence type has changed! Note that the data is not converted.");
|
||||
}
|
||||
handler = handlerFactory.newInstance(persistenceType.getImplementationClass());
|
||||
}
|
||||
|
|
|
@ -1,11 +1,14 @@
|
|||
package fr.xephi.authme.data.limbo.persistence;
|
||||
|
||||
import com.google.common.reflect.TypeToken;
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.JsonArray;
|
||||
import com.google.gson.JsonDeserializationContext;
|
||||
import com.google.gson.JsonDeserializer;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
import fr.xephi.authme.data.limbo.LimboPlayer;
|
||||
import fr.xephi.authme.data.limbo.UserGroup;
|
||||
import fr.xephi.authme.service.BukkitService;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.World;
|
||||
|
@ -15,6 +18,7 @@ import java.util.ArrayList;
|
|||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.Function;
|
||||
|
||||
import static fr.xephi.authme.data.limbo.persistence.LimboPlayerSerializer.CAN_FLY;
|
||||
|
@ -37,6 +41,8 @@ import static java.util.Optional.ofNullable;
|
|||
class LimboPlayerDeserializer implements JsonDeserializer<LimboPlayer> {
|
||||
|
||||
private static final String GROUP_LEGACY = "group";
|
||||
private static final String CONTEXT_MAP = "contextMap";
|
||||
private static final String GROUP_NAME = "groupName";
|
||||
|
||||
private BukkitService bukkitService;
|
||||
|
||||
|
@ -54,7 +60,7 @@ class LimboPlayerDeserializer implements JsonDeserializer<LimboPlayer> {
|
|||
Location loc = deserializeLocation(jsonObject);
|
||||
boolean operator = getBoolean(jsonObject, IS_OP);
|
||||
|
||||
Collection<String> groups = getLimboGroups(jsonObject);
|
||||
Collection<UserGroup> groups = getLimboGroups(jsonObject);
|
||||
boolean canFly = getBoolean(jsonObject, CAN_FLY);
|
||||
float walkSpeed = getFloat(jsonObject, WALK_SPEED, LimboPlayer.DEFAULT_WALK_SPEED);
|
||||
float flySpeed = getFloat(jsonObject, FLY_SPEED, LimboPlayer.DEFAULT_FLY_SPEED);
|
||||
|
@ -84,16 +90,35 @@ class LimboPlayerDeserializer implements JsonDeserializer<LimboPlayer> {
|
|||
return element != null ? element.getAsString() : "";
|
||||
}
|
||||
|
||||
private static List<String> getLimboGroups(JsonObject jsonObject) {
|
||||
/**
|
||||
* @param jsonObject LimboPlayer represented as JSON
|
||||
* @return The list of UserGroups create from JSON
|
||||
*/
|
||||
private static List<UserGroup> getLimboGroups(JsonObject jsonObject) {
|
||||
JsonElement element = jsonObject.get(GROUPS);
|
||||
if (element == null) {
|
||||
String legacyGroup = ofNullable(jsonObject.get(GROUP_LEGACY)).map(JsonElement::getAsString).orElse(null);
|
||||
return legacyGroup == null ? Collections.emptyList() : Collections.singletonList(legacyGroup);
|
||||
return legacyGroup == null ? Collections.emptyList() :
|
||||
Collections.singletonList(new UserGroup(legacyGroup, null));
|
||||
}
|
||||
List<String> result = new ArrayList<>();
|
||||
List<UserGroup> result = new ArrayList<>();
|
||||
JsonArray jsonArray = element.getAsJsonArray();
|
||||
for (JsonElement arrayElement : jsonArray) {
|
||||
result.add(arrayElement.getAsString());
|
||||
if (!arrayElement.isJsonObject()) {
|
||||
result.add(new UserGroup(arrayElement.getAsString(), null));
|
||||
} else {
|
||||
JsonObject jsonGroup = arrayElement.getAsJsonObject();
|
||||
Map<String, String> contextMap = null;
|
||||
if (jsonGroup.has(CONTEXT_MAP)) {
|
||||
JsonElement contextMapJson = jsonGroup.get("contextMap");
|
||||
Type type = new TypeToken<Map<String, String>>() {
|
||||
}.getType();
|
||||
contextMap = new Gson().fromJson(contextMapJson.getAsString(), type);
|
||||
}
|
||||
|
||||
String groupName = jsonGroup.get(GROUP_NAME).getAsString();
|
||||
result.add(new UserGroup(groupName, contextMap));
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
@ -122,7 +147,6 @@ class LimboPlayerDeserializer implements JsonDeserializer<LimboPlayer> {
|
|||
* @param numberFunction the function to get the number from the element
|
||||
* @param defaultValue the value to return if the element is null or the number cannot be retrieved
|
||||
* @param <N> the number type
|
||||
*
|
||||
* @return the number from the given JSON element, or the default value
|
||||
*/
|
||||
private static <N extends Number> N getNumberFromElement(JsonElement jsonElement,
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package fr.xephi.authme.data.limbo.persistence;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.JsonArray;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonSerializationContext;
|
||||
|
@ -9,6 +10,8 @@ import fr.xephi.authme.data.limbo.LimboPlayer;
|
|||
import org.bukkit.Location;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Converts a LimboPlayer to a JsonElement.
|
||||
|
@ -45,7 +48,19 @@ class LimboPlayerSerializer implements JsonSerializer<LimboPlayer> {
|
|||
|
||||
JsonObject obj = new JsonObject();
|
||||
obj.add(LOCATION, locationObject);
|
||||
obj.add(GROUPS, GSON.toJsonTree(limboPlayer.getGroups()).getAsJsonArray());
|
||||
|
||||
List<JsonObject> groups = limboPlayer.getGroups().stream().map(g -> {
|
||||
JsonObject jsonGroup = new JsonObject();
|
||||
jsonGroup.addProperty("groupName", g.getGroupName());
|
||||
if (g.getContextMap() != null) {
|
||||
jsonGroup.addProperty("contextMap", GSON.toJson(g.getContextMap()));
|
||||
}
|
||||
return jsonGroup;
|
||||
}).collect(Collectors.toList());
|
||||
|
||||
JsonArray jsonGroups = new JsonArray();
|
||||
groups.forEach(jsonGroups::add);
|
||||
obj.add(GROUPS, jsonGroups);
|
||||
|
||||
obj.addProperty(IS_OP, limboPlayer.isOperator());
|
||||
obj.addProperty(CAN_FLY, limboPlayer.isCanFly());
|
||||
|
|
|
@ -53,7 +53,8 @@ public abstract class AbstractSqlDataSource implements DataSource {
|
|||
public boolean saveAuth(PlayerAuth auth) {
|
||||
return columnsHandler.insert(auth,
|
||||
AuthMeColumns.NAME, AuthMeColumns.NICK_NAME, AuthMeColumns.PASSWORD, AuthMeColumns.SALT,
|
||||
AuthMeColumns.EMAIL, AuthMeColumns.REGISTRATION_DATE, AuthMeColumns.REGISTRATION_IP);
|
||||
AuthMeColumns.EMAIL, AuthMeColumns.REGISTRATION_DATE, AuthMeColumns.REGISTRATION_IP,
|
||||
AuthMeColumns.UUID);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -166,4 +167,6 @@ public abstract class AbstractSqlDataSource implements DataSource {
|
|||
return DataSourceValueImpl.unknownRow();
|
||||
}
|
||||
}
|
||||
|
||||
abstract String getJdbcUrl(String host, String port, String database);
|
||||
}
|
||||
|
|
|
@ -12,11 +12,13 @@ import com.google.common.util.concurrent.ThreadFactoryBuilder;
|
|||
import fr.xephi.authme.ConsoleLogger;
|
||||
import fr.xephi.authme.data.auth.PlayerAuth;
|
||||
import fr.xephi.authme.data.auth.PlayerCache;
|
||||
import fr.xephi.authme.output.ConsoleLoggerFactory;
|
||||
import fr.xephi.authme.security.crypts.HashedPassword;
|
||||
import fr.xephi.authme.util.Utils;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.Executors;
|
||||
|
@ -25,6 +27,8 @@ import java.util.stream.Collectors;
|
|||
|
||||
public class CacheDataSource implements DataSource {
|
||||
|
||||
private final ConsoleLogger logger = ConsoleLoggerFactory.get(CacheDataSource.class);
|
||||
|
||||
private final DataSource source;
|
||||
private final PlayerCache playerCache;
|
||||
private final LoadingCache<String, Optional<PlayerAuth>> cachedAuths;
|
||||
|
@ -83,7 +87,7 @@ public class CacheDataSource implements DataSource {
|
|||
|
||||
@Override
|
||||
public HashedPassword getPassword(String user) {
|
||||
user = user.toLowerCase();
|
||||
user = user.toLowerCase(Locale.ROOT);
|
||||
Optional<PlayerAuth> pAuthOpt = cachedAuths.getIfPresent(user);
|
||||
if (pAuthOpt != null && pAuthOpt.isPresent()) {
|
||||
return pAuthOpt.get().getPassword();
|
||||
|
@ -93,7 +97,7 @@ public class CacheDataSource implements DataSource {
|
|||
|
||||
@Override
|
||||
public PlayerAuth getAuth(String user) {
|
||||
user = user.toLowerCase();
|
||||
user = user.toLowerCase(Locale.ROOT);
|
||||
return cachedAuths.getUnchecked(user).orElse(null);
|
||||
}
|
||||
|
||||
|
@ -117,7 +121,7 @@ public class CacheDataSource implements DataSource {
|
|||
|
||||
@Override
|
||||
public boolean updatePassword(String user, HashedPassword password) {
|
||||
user = user.toLowerCase();
|
||||
user = user.toLowerCase(Locale.ROOT);
|
||||
boolean result = source.updatePassword(user, password);
|
||||
if (result) {
|
||||
cachedAuths.refresh(user);
|
||||
|
@ -150,7 +154,7 @@ public class CacheDataSource implements DataSource {
|
|||
|
||||
@Override
|
||||
public boolean removeAuth(String name) {
|
||||
name = name.toLowerCase();
|
||||
name = name.toLowerCase(Locale.ROOT);
|
||||
boolean result = source.removeAuth(name);
|
||||
if (result) {
|
||||
cachedAuths.invalidate(name);
|
||||
|
@ -164,7 +168,7 @@ public class CacheDataSource implements DataSource {
|
|||
try {
|
||||
executorService.awaitTermination(5, TimeUnit.SECONDS);
|
||||
} catch (InterruptedException e) {
|
||||
ConsoleLogger.logException("Could not close executor service:", e);
|
||||
logger.logException("Could not close executor service:", e);
|
||||
}
|
||||
cachedAuths.invalidateAll();
|
||||
source.closeConnection();
|
||||
|
@ -207,12 +211,12 @@ public class CacheDataSource implements DataSource {
|
|||
|
||||
@Override
|
||||
public void setLogged(final String user) {
|
||||
source.setLogged(user.toLowerCase());
|
||||
source.setLogged(user.toLowerCase(Locale.ROOT));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setUnlogged(final String user) {
|
||||
source.setUnlogged(user.toLowerCase());
|
||||
source.setUnlogged(user.toLowerCase(Locale.ROOT));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -30,6 +30,7 @@ public final class Columns {
|
|||
public final String HAS_SESSION;
|
||||
public final String REGISTRATION_DATE;
|
||||
public final String REGISTRATION_IP;
|
||||
public final String PLAYER_UUID;
|
||||
|
||||
public Columns(Settings settings) {
|
||||
NAME = settings.getProperty(DatabaseSettings.MYSQL_COL_NAME);
|
||||
|
@ -52,6 +53,7 @@ public final class Columns {
|
|||
HAS_SESSION = settings.getProperty(DatabaseSettings.MYSQL_COL_HASSESSION);
|
||||
REGISTRATION_DATE = settings.getProperty(DatabaseSettings.MYSQL_COL_REGISTER_DATE);
|
||||
REGISTRATION_IP = settings.getProperty(DatabaseSettings.MYSQL_COL_REGISTER_IP);
|
||||
PLAYER_UUID = settings.getProperty(DatabaseSettings.MYSQL_COL_PLAYER_UUID);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -7,11 +7,10 @@ public enum DataSourceType {
|
|||
|
||||
MYSQL,
|
||||
|
||||
MARIADB,
|
||||
|
||||
POSTGRESQL,
|
||||
|
||||
SQLITE,
|
||||
|
||||
@Deprecated
|
||||
FILE
|
||||
SQLITE
|
||||
|
||||
}
|
||||
|
|
|
@ -1,437 +0,0 @@
|
|||
package fr.xephi.authme.datasource;
|
||||
|
||||
import ch.jalu.datasourcecolumns.data.DataSourceValue;
|
||||
import fr.xephi.authme.ConsoleLogger;
|
||||
import fr.xephi.authme.data.auth.PlayerAuth;
|
||||
import fr.xephi.authme.security.crypts.HashedPassword;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.BufferedWriter;
|
||||
import java.io.File;
|
||||
import java.io.FileReader;
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Deprecated flat file datasource. The only method guaranteed to work is {@link FlatFile#getAllAuths()}
|
||||
* as to migrate the entries to {@link SQLite} when AuthMe starts.
|
||||
*/
|
||||
@Deprecated
|
||||
public class FlatFile implements DataSource {
|
||||
|
||||
/*
|
||||
* file layout:
|
||||
*
|
||||
* PLAYERNAME:HASHSUM:IP:LOGININMILLIESECONDS:LASTPOSX:LASTPOSY:LASTPOSZ:
|
||||
* LASTPOSWORLD:EMAIL
|
||||
*
|
||||
* Old but compatible:
|
||||
* PLAYERNAME:HASHSUM:IP:LOGININMILLIESECONDS:LASTPOSX:LASTPOSY
|
||||
* :LASTPOSZ:LASTPOSWORLD PLAYERNAME:HASHSUM:IP:LOGININMILLIESECONDS
|
||||
* PLAYERNAME:HASHSUM:IP PLAYERNAME:HASHSUM
|
||||
*/
|
||||
private final File source;
|
||||
|
||||
public FlatFile(File source) throws IOException {
|
||||
this.source = source;
|
||||
if (!source.exists() && !source.createNewFile()) {
|
||||
throw new IOException("Could not create file '" + source.getPath() + "'");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reload() {
|
||||
throw new UnsupportedOperationException("Flatfile no longer supported");
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized boolean isAuthAvailable(String user) {
|
||||
try (BufferedReader br = new BufferedReader(new FileReader(source))) {
|
||||
String line;
|
||||
while ((line = br.readLine()) != null) {
|
||||
String[] args = line.split(":");
|
||||
if (args.length > 1 && args[0].equalsIgnoreCase(user)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} catch (IOException ex) {
|
||||
ConsoleLogger.warning(ex.getMessage());
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public HashedPassword getPassword(String user) {
|
||||
PlayerAuth auth = getAuth(user);
|
||||
if (auth != null) {
|
||||
return auth.getPassword();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized boolean saveAuth(PlayerAuth auth) {
|
||||
if (isAuthAvailable(auth.getNickname())) {
|
||||
return false;
|
||||
}
|
||||
try (BufferedWriter bw = new BufferedWriter(new FileWriter(source, true))) {
|
||||
bw.write(auth.getNickname() + ":" + auth.getPassword().getHash() + ":" + auth.getLastIp()
|
||||
+ ":" + auth.getLastLogin() + ":" + auth.getQuitLocX() + ":" + auth.getQuitLocY()
|
||||
+ ":" + auth.getQuitLocZ() + ":" + auth.getWorld() + ":" + auth.getEmail() + "\n");
|
||||
} catch (IOException ex) {
|
||||
ConsoleLogger.warning(ex.getMessage());
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized boolean updatePassword(PlayerAuth auth) {
|
||||
return updatePassword(auth.getNickname(), auth.getPassword());
|
||||
}
|
||||
|
||||
@Override
|
||||
// Note ljacqu 20151230: This does not persist the salt; it is not supported in flat file.
|
||||
public boolean updatePassword(String user, HashedPassword password) {
|
||||
user = user.toLowerCase();
|
||||
if (!isAuthAvailable(user)) {
|
||||
return false;
|
||||
}
|
||||
PlayerAuth newAuth = null;
|
||||
try (BufferedReader br = new BufferedReader(new FileReader(source))) {
|
||||
String line;
|
||||
while ((line = br.readLine()) != null) {
|
||||
String[] args = line.split(":");
|
||||
if (args[0].equals(user)) {
|
||||
newAuth = buildAuthFromArray(args);
|
||||
if (newAuth != null) {
|
||||
newAuth.setPassword(password);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
} catch (IOException ex) {
|
||||
ConsoleLogger.warning(ex.getMessage());
|
||||
return false;
|
||||
}
|
||||
if (newAuth != null) {
|
||||
removeAuth(user);
|
||||
saveAuth(newAuth);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean updateSession(PlayerAuth auth) {
|
||||
if (!isAuthAvailable(auth.getNickname())) {
|
||||
return false;
|
||||
}
|
||||
PlayerAuth newAuth = null;
|
||||
try (BufferedReader br = new BufferedReader(new FileReader(source))) {
|
||||
String line;
|
||||
while ((line = br.readLine()) != null) {
|
||||
String[] args = line.split(":");
|
||||
if (args[0].equalsIgnoreCase(auth.getNickname())) {
|
||||
newAuth = buildAuthFromArray(args);
|
||||
if (newAuth != null) {
|
||||
newAuth.setLastLogin(auth.getLastLogin());
|
||||
newAuth.setLastIp(auth.getLastIp());
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
} catch (IOException ex) {
|
||||
ConsoleLogger.warning(ex.getMessage());
|
||||
return false;
|
||||
}
|
||||
if (newAuth != null) {
|
||||
removeAuth(auth.getNickname());
|
||||
saveAuth(newAuth);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean updateQuitLoc(PlayerAuth auth) {
|
||||
if (!isAuthAvailable(auth.getNickname())) {
|
||||
return false;
|
||||
}
|
||||
PlayerAuth newAuth = null;
|
||||
try (BufferedReader br = new BufferedReader(new FileReader(source))) {
|
||||
String line;
|
||||
while ((line = br.readLine()) != null) {
|
||||
String[] args = line.split(":");
|
||||
if (args[0].equalsIgnoreCase(auth.getNickname())) {
|
||||
newAuth = buildAuthFromArray(args);
|
||||
if (newAuth != null) {
|
||||
newAuth.setQuitLocX(auth.getQuitLocX());
|
||||
newAuth.setQuitLocY(auth.getQuitLocY());
|
||||
newAuth.setQuitLocZ(auth.getQuitLocZ());
|
||||
newAuth.setWorld(auth.getWorld());
|
||||
newAuth.setEmail(auth.getEmail());
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
} catch (IOException ex) {
|
||||
ConsoleLogger.warning(ex.getMessage());
|
||||
return false;
|
||||
}
|
||||
if (newAuth != null) {
|
||||
removeAuth(auth.getNickname());
|
||||
saveAuth(newAuth);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<String> getRecordsToPurge(long until) {
|
||||
throw new UnsupportedOperationException("Flat file no longer supported");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void purgeRecords(Collection<String> toPurge) {
|
||||
throw new UnsupportedOperationException("Flat file no longer supported");
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized boolean removeAuth(String user) {
|
||||
if (!isAuthAvailable(user)) {
|
||||
return false;
|
||||
}
|
||||
ArrayList<String> lines = new ArrayList<>();
|
||||
try (BufferedReader br = new BufferedReader(new FileReader(source))) {
|
||||
|
||||
String line;
|
||||
while ((line = br.readLine()) != null) {
|
||||
String[] args = line.split(":");
|
||||
if (args.length > 1 && !args[0].equals(user)) {
|
||||
lines.add(line);
|
||||
}
|
||||
}
|
||||
try (BufferedWriter bw = new BufferedWriter(new FileWriter(source))) {
|
||||
for (String l : lines) {
|
||||
bw.write(l + "\n");
|
||||
}
|
||||
}
|
||||
} catch (IOException ex) {
|
||||
ConsoleLogger.warning(ex.getMessage());
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized PlayerAuth getAuth(String user) {
|
||||
try (BufferedReader br = new BufferedReader(new FileReader(source))) {
|
||||
String line;
|
||||
while ((line = br.readLine()) != null) {
|
||||
String[] args = line.split(":");
|
||||
if (args[0].equalsIgnoreCase(user)) {
|
||||
return buildAuthFromArray(args);
|
||||
}
|
||||
}
|
||||
} catch (IOException ex) {
|
||||
ConsoleLogger.warning(ex.getMessage());
|
||||
return null;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void closeConnection() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean updateEmail(PlayerAuth auth) {
|
||||
if (!isAuthAvailable(auth.getNickname())) {
|
||||
return false;
|
||||
}
|
||||
PlayerAuth newAuth = null;
|
||||
try (BufferedReader br = new BufferedReader(new FileReader(source))) {
|
||||
String line;
|
||||
while ((line = br.readLine()) != null) {
|
||||
String[] args = line.split(":");
|
||||
if (args[0].equals(auth.getNickname())) {
|
||||
newAuth = buildAuthFromArray(args);
|
||||
if (newAuth != null) {
|
||||
newAuth.setEmail(auth.getEmail());
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
} catch (IOException ex) {
|
||||
ConsoleLogger.warning(ex.getMessage());
|
||||
return false;
|
||||
}
|
||||
if (newAuth != null) {
|
||||
removeAuth(auth.getNickname());
|
||||
saveAuth(newAuth);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getAllAuthsByIp(String ip) {
|
||||
List<String> countIp = new ArrayList<>();
|
||||
try (BufferedReader br = new BufferedReader(new FileReader(source))) {
|
||||
String line;
|
||||
while ((line = br.readLine()) != null) {
|
||||
String[] args = line.split(":");
|
||||
if (args.length > 3 && args[2].equals(ip)) {
|
||||
countIp.add(args[0]);
|
||||
}
|
||||
}
|
||||
return countIp;
|
||||
} catch (IOException ex) {
|
||||
ConsoleLogger.warning(ex.getMessage());
|
||||
return new ArrayList<>();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int countAuthsByEmail(String email) {
|
||||
int countEmail = 0;
|
||||
try (BufferedReader br = new BufferedReader(new FileReader(source))) {
|
||||
String line;
|
||||
while ((line = br.readLine()) != null) {
|
||||
String[] args = line.split(":");
|
||||
if (args.length > 8 && args[8].equals(email)) {
|
||||
++countEmail;
|
||||
}
|
||||
}
|
||||
return countEmail;
|
||||
} catch (IOException ex) {
|
||||
ConsoleLogger.warning(ex.getMessage());
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataSourceType getType() {
|
||||
return DataSourceType.FILE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isLogged(String user) {
|
||||
throw new UnsupportedOperationException("Flat file no longer supported");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setLogged(String user) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setUnlogged(String user) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasSession(String user) {
|
||||
throw new UnsupportedOperationException("Flat file no longer supported");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void grantSession(String user) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void revokeSession(String user) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void purgeLogged() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getAccountsRegistered() {
|
||||
int result = 0;
|
||||
try (BufferedReader br = new BufferedReader(new FileReader(source))) {
|
||||
while ((br.readLine()) != null) {
|
||||
result++;
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
ConsoleLogger.warning(ex.getMessage());
|
||||
return result;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean updateRealName(String user, String realName) {
|
||||
throw new UnsupportedOperationException("Flat file no longer supported");
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataSourceValue<String> getEmail(String user) {
|
||||
throw new UnsupportedOperationException("Flat file no longer supported");
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<PlayerAuth> getAllAuths() {
|
||||
List<PlayerAuth> auths = new ArrayList<>();
|
||||
try (BufferedReader br = new BufferedReader(new FileReader(source))) {
|
||||
String line;
|
||||
while ((line = br.readLine()) != null) {
|
||||
String[] args = line.split(":");
|
||||
PlayerAuth auth = buildAuthFromArray(args);
|
||||
if (auth != null) {
|
||||
auths.add(auth);
|
||||
}
|
||||
}
|
||||
} catch (IOException ex) {
|
||||
ConsoleLogger.logException("Error while getting auths from flatfile:", ex);
|
||||
}
|
||||
return auths;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getLoggedPlayersWithEmptyMail() {
|
||||
throw new UnsupportedOperationException("Flat file no longer supported");
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<PlayerAuth> getRecentlyLoggedInPlayers() {
|
||||
throw new UnsupportedOperationException("Flat file no longer supported");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean setTotpKey(String user, String totpKey) {
|
||||
throw new UnsupportedOperationException("Flat file no longer supported");
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a PlayerAuth object from the read data.
|
||||
*
|
||||
* @param args the data read from the line
|
||||
* @return the player auth object with the data
|
||||
*/
|
||||
@SuppressWarnings("checkstyle:NeedBraces")
|
||||
private static PlayerAuth buildAuthFromArray(String[] args) {
|
||||
// Format allows 2, 3, 4, 7, 8, 9 fields. Anything else is unknown
|
||||
if (args.length >= 2 && args.length <= 9 && args.length != 5 && args.length != 6) {
|
||||
PlayerAuth.Builder builder = PlayerAuth.builder()
|
||||
.name(args[0]).realName(args[0]).password(args[1], null);
|
||||
|
||||
if (args.length >= 3) builder.lastIp(args[2]);
|
||||
if (args.length >= 4) builder.lastLogin(parseNullableLong(args[3]));
|
||||
if (args.length >= 7) {
|
||||
builder.locX(Double.parseDouble(args[4]))
|
||||
.locY(Double.parseDouble(args[5]))
|
||||
.locZ(Double.parseDouble(args[6]));
|
||||
}
|
||||
if (args.length >= 8) builder.locWorld(args[7]);
|
||||
if (args.length >= 9) builder.email(args[8]);
|
||||
return builder.build();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static Long parseNullableLong(String str) {
|
||||
return "null".equals(str) ? null : Long.parseLong(str);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
package fr.xephi.authme.datasource;
|
||||
|
||||
import fr.xephi.authme.datasource.mysqlextensions.MySqlExtensionsFactory;
|
||||
import fr.xephi.authme.settings.Settings;
|
||||
|
||||
import java.sql.SQLException;
|
||||
|
||||
public class MariaDB extends MySQL {
|
||||
public MariaDB(Settings settings, MySqlExtensionsFactory extensionsFactory) throws SQLException {
|
||||
super(settings, extensionsFactory);
|
||||
}
|
||||
|
||||
@Override
|
||||
String getJdbcUrl(String host, String port, String database) {
|
||||
return "jdbc:mariadb://" + host + ":" + port + "/" + database;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getDriverClassName() {
|
||||
return "org.mariadb.jdbc.Driver";
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataSourceType getType() {
|
||||
return DataSourceType.MARIADB;
|
||||
}
|
||||
}
|
|
@ -8,9 +8,11 @@ import fr.xephi.authme.data.auth.PlayerAuth;
|
|||
import fr.xephi.authme.datasource.columnshandler.AuthMeColumnsHandler;
|
||||
import fr.xephi.authme.datasource.mysqlextensions.MySqlExtension;
|
||||
import fr.xephi.authme.datasource.mysqlextensions.MySqlExtensionsFactory;
|
||||
import fr.xephi.authme.output.ConsoleLoggerFactory;
|
||||
import fr.xephi.authme.settings.Settings;
|
||||
import fr.xephi.authme.settings.properties.DatabaseSettings;
|
||||
import fr.xephi.authme.settings.properties.HooksSettings;
|
||||
import fr.xephi.authme.util.UuidUtils;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.DatabaseMetaData;
|
||||
|
@ -22,7 +24,9 @@ import java.util.ArrayList;
|
|||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
|
||||
import static fr.xephi.authme.datasource.SqlDataSourceUtils.getNullableLong;
|
||||
import static fr.xephi.authme.datasource.SqlDataSourceUtils.logSqlException;
|
||||
|
@ -32,8 +36,11 @@ import static fr.xephi.authme.datasource.SqlDataSourceUtils.logSqlException;
|
|||
*/
|
||||
@SuppressWarnings({"checkstyle:AbbreviationAsWordInName"}) // Justification: Class name cannot be changed anymore
|
||||
public class MySQL extends AbstractSqlDataSource {
|
||||
private final ConsoleLogger logger = ConsoleLoggerFactory.get(MySQL.class);
|
||||
|
||||
private boolean useSsl;
|
||||
private boolean serverCertificateVerification;
|
||||
private boolean allowPublicKeyRetrieval;
|
||||
private String host;
|
||||
private String port;
|
||||
private String username;
|
||||
|
@ -55,14 +62,14 @@ public class MySQL extends AbstractSqlDataSource {
|
|||
this.setConnectionArguments();
|
||||
} catch (RuntimeException e) {
|
||||
if (e instanceof IllegalArgumentException) {
|
||||
ConsoleLogger.warning("Invalid database arguments! Please check your configuration!");
|
||||
ConsoleLogger.warning("If this error persists, please report it to the developer!");
|
||||
logger.warning("Invalid database arguments! Please check your configuration!");
|
||||
logger.warning("If this error persists, please report it to the developer!");
|
||||
}
|
||||
if (e instanceof PoolInitializationException) {
|
||||
ConsoleLogger.warning("Can't initialize database connection! Please check your configuration!");
|
||||
ConsoleLogger.warning("If this error persists, please report it to the developer!");
|
||||
logger.warning("Can't initialize database connection! Please check your configuration!");
|
||||
logger.warning("If this error persists, please report it to the developer!");
|
||||
}
|
||||
ConsoleLogger.warning("Can't use the Hikari Connection Pool! Please, report this error to the developer!");
|
||||
logger.warning("Can't use the Hikari Connection Pool! Please, report this error to the developer!");
|
||||
throw e;
|
||||
}
|
||||
|
||||
|
@ -71,8 +78,8 @@ public class MySQL extends AbstractSqlDataSource {
|
|||
checkTablesAndColumns();
|
||||
} catch (SQLException e) {
|
||||
closeConnection();
|
||||
ConsoleLogger.logException("Can't initialize the MySQL database:", e);
|
||||
ConsoleLogger.warning("Please check your database settings in the config.yml file!");
|
||||
logger.logException("Can't initialize the MySQL database:", e);
|
||||
logger.warning("Please check your database settings in the config.yml file!");
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
@ -83,6 +90,15 @@ public class MySQL extends AbstractSqlDataSource {
|
|||
setParameters(settings, extensionsFactory);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the path of the Driver class to use when connecting to the database.
|
||||
*
|
||||
* @return the dotted path of the SQL driver class to be used
|
||||
*/
|
||||
protected String getDriverClassName() {
|
||||
return "com.mysql.cj.jdbc.Driver";
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves various settings.
|
||||
*
|
||||
|
@ -103,6 +119,8 @@ public class MySQL extends AbstractSqlDataSource {
|
|||
this.poolSize = settings.getProperty(DatabaseSettings.MYSQL_POOL_SIZE);
|
||||
this.maxLifetime = settings.getProperty(DatabaseSettings.MYSQL_CONNECTION_MAX_LIFETIME);
|
||||
this.useSsl = settings.getProperty(DatabaseSettings.MYSQL_USE_SSL);
|
||||
this.serverCertificateVerification = settings.getProperty(DatabaseSettings.MYSQL_CHECK_SERVER_CERTIFICATE);
|
||||
this.allowPublicKeyRetrieval = settings.getProperty(DatabaseSettings.MYSQL_ALLOW_PUBLIC_KEY_RETRIEVAL);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -114,18 +132,29 @@ public class MySQL extends AbstractSqlDataSource {
|
|||
|
||||
// Pool Settings
|
||||
ds.setMaximumPoolSize(poolSize);
|
||||
ds.setMaxLifetime(maxLifetime * 1000);
|
||||
ds.setMaxLifetime(maxLifetime * 1000L);
|
||||
|
||||
// Database URL
|
||||
ds.setJdbcUrl("jdbc:mysql://" + this.host + ":" + this.port + "/" + this.database);
|
||||
ds.setJdbcUrl(this.getJdbcUrl(this.host, this.port, this.database));
|
||||
|
||||
// Auth
|
||||
ds.setUsername(this.username);
|
||||
ds.setPassword(this.password);
|
||||
|
||||
// Driver
|
||||
ds.setDriverClassName(this.getDriverClassName());
|
||||
|
||||
// Request mysql over SSL
|
||||
ds.addDataSourceProperty("useSSL", String.valueOf(useSsl));
|
||||
|
||||
// Disabling server certificate verification on need
|
||||
if (!serverCertificateVerification) {
|
||||
ds.addDataSourceProperty("verifyServerCertificate", String.valueOf(false));
|
||||
} // Disabling server certificate verification on need
|
||||
if (allowPublicKeyRetrieval) {
|
||||
ds.addDataSourceProperty("allowPublicKeyRetrieval", String.valueOf(true));
|
||||
}
|
||||
|
||||
// Encoding
|
||||
ds.addDataSourceProperty("characterEncoding", "utf8");
|
||||
ds.addDataSourceProperty("encoding", "UTF-8");
|
||||
|
@ -140,7 +169,7 @@ public class MySQL extends AbstractSqlDataSource {
|
|||
ds.addDataSourceProperty("prepStmtCacheSize", "275");
|
||||
ds.addDataSourceProperty("prepStmtCacheSqlLimit", "2048");
|
||||
|
||||
ConsoleLogger.info("Connection arguments loaded, Hikari ConnectionPool ready!");
|
||||
logger.info("Connection arguments loaded, Hikari ConnectionPool ready!");
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -149,7 +178,7 @@ public class MySQL extends AbstractSqlDataSource {
|
|||
ds.close();
|
||||
}
|
||||
setConnectionArguments();
|
||||
ConsoleLogger.info("Hikari ConnectionPool arguments reloaded!");
|
||||
logger.info("Hikari ConnectionPool arguments reloaded!");
|
||||
}
|
||||
|
||||
private Connection getConnection() throws SQLException {
|
||||
|
@ -159,6 +188,7 @@ public class MySQL extends AbstractSqlDataSource {
|
|||
/**
|
||||
* Creates the table or any of its required columns if they don't exist.
|
||||
*/
|
||||
@SuppressWarnings({"checkstyle:CyclomaticComplexity", "checkstyle:JavaNCSS"})
|
||||
private void checkTablesAndColumns() throws SQLException {
|
||||
try (Connection con = getConnection(); Statement st = con.createStatement()) {
|
||||
// Create table with ID column if it doesn't exist
|
||||
|
@ -255,14 +285,22 @@ public class MySQL extends AbstractSqlDataSource {
|
|||
|
||||
if (isColumnMissing(md, col.TOTP_KEY)) {
|
||||
st.executeUpdate("ALTER TABLE " + tableName
|
||||
+ " ADD COLUMN " + col.TOTP_KEY + " VARCHAR(16);");
|
||||
+ " ADD COLUMN " + col.TOTP_KEY + " VARCHAR(32);");
|
||||
} else if (SqlDataSourceUtils.getColumnSize(md, tableName, col.TOTP_KEY) != 32) {
|
||||
st.executeUpdate("ALTER TABLE " + tableName
|
||||
+ " MODIFY " + col.TOTP_KEY + " VARCHAR(32);");
|
||||
}
|
||||
|
||||
if (!col.PLAYER_UUID.isEmpty() && isColumnMissing(md, col.PLAYER_UUID)) {
|
||||
st.executeUpdate("ALTER TABLE " + tableName
|
||||
+ " ADD COLUMN " + col.PLAYER_UUID + " VARCHAR(36)");
|
||||
}
|
||||
}
|
||||
ConsoleLogger.info("MySQL setup finished");
|
||||
logger.info("MySQL setup finished");
|
||||
}
|
||||
|
||||
private boolean isColumnMissing(DatabaseMetaData metaData, String columnName) throws SQLException {
|
||||
try (ResultSet rs = metaData.getColumns(null, null, tableName, columnName)) {
|
||||
try (ResultSet rs = metaData.getColumns(database, null, tableName, columnName)) {
|
||||
return !rs.next();
|
||||
}
|
||||
}
|
||||
|
@ -272,7 +310,7 @@ public class MySQL extends AbstractSqlDataSource {
|
|||
String sql = "SELECT * FROM " + tableName + " WHERE " + col.NAME + "=?;";
|
||||
PlayerAuth auth;
|
||||
try (Connection con = getConnection(); PreparedStatement pst = con.prepareStatement(sql)) {
|
||||
pst.setString(1, user.toLowerCase());
|
||||
pst.setString(1, user.toLowerCase(Locale.ROOT));
|
||||
try (ResultSet rs = pst.executeQuery()) {
|
||||
if (rs.next()) {
|
||||
int id = rs.getInt(col.ID);
|
||||
|
@ -311,6 +349,11 @@ public class MySQL extends AbstractSqlDataSource {
|
|||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
String getJdbcUrl(String host, String port, String database) {
|
||||
return "jdbc:mysql://" + host + ":" + port + "/" + database;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<String> getRecordsToPurge(long until) {
|
||||
Set<String> list = new HashSet<>();
|
||||
|
@ -335,11 +378,11 @@ public class MySQL extends AbstractSqlDataSource {
|
|||
|
||||
@Override
|
||||
public boolean removeAuth(String user) {
|
||||
user = user.toLowerCase();
|
||||
user = user.toLowerCase(Locale.ROOT);
|
||||
String sql = "DELETE FROM " + tableName + " WHERE " + col.NAME + "=?;";
|
||||
try (Connection con = getConnection(); PreparedStatement pst = con.prepareStatement(sql)) {
|
||||
sqlExtension.removeAuth(user, con);
|
||||
pst.setString(1, user.toLowerCase());
|
||||
pst.setString(1, user.toLowerCase(Locale.ROOT));
|
||||
pst.executeUpdate();
|
||||
return true;
|
||||
} catch (SQLException ex) {
|
||||
|
@ -360,7 +403,7 @@ public class MySQL extends AbstractSqlDataSource {
|
|||
String sql = "DELETE FROM " + tableName + " WHERE " + col.NAME + "=?;";
|
||||
try (Connection con = getConnection(); PreparedStatement pst = con.prepareStatement(sql)) {
|
||||
for (String name : toPurge) {
|
||||
pst.setString(1, name.toLowerCase());
|
||||
pst.setString(1, name.toLowerCase(Locale.ROOT));
|
||||
pst.executeUpdate();
|
||||
}
|
||||
} catch (SQLException ex) {
|
||||
|
@ -428,7 +471,7 @@ public class MySQL extends AbstractSqlDataSource {
|
|||
String sql = "UPDATE " + tableName + " SET " + col.TOTP_KEY + " = ? WHERE " + col.NAME + " = ?";
|
||||
try (Connection con = getConnection(); PreparedStatement pst = con.prepareStatement(sql)) {
|
||||
pst.setString(1, totpKey);
|
||||
pst.setString(2, user.toLowerCase());
|
||||
pst.setString(2, user.toLowerCase(Locale.ROOT));
|
||||
pst.executeUpdate();
|
||||
return true;
|
||||
} catch (SQLException e) {
|
||||
|
@ -447,6 +490,8 @@ public class MySQL extends AbstractSqlDataSource {
|
|||
private PlayerAuth buildAuthFromResultSet(ResultSet row) throws SQLException {
|
||||
String salt = col.SALT.isEmpty() ? null : row.getString(col.SALT);
|
||||
int group = col.GROUP.isEmpty() ? -1 : row.getInt(col.GROUP);
|
||||
UUID uuid = col.PLAYER_UUID.isEmpty()
|
||||
? null : UuidUtils.parseUuidSafely(row.getString(col.PLAYER_UUID));
|
||||
return PlayerAuth.builder()
|
||||
.name(row.getString(col.NAME))
|
||||
.realName(row.getString(col.REAL_NAME))
|
||||
|
@ -464,6 +509,7 @@ public class MySQL extends AbstractSqlDataSource {
|
|||
.locZ(row.getDouble(col.LASTLOC_Z))
|
||||
.locYaw(row.getFloat(col.LASTLOC_YAW))
|
||||
.locPitch(row.getFloat(col.LASTLOC_PITCH))
|
||||
.uuid(uuid)
|
||||
.build();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package fr.xephi.authme.datasource;
|
||||
|
||||
import fr.xephi.authme.ConsoleLogger;
|
||||
import fr.xephi.authme.output.ConsoleLoggerFactory;
|
||||
|
||||
import java.sql.DatabaseMetaData;
|
||||
import java.sql.ResultSet;
|
||||
|
@ -12,6 +13,8 @@ import java.sql.Types;
|
|||
* Performs migrations on the MySQL data source if necessary.
|
||||
*/
|
||||
final class MySqlMigrater {
|
||||
|
||||
private static ConsoleLogger logger = ConsoleLoggerFactory.get(MySqlMigrater.class);
|
||||
|
||||
private MySqlMigrater() {
|
||||
}
|
||||
|
@ -35,7 +38,7 @@ final class MySqlMigrater {
|
|||
String sql = String.format("ALTER TABLE %s MODIFY %s VARCHAR(40) CHARACTER SET ascii COLLATE ascii_bin",
|
||||
tableName, col.LAST_IP);
|
||||
st.execute(sql);
|
||||
ConsoleLogger.info("Changed last login column to allow NULL values. Please verify the registration feature "
|
||||
logger.info("Changed last login column to allow NULL values. Please verify the registration feature "
|
||||
+ "if you are hooking into a forum.");
|
||||
}
|
||||
}
|
||||
|
@ -53,55 +56,17 @@ final class MySqlMigrater {
|
|||
final int columnType;
|
||||
try (ResultSet rs = metaData.getColumns(null, null, tableName, col.LAST_LOGIN)) {
|
||||
if (!rs.next()) {
|
||||
ConsoleLogger.warning("Could not get LAST_LOGIN meta data. This should never happen!");
|
||||
logger.warning("Could not get LAST_LOGIN meta data. This should never happen!");
|
||||
return;
|
||||
}
|
||||
columnType = rs.getInt("DATA_TYPE");
|
||||
}
|
||||
|
||||
if (columnType == Types.TIMESTAMP) {
|
||||
migrateLastLoginColumnFromTimestamp(st, tableName, col);
|
||||
} else if (columnType == Types.INTEGER) {
|
||||
if (columnType == Types.INTEGER) {
|
||||
migrateLastLoginColumnFromInt(st, tableName, col);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs conversion of lastlogin column from timestamp type to bigint.
|
||||
*
|
||||
* @param st Statement object to the database
|
||||
* @param tableName the table name
|
||||
* @param col the column names configuration
|
||||
* @see <a href="https://github.com/AuthMe/AuthMeReloaded/issues/477">#477</a>
|
||||
*/
|
||||
private static void migrateLastLoginColumnFromTimestamp(Statement st, String tableName,
|
||||
Columns col) throws SQLException {
|
||||
ConsoleLogger.info("Migrating lastlogin column from timestamp to bigint");
|
||||
final String lastLoginOld = col.LAST_LOGIN + "_old";
|
||||
|
||||
// Rename lastlogin to lastlogin_old
|
||||
String sql = String.format("ALTER TABLE %s CHANGE COLUMN %s %s BIGINT",
|
||||
tableName, col.LAST_LOGIN, lastLoginOld);
|
||||
st.execute(sql);
|
||||
|
||||
// Create lastlogin column
|
||||
sql = String.format("ALTER TABLE %s ADD COLUMN %s "
|
||||
+ "BIGINT NOT NULL DEFAULT 0 AFTER %s",
|
||||
tableName, col.LAST_LOGIN, col.LAST_IP);
|
||||
st.execute(sql);
|
||||
|
||||
// Set values of lastlogin based on lastlogin_old
|
||||
sql = String.format("UPDATE %s SET %s = UNIX_TIMESTAMP(%s) * 1000",
|
||||
tableName, col.LAST_LOGIN, lastLoginOld);
|
||||
st.execute(sql);
|
||||
|
||||
// Drop lastlogin_old
|
||||
sql = String.format("ALTER TABLE %s DROP COLUMN %s",
|
||||
tableName, lastLoginOld);
|
||||
st.execute(sql);
|
||||
ConsoleLogger.info("Finished migration of lastlogin (timestamp to bigint)");
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs conversion of lastlogin column from int to bigint.
|
||||
*
|
||||
|
@ -113,7 +78,7 @@ final class MySqlMigrater {
|
|||
*/
|
||||
private static void migrateLastLoginColumnFromInt(Statement st, String tableName, Columns col) throws SQLException {
|
||||
// Change from int to bigint
|
||||
ConsoleLogger.info("Migrating lastlogin column from int to bigint");
|
||||
logger.info("Migrating lastlogin column from int to bigint");
|
||||
String sql = String.format("ALTER TABLE %s MODIFY %s BIGINT;", tableName, col.LAST_LOGIN);
|
||||
st.execute(sql);
|
||||
|
||||
|
@ -124,7 +89,7 @@ final class MySqlMigrater {
|
|||
tableName, col.LAST_LOGIN, col.LAST_LOGIN, col.LAST_LOGIN, rangeStart, col.LAST_LOGIN, rangeEnd);
|
||||
int changedRows = st.executeUpdate(sql);
|
||||
|
||||
ConsoleLogger.warning("You may have entries with invalid timestamps. Please check your data "
|
||||
logger.warning("You may have entries with invalid timestamps. Please check your data "
|
||||
+ "before purging. " + changedRows + " rows were migrated from seconds to milliseconds.");
|
||||
}
|
||||
|
||||
|
@ -145,7 +110,7 @@ final class MySqlMigrater {
|
|||
long currentTimestamp = System.currentTimeMillis();
|
||||
int updatedRows = st.executeUpdate(String.format("UPDATE %s SET %s = %d;",
|
||||
tableName, col.REGISTRATION_DATE, currentTimestamp));
|
||||
ConsoleLogger.info("Created column '" + col.REGISTRATION_DATE + "' and set the current timestamp, "
|
||||
logger.info("Created column '" + col.REGISTRATION_DATE + "' and set the current timestamp, "
|
||||
+ currentTimestamp + ", to all " + updatedRows + " rows");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@ import fr.xephi.authme.data.auth.PlayerAuth;
|
|||
import fr.xephi.authme.datasource.columnshandler.AuthMeColumnsHandler;
|
||||
import fr.xephi.authme.datasource.mysqlextensions.MySqlExtension;
|
||||
import fr.xephi.authme.datasource.mysqlextensions.MySqlExtensionsFactory;
|
||||
import fr.xephi.authme.output.ConsoleLoggerFactory;
|
||||
import fr.xephi.authme.settings.Settings;
|
||||
import fr.xephi.authme.settings.properties.DatabaseSettings;
|
||||
import fr.xephi.authme.settings.properties.HooksSettings;
|
||||
|
@ -22,6 +23,7 @@ import java.util.ArrayList;
|
|||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Set;
|
||||
|
||||
import static fr.xephi.authme.datasource.SqlDataSourceUtils.getNullableLong;
|
||||
|
@ -32,6 +34,8 @@ import static fr.xephi.authme.datasource.SqlDataSourceUtils.logSqlException;
|
|||
*/
|
||||
public class PostgreSqlDataSource extends AbstractSqlDataSource {
|
||||
|
||||
private final ConsoleLogger logger = ConsoleLoggerFactory.get(PostgreSqlDataSource.class);
|
||||
|
||||
private String host;
|
||||
private String port;
|
||||
private String username;
|
||||
|
@ -53,14 +57,14 @@ public class PostgreSqlDataSource extends AbstractSqlDataSource {
|
|||
this.setConnectionArguments();
|
||||
} catch (RuntimeException e) {
|
||||
if (e instanceof IllegalArgumentException) {
|
||||
ConsoleLogger.warning("Invalid database arguments! Please check your configuration!");
|
||||
ConsoleLogger.warning("If this error persists, please report it to the developer!");
|
||||
logger.warning("Invalid database arguments! Please check your configuration!");
|
||||
logger.warning("If this error persists, please report it to the developer!");
|
||||
}
|
||||
if (e instanceof PoolInitializationException) {
|
||||
ConsoleLogger.warning("Can't initialize database connection! Please check your configuration!");
|
||||
ConsoleLogger.warning("If this error persists, please report it to the developer!");
|
||||
logger.warning("Can't initialize database connection! Please check your configuration!");
|
||||
logger.warning("If this error persists, please report it to the developer!");
|
||||
}
|
||||
ConsoleLogger.warning("Can't use the Hikari Connection Pool! Please, report this error to the developer!");
|
||||
logger.warning("Can't use the Hikari Connection Pool! Please, report this error to the developer!");
|
||||
throw e;
|
||||
}
|
||||
|
||||
|
@ -69,8 +73,8 @@ public class PostgreSqlDataSource extends AbstractSqlDataSource {
|
|||
checkTablesAndColumns();
|
||||
} catch (SQLException e) {
|
||||
closeConnection();
|
||||
ConsoleLogger.logException("Can't initialize the PostgreSQL database:", e);
|
||||
ConsoleLogger.warning("Please check your database settings in the config.yml file!");
|
||||
logger.logException("Can't initialize the PostgreSQL database:", e);
|
||||
logger.warning("Please check your database settings in the config.yml file!");
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
@ -116,7 +120,7 @@ public class PostgreSqlDataSource extends AbstractSqlDataSource {
|
|||
|
||||
// Database URL
|
||||
ds.setDriverClassName("org.postgresql.Driver");
|
||||
ds.setJdbcUrl("jdbc:postgresql://" + this.host + ":" + this.port + "/" + this.database);
|
||||
ds.setJdbcUrl(this.getJdbcUrl(this.host, this.port, this.database));
|
||||
|
||||
// Auth
|
||||
ds.setUsername(this.username);
|
||||
|
@ -129,7 +133,7 @@ public class PostgreSqlDataSource extends AbstractSqlDataSource {
|
|||
ds.addDataSourceProperty("cachePrepStmts", "true");
|
||||
ds.addDataSourceProperty("preparedStatementCacheQueries", "275");
|
||||
|
||||
ConsoleLogger.info("Connection arguments loaded, Hikari ConnectionPool ready!");
|
||||
logger.info("Connection arguments loaded, Hikari ConnectionPool ready!");
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -138,7 +142,7 @@ public class PostgreSqlDataSource extends AbstractSqlDataSource {
|
|||
ds.close();
|
||||
}
|
||||
setConnectionArguments();
|
||||
ConsoleLogger.info("Hikari ConnectionPool arguments reloaded!");
|
||||
logger.info("Hikari ConnectionPool arguments reloaded!");
|
||||
}
|
||||
|
||||
private Connection getConnection() throws SQLException {
|
||||
|
@ -239,14 +243,22 @@ public class PostgreSqlDataSource extends AbstractSqlDataSource {
|
|||
|
||||
if (isColumnMissing(md, col.TOTP_KEY)) {
|
||||
st.executeUpdate("ALTER TABLE " + tableName
|
||||
+ " ADD COLUMN " + col.TOTP_KEY + " VARCHAR(16);");
|
||||
+ " ADD COLUMN " + col.TOTP_KEY + " VARCHAR(32);");
|
||||
} else if (SqlDataSourceUtils.getColumnSize(md, tableName, col.TOTP_KEY) != 32) {
|
||||
st.executeUpdate("ALTER TABLE " + tableName
|
||||
+ " ALTER COLUMN " + col.TOTP_KEY + " TYPE VARCHAR(32);");
|
||||
}
|
||||
|
||||
if (!col.PLAYER_UUID.isEmpty() && isColumnMissing(md, col.PLAYER_UUID)) {
|
||||
st.executeUpdate("ALTER TABLE " + tableName
|
||||
+ " ADD COLUMN " + col.PLAYER_UUID + " VARCHAR(36)");
|
||||
}
|
||||
}
|
||||
ConsoleLogger.info("PostgreSQL setup finished");
|
||||
logger.info("PostgreSQL setup finished");
|
||||
}
|
||||
|
||||
private boolean isColumnMissing(DatabaseMetaData metaData, String columnName) throws SQLException {
|
||||
try (ResultSet rs = metaData.getColumns(null, null, tableName, columnName.toLowerCase())) {
|
||||
try (ResultSet rs = metaData.getColumns(null, null, tableName, columnName.toLowerCase(Locale.ROOT))) {
|
||||
return !rs.next();
|
||||
}
|
||||
}
|
||||
|
@ -256,7 +268,7 @@ public class PostgreSqlDataSource extends AbstractSqlDataSource {
|
|||
String sql = "SELECT * FROM " + tableName + " WHERE " + col.NAME + "=?;";
|
||||
PlayerAuth auth;
|
||||
try (Connection con = getConnection(); PreparedStatement pst = con.prepareStatement(sql)) {
|
||||
pst.setString(1, user.toLowerCase());
|
||||
pst.setString(1, user.toLowerCase(Locale.ROOT));
|
||||
try (ResultSet rs = pst.executeQuery()) {
|
||||
if (rs.next()) {
|
||||
int id = rs.getInt(col.ID);
|
||||
|
@ -295,6 +307,11 @@ public class PostgreSqlDataSource extends AbstractSqlDataSource {
|
|||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
String getJdbcUrl(String host, String port, String database) {
|
||||
return "jdbc:postgresql://" + host + ":" + port + "/" + database;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<String> getRecordsToPurge(long until) {
|
||||
Set<String> list = new HashSet<>();
|
||||
|
@ -319,11 +336,11 @@ public class PostgreSqlDataSource extends AbstractSqlDataSource {
|
|||
|
||||
@Override
|
||||
public boolean removeAuth(String user) {
|
||||
user = user.toLowerCase();
|
||||
user = user.toLowerCase(Locale.ROOT);
|
||||
String sql = "DELETE FROM " + tableName + " WHERE " + col.NAME + "=?;";
|
||||
try (Connection con = getConnection(); PreparedStatement pst = con.prepareStatement(sql)) {
|
||||
sqlExtension.removeAuth(user, con);
|
||||
pst.setString(1, user.toLowerCase());
|
||||
pst.setString(1, user.toLowerCase(Locale.ROOT));
|
||||
pst.executeUpdate();
|
||||
return true;
|
||||
} catch (SQLException ex) {
|
||||
|
@ -344,7 +361,7 @@ public class PostgreSqlDataSource extends AbstractSqlDataSource {
|
|||
String sql = "DELETE FROM " + tableName + " WHERE " + col.NAME + "=?;";
|
||||
try (Connection con = getConnection(); PreparedStatement pst = con.prepareStatement(sql)) {
|
||||
for (String name : toPurge) {
|
||||
pst.setString(1, name.toLowerCase());
|
||||
pst.setString(1, name.toLowerCase(Locale.ROOT));
|
||||
pst.executeUpdate();
|
||||
}
|
||||
} catch (SQLException ex) {
|
||||
|
@ -412,7 +429,7 @@ public class PostgreSqlDataSource extends AbstractSqlDataSource {
|
|||
String sql = "UPDATE " + tableName + " SET " + col.TOTP_KEY + " = ? WHERE " + col.NAME + " = ?";
|
||||
try (Connection con = getConnection(); PreparedStatement pst = con.prepareStatement(sql)) {
|
||||
pst.setString(1, totpKey);
|
||||
pst.setString(2, user.toLowerCase());
|
||||
pst.setString(2, user.toLowerCase(Locale.ROOT));
|
||||
pst.executeUpdate();
|
||||
return true;
|
||||
} catch (SQLException e) {
|
||||
|
|
|
@ -4,6 +4,7 @@ import com.google.common.annotations.VisibleForTesting;
|
|||
import fr.xephi.authme.ConsoleLogger;
|
||||
import fr.xephi.authme.data.auth.PlayerAuth;
|
||||
import fr.xephi.authme.datasource.columnshandler.AuthMeColumnsHandler;
|
||||
import fr.xephi.authme.output.ConsoleLoggerFactory;
|
||||
import fr.xephi.authme.settings.Settings;
|
||||
import fr.xephi.authme.settings.properties.DatabaseSettings;
|
||||
|
||||
|
@ -19,6 +20,7 @@ import java.util.ArrayList;
|
|||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Set;
|
||||
|
||||
import static fr.xephi.authme.datasource.SqlDataSourceUtils.getNullableLong;
|
||||
|
@ -30,6 +32,7 @@ import static fr.xephi.authme.datasource.SqlDataSourceUtils.logSqlException;
|
|||
@SuppressWarnings({"checkstyle:AbbreviationAsWordInName"}) // Justification: Class name cannot be changed anymore
|
||||
public class SQLite extends AbstractSqlDataSource {
|
||||
|
||||
private final ConsoleLogger logger = ConsoleLoggerFactory.get(SQLite.class);
|
||||
private final Settings settings;
|
||||
private final File dataFolder;
|
||||
private final String database;
|
||||
|
@ -57,7 +60,7 @@ public class SQLite extends AbstractSqlDataSource {
|
|||
this.setup();
|
||||
this.migrateIfNeeded();
|
||||
} catch (Exception ex) {
|
||||
ConsoleLogger.logException("Error during SQLite initialization:", ex);
|
||||
logger.logException("Error during SQLite initialization:", ex);
|
||||
throw ex;
|
||||
}
|
||||
}
|
||||
|
@ -85,8 +88,8 @@ public class SQLite extends AbstractSqlDataSource {
|
|||
throw new IllegalStateException("Failed to load SQLite JDBC class", e);
|
||||
}
|
||||
|
||||
ConsoleLogger.debug("SQLite driver loaded");
|
||||
this.con = DriverManager.getConnection("jdbc:sqlite:plugins/AuthMe/" + database + ".db");
|
||||
logger.debug("SQLite driver loaded");
|
||||
this.con = DriverManager.getConnection(this.getJdbcUrl(this.dataFolder.getAbsolutePath(), "", this.database));
|
||||
this.columnsHandler = AuthMeColumnsHandler.createForSqlite(con, settings);
|
||||
}
|
||||
|
||||
|
@ -96,6 +99,7 @@ public class SQLite extends AbstractSqlDataSource {
|
|||
* @throws SQLException when an SQL error occurs while initializing the database
|
||||
*/
|
||||
@VisibleForTesting
|
||||
@SuppressWarnings("checkstyle:CyclomaticComplexity")
|
||||
protected void setup() throws SQLException {
|
||||
try (Statement st = con.createStatement()) {
|
||||
// Note: cannot add unique fields later on in SQLite, so we add it on initialization
|
||||
|
@ -180,10 +184,15 @@ public class SQLite extends AbstractSqlDataSource {
|
|||
|
||||
if (isColumnMissing(md, col.TOTP_KEY)) {
|
||||
st.executeUpdate("ALTER TABLE " + tableName
|
||||
+ " ADD COLUMN " + col.TOTP_KEY + " VARCHAR(16);");
|
||||
+ " ADD COLUMN " + col.TOTP_KEY + " VARCHAR(32);");
|
||||
}
|
||||
|
||||
if (!col.PLAYER_UUID.isEmpty() && isColumnMissing(md, col.PLAYER_UUID)) {
|
||||
st.executeUpdate("ALTER TABLE " + tableName
|
||||
+ " ADD COLUMN " + col.PLAYER_UUID + " VARCHAR(36)");
|
||||
}
|
||||
}
|
||||
ConsoleLogger.info("SQLite Setup finished");
|
||||
logger.info("SQLite Setup finished");
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -214,7 +223,7 @@ public class SQLite extends AbstractSqlDataSource {
|
|||
this.setup();
|
||||
this.migrateIfNeeded();
|
||||
} catch (SQLException ex) {
|
||||
ConsoleLogger.logException("Error while reloading SQLite:", ex);
|
||||
logger.logException("Error while reloading SQLite:", ex);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -260,7 +269,7 @@ public class SQLite extends AbstractSqlDataSource {
|
|||
String delete = "DELETE FROM " + tableName + " WHERE " + col.NAME + "=?;";
|
||||
try (PreparedStatement deletePst = con.prepareStatement(delete)) {
|
||||
for (String name : toPurge) {
|
||||
deletePst.setString(1, name.toLowerCase());
|
||||
deletePst.setString(1, name.toLowerCase(Locale.ROOT));
|
||||
deletePst.executeUpdate();
|
||||
}
|
||||
} catch (SQLException ex) {
|
||||
|
@ -272,7 +281,7 @@ public class SQLite extends AbstractSqlDataSource {
|
|||
public boolean removeAuth(String user) {
|
||||
String sql = "DELETE FROM " + tableName + " WHERE " + col.NAME + "=?;";
|
||||
try (PreparedStatement pst = con.prepareStatement(sql)) {
|
||||
pst.setString(1, user.toLowerCase());
|
||||
pst.setString(1, user.toLowerCase(Locale.ROOT));
|
||||
pst.executeUpdate();
|
||||
return true;
|
||||
} catch (SQLException ex) {
|
||||
|
@ -347,7 +356,7 @@ public class SQLite extends AbstractSqlDataSource {
|
|||
String sql = "UPDATE " + tableName + " SET " + col.TOTP_KEY + " = ? WHERE " + col.NAME + " = ?";
|
||||
try (PreparedStatement pst = con.prepareStatement(sql)) {
|
||||
pst.setString(1, totpKey);
|
||||
pst.setString(2, user.toLowerCase());
|
||||
pst.setString(2, user.toLowerCase(Locale.ROOT));
|
||||
pst.executeUpdate();
|
||||
return true;
|
||||
} catch (SQLException e) {
|
||||
|
@ -393,10 +402,15 @@ public class SQLite extends AbstractSqlDataSource {
|
|||
long currentTimestamp = System.currentTimeMillis();
|
||||
int updatedRows = st.executeUpdate(String.format("UPDATE %s SET %s = %d;",
|
||||
tableName, col.REGISTRATION_DATE, currentTimestamp));
|
||||
ConsoleLogger.info("Created column '" + col.REGISTRATION_DATE + "' and set the current timestamp, "
|
||||
logger.info("Created column '" + col.REGISTRATION_DATE + "' and set the current timestamp, "
|
||||
+ currentTimestamp + ", to all " + updatedRows + " rows");
|
||||
}
|
||||
|
||||
@Override
|
||||
String getJdbcUrl(String dataPath, String ignored, String database) {
|
||||
return "jdbc:sqlite:" + dataPath + File.separator + database + ".db";
|
||||
}
|
||||
|
||||
private static void close(Connection con) {
|
||||
if (con != null) {
|
||||
try {
|
||||
|
|
|
@ -2,6 +2,7 @@ package fr.xephi.authme.datasource;
|
|||
|
||||
import com.google.common.io.Files;
|
||||
import fr.xephi.authme.ConsoleLogger;
|
||||
import fr.xephi.authme.output.ConsoleLoggerFactory;
|
||||
import fr.xephi.authme.settings.Settings;
|
||||
import fr.xephi.authme.settings.properties.DatabaseSettings;
|
||||
import fr.xephi.authme.util.FileUtils;
|
||||
|
@ -19,6 +20,7 @@ import java.sql.Statement;
|
|||
*/
|
||||
class SqLiteMigrater {
|
||||
|
||||
private final ConsoleLogger logger = ConsoleLoggerFactory.get(SqLiteMigrater.class);
|
||||
private final File dataFolder;
|
||||
private final String databaseName;
|
||||
private final String tableName;
|
||||
|
@ -53,13 +55,13 @@ class SqLiteMigrater {
|
|||
* @param sqLite the instance to migrate
|
||||
*/
|
||||
void performMigration(SQLite sqLite) throws SQLException {
|
||||
ConsoleLogger.warning("YOUR SQLITE DATABASE NEEDS MIGRATING! DO NOT TURN OFF YOUR SERVER");
|
||||
logger.warning("YOUR SQLITE DATABASE NEEDS MIGRATING! DO NOT TURN OFF YOUR SERVER");
|
||||
|
||||
String backupName = createBackup();
|
||||
ConsoleLogger.info("Made a backup of your database at 'backups/" + backupName + "'");
|
||||
logger.info("Made a backup of your database at 'backups/" + backupName + "'");
|
||||
|
||||
recreateDatabaseWithNewDefinitions(sqLite);
|
||||
ConsoleLogger.info("SQLite database migrated successfully");
|
||||
logger.info("SQLite database migrated successfully");
|
||||
}
|
||||
|
||||
private String createBackup() {
|
||||
|
@ -104,7 +106,7 @@ class SqLiteMigrater {
|
|||
+ " CASE WHEN $email = 'your@email.com' THEN NULL ELSE $email END, $isLogged"
|
||||
+ " FROM " + tempTable + ";";
|
||||
int insertedEntries = st.executeUpdate(replaceColumnVariables(copySql));
|
||||
ConsoleLogger.info("Copied over " + insertedEntries + " from the old table to the new one");
|
||||
logger.info("Copied over " + insertedEntries + " from the old table to the new one");
|
||||
|
||||
st.execute("DROP TABLE " + tempTable + ";");
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package fr.xephi.authme.datasource;
|
||||
|
||||
import fr.xephi.authme.ConsoleLogger;
|
||||
import fr.xephi.authme.output.ConsoleLoggerFactory;
|
||||
|
||||
import java.sql.DatabaseMetaData;
|
||||
import java.sql.ResultSet;
|
||||
|
@ -11,6 +12,8 @@ import java.sql.SQLException;
|
|||
*/
|
||||
public final class SqlDataSourceUtils {
|
||||
|
||||
private static final ConsoleLogger logger = ConsoleLoggerFactory.get(SqlDataSourceUtils.class);
|
||||
|
||||
private SqlDataSourceUtils() {
|
||||
}
|
||||
|
||||
|
@ -20,7 +23,7 @@ public final class SqlDataSourceUtils {
|
|||
* @param e the exception to log
|
||||
*/
|
||||
public static void logSqlException(SQLException e) {
|
||||
ConsoleLogger.logException("Error during SQL operation:", e);
|
||||
logger.logException("Error during SQL operation:", e);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -58,7 +61,7 @@ public final class SqlDataSourceUtils {
|
|||
if (nullableCode == DatabaseMetaData.columnNoNulls) {
|
||||
return true;
|
||||
} else if (nullableCode == DatabaseMetaData.columnNullableUnknown) {
|
||||
ConsoleLogger.warning("Unknown nullable status for column '" + columnName + "'");
|
||||
logger.warning("Unknown nullable status for column '" + columnName + "'");
|
||||
}
|
||||
}
|
||||
return false;
|
||||
|
@ -83,4 +86,24 @@ public final class SqlDataSourceUtils {
|
|||
return rs.getObject("COLUMN_DEF");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the size of a column (as per its SQL definition).
|
||||
*
|
||||
* @param metaData the database meta data
|
||||
* @param tableName the name of the table in which the column is
|
||||
* @param columnName the name of the column to check
|
||||
* @return the size of the column
|
||||
* @throws SQLException :)
|
||||
*/
|
||||
public static int getColumnSize(DatabaseMetaData metaData, String tableName,
|
||||
String columnName) throws SQLException {
|
||||
try (ResultSet rs = metaData.getColumns(null, null, tableName, columnName)) {
|
||||
if (!rs.next()) {
|
||||
throw new IllegalStateException("Did not find meta data for column '"
|
||||
+ columnName + "' while checking its size");
|
||||
}
|
||||
return rs.getInt("COLUMN_SIZE");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,6 +3,8 @@ package fr.xephi.authme.datasource.columnshandler;
|
|||
import fr.xephi.authme.data.auth.PlayerAuth;
|
||||
import fr.xephi.authme.settings.properties.DatabaseSettings;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
import static fr.xephi.authme.datasource.columnshandler.AuthMeColumnsFactory.ColumnOptions.DEFAULT_FOR_NULL;
|
||||
import static fr.xephi.authme.datasource.columnshandler.AuthMeColumnsFactory.ColumnOptions.OPTIONAL;
|
||||
import static fr.xephi.authme.datasource.columnshandler.AuthMeColumnsFactory.createDouble;
|
||||
|
@ -46,6 +48,11 @@ public final class AuthMeColumns {
|
|||
public static final PlayerAuthColumn<Long> REGISTRATION_DATE = createLong(
|
||||
DatabaseSettings.MYSQL_COL_REGISTER_DATE, PlayerAuth::getRegistrationDate);
|
||||
|
||||
public static final PlayerAuthColumn<String> UUID = createString(
|
||||
DatabaseSettings.MYSQL_COL_PLAYER_UUID,
|
||||
auth -> ( auth.getUuid() == null ? null : auth.getUuid().toString()),
|
||||
OPTIONAL);
|
||||
|
||||
// --------
|
||||
// Location columns
|
||||
// --------
|
||||
|
@ -76,7 +83,6 @@ public final class AuthMeColumns {
|
|||
public static final DataSourceColumn<Integer> HAS_SESSION = createInteger(
|
||||
DatabaseSettings.MYSQL_COL_HASSESSION);
|
||||
|
||||
|
||||
private AuthMeColumns() {
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,6 +14,7 @@ import fr.xephi.authme.settings.properties.DatabaseSettings;
|
|||
import java.sql.Connection;
|
||||
import java.sql.SQLException;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
import static ch.jalu.datasourcecolumns.sqlimplementation.SqlColumnsHandlerConfig.forConnectionPool;
|
||||
import static ch.jalu.datasourcecolumns.sqlimplementation.SqlColumnsHandlerConfig.forSingleConnection;
|
||||
|
@ -78,7 +79,7 @@ public final class AuthMeColumnsHandler {
|
|||
*/
|
||||
public <T> boolean update(String name, DataSourceColumn<T> column, T value) {
|
||||
try {
|
||||
return internalHandler.update(name, column, value);
|
||||
return internalHandler.update(name.toLowerCase(Locale.ROOT), column, value);
|
||||
} catch (SQLException e) {
|
||||
logSqlException(e);
|
||||
return false;
|
||||
|
@ -110,7 +111,7 @@ public final class AuthMeColumnsHandler {
|
|||
*/
|
||||
public boolean update(String name, UpdateValues<ColumnContext> updateValues) {
|
||||
try {
|
||||
return internalHandler.update(name.toLowerCase(), updateValues);
|
||||
return internalHandler.update(name.toLowerCase(Locale.ROOT), updateValues);
|
||||
} catch (SQLException e) {
|
||||
logSqlException(e);
|
||||
return false;
|
||||
|
@ -145,7 +146,7 @@ public final class AuthMeColumnsHandler {
|
|||
* @throws SQLException .
|
||||
*/
|
||||
public <T> DataSourceValue<T> retrieve(String name, DataSourceColumn<T> column) throws SQLException {
|
||||
return internalHandler.retrieve(name.toLowerCase(), column);
|
||||
return internalHandler.retrieve(name.toLowerCase(Locale.ROOT), column);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -157,7 +158,7 @@ public final class AuthMeColumnsHandler {
|
|||
* @throws SQLException .
|
||||
*/
|
||||
public DataSourceValues retrieve(String name, DataSourceColumn<?>... columns) throws SQLException {
|
||||
return internalHandler.retrieve(name.toLowerCase(), columns);
|
||||
return internalHandler.retrieve(name.toLowerCase(Locale.ROOT), columns);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -2,8 +2,8 @@ package fr.xephi.authme.datasource.columnshandler;
|
|||
|
||||
import fr.xephi.authme.settings.Settings;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
/**
|
||||
* Context for resolving the properties of {@link AuthMeColumns} entries.
|
||||
|
@ -11,7 +11,7 @@ import java.util.Map;
|
|||
public class ColumnContext {
|
||||
|
||||
private final Settings settings;
|
||||
private final Map<DataSourceColumn<?>, String> columnNames = new HashMap<>();
|
||||
private final Map<DataSourceColumn<?>, String> columnNames = new ConcurrentHashMap<>();
|
||||
private final boolean hasDefaultSupport;
|
||||
|
||||
/**
|
||||
|
|
|
@ -4,6 +4,7 @@ import fr.xephi.authme.ConsoleLogger;
|
|||
import fr.xephi.authme.data.auth.PlayerAuth;
|
||||
import fr.xephi.authme.datasource.DataSource;
|
||||
import fr.xephi.authme.datasource.DataSourceType;
|
||||
import fr.xephi.authme.output.ConsoleLoggerFactory;
|
||||
import org.bukkit.command.CommandSender;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
@ -18,8 +19,10 @@ import static fr.xephi.authme.util.Utils.logAndSendMessage;
|
|||
*/
|
||||
public abstract class AbstractDataSourceConverter<S extends DataSource> implements Converter {
|
||||
|
||||
private DataSource destination;
|
||||
private DataSourceType destinationType;
|
||||
private final ConsoleLogger logger = ConsoleLoggerFactory.get(MySqlToSqlite.class);
|
||||
|
||||
private final DataSource destination;
|
||||
private final DataSourceType destinationType;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
|
@ -51,7 +54,7 @@ public abstract class AbstractDataSourceConverter<S extends DataSource> implemen
|
|||
source = getSource();
|
||||
} catch (Exception e) {
|
||||
logAndSendMessage(sender, "The data source to convert from could not be initialized");
|
||||
ConsoleLogger.logException("Could not initialize source:", e);
|
||||
logger.logException("Could not initialize source:", e);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -60,7 +63,6 @@ public abstract class AbstractDataSourceConverter<S extends DataSource> implemen
|
|||
if (destination.isAuthAvailable(auth.getNickname())) {
|
||||
skippedPlayers.add(auth.getNickname());
|
||||
} else {
|
||||
adaptPlayerAuth(auth);
|
||||
destination.saveAuth(auth);
|
||||
destination.updateSession(auth);
|
||||
destination.updateQuitLoc(auth);
|
||||
|
@ -75,15 +77,6 @@ public abstract class AbstractDataSourceConverter<S extends DataSource> implemen
|
|||
+ " to " + destinationType);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adapts the PlayerAuth from the source before it is saved in the destination.
|
||||
*
|
||||
* @param auth the auth from the source
|
||||
*/
|
||||
protected void adaptPlayerAuth(PlayerAuth auth) {
|
||||
// noop
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the data source to convert from
|
||||
* @throws Exception during initialization of source
|
||||
|
|
|
@ -4,6 +4,7 @@ import fr.xephi.authme.ConsoleLogger;
|
|||
import fr.xephi.authme.data.auth.PlayerAuth;
|
||||
import fr.xephi.authme.datasource.DataSource;
|
||||
import fr.xephi.authme.initialization.DataFolder;
|
||||
import fr.xephi.authme.output.ConsoleLoggerFactory;
|
||||
import fr.xephi.authme.settings.Settings;
|
||||
import fr.xephi.authme.settings.properties.ConverterSettings;
|
||||
import org.bukkit.command.CommandSender;
|
||||
|
@ -13,12 +14,15 @@ import java.io.BufferedReader;
|
|||
import java.io.File;
|
||||
import java.io.FileReader;
|
||||
import java.io.IOException;
|
||||
import java.util.Locale;
|
||||
|
||||
/**
|
||||
* Converter for CrazyLogin to AuthMe.
|
||||
*/
|
||||
public class CrazyLoginConverter implements Converter {
|
||||
|
||||
private final ConsoleLogger logger = ConsoleLoggerFactory.get(CrazyLoginConverter.class);
|
||||
|
||||
private final DataSource database;
|
||||
private final Settings settings;
|
||||
private final File dataFolder;
|
||||
|
@ -46,10 +50,10 @@ public class CrazyLoginConverter implements Converter {
|
|||
migrateAccount(line);
|
||||
}
|
||||
}
|
||||
ConsoleLogger.info("CrazyLogin database has been imported correctly");
|
||||
logger.info("CrazyLogin database has been imported correctly");
|
||||
} catch (IOException ex) {
|
||||
ConsoleLogger.warning("Can't open the crazylogin database file! Does it exist?");
|
||||
ConsoleLogger.logException("Encountered", ex);
|
||||
logger.warning("Can't open the crazylogin database file! Does it exist?");
|
||||
logger.logException("Encountered", ex);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -67,7 +71,7 @@ public class CrazyLoginConverter implements Converter {
|
|||
String password = args[1];
|
||||
if (password != null) {
|
||||
PlayerAuth auth = PlayerAuth.builder()
|
||||
.name(playerName.toLowerCase())
|
||||
.name(playerName.toLowerCase(Locale.ROOT))
|
||||
.realName(playerName)
|
||||
.password(password, null)
|
||||
.build();
|
||||
|
|
|
@ -1,36 +0,0 @@
|
|||
package fr.xephi.authme.datasource.converter;
|
||||
|
||||
import fr.xephi.authme.data.auth.PlayerAuth;
|
||||
import fr.xephi.authme.datasource.DataSource;
|
||||
import fr.xephi.authme.datasource.FlatFile;
|
||||
|
||||
/**
|
||||
* Mandatory migration from the deprecated flat file datasource to SQLite.
|
||||
*/
|
||||
public class ForceFlatToSqlite extends AbstractDataSourceConverter<FlatFile> {
|
||||
|
||||
private final FlatFile source;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param source The datasource to convert (flatfile)
|
||||
* @param destination The datasource to copy the data to (sqlite)
|
||||
*/
|
||||
public ForceFlatToSqlite(FlatFile source, DataSource destination) {
|
||||
super(destination, destination.getType());
|
||||
this.source = source;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FlatFile getSource() {
|
||||
return source;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void adaptPlayerAuth(PlayerAuth auth) {
|
||||
// Issue #1120: FlatFile returns PlayerAuth objects with realname = lower-case name all the time.
|
||||
// We don't want to take this over into the new data source.
|
||||
auth.setRealName("Player");
|
||||
}
|
||||
}
|
|
@ -5,8 +5,10 @@ import fr.xephi.authme.ConsoleLogger;
|
|||
import fr.xephi.authme.data.auth.PlayerAuth;
|
||||
import fr.xephi.authme.datasource.DataSource;
|
||||
import fr.xephi.authme.initialization.DataFolder;
|
||||
import fr.xephi.authme.output.ConsoleLoggerFactory;
|
||||
import fr.xephi.authme.settings.Settings;
|
||||
import fr.xephi.authme.settings.properties.ConverterSettings;
|
||||
import fr.xephi.authme.util.UuidUtils;
|
||||
import org.bukkit.command.CommandSender;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
@ -21,6 +23,7 @@ import java.util.ArrayList;
|
|||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
|
||||
import static fr.xephi.authme.util.Utils.logAndSendMessage;
|
||||
|
||||
|
@ -29,6 +32,7 @@ import static fr.xephi.authme.util.Utils.logAndSendMessage;
|
|||
*/
|
||||
public class LoginSecurityConverter implements Converter {
|
||||
|
||||
private final ConsoleLogger logger = ConsoleLoggerFactory.get(LoginSecurityConverter.class);
|
||||
private final File dataFolder;
|
||||
private final DataSource dataSource;
|
||||
|
||||
|
@ -55,10 +59,12 @@ public class LoginSecurityConverter implements Converter {
|
|||
try (Connection connection = createConnectionOrInformSender(sender)) {
|
||||
if (connection != null) {
|
||||
performConversion(sender, connection);
|
||||
logger.info("LoginSecurity conversion completed! Please remember to set \"legacyHashes: ['BCRYPT']\" "
|
||||
+ "in your configuration file!");
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
sender.sendMessage("Failed to convert from SQLite. Please see the log for more info");
|
||||
ConsoleLogger.logException("Could not fetch or migrate data:", e);
|
||||
logger.logException("Could not fetch or migrate data:", e);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -119,6 +125,7 @@ public class LoginSecurityConverter implements Converter {
|
|||
.map(Timestamp::getTime).orElse(null);
|
||||
long regDate = Optional.ofNullable(resultSet.getDate("registration_date"))
|
||||
.map(Date::getTime).orElse(System.currentTimeMillis());
|
||||
UUID uuid = UuidUtils.parseUuidSafely(resultSet.getString("unique_user_id"));
|
||||
return PlayerAuth.builder()
|
||||
.name(name)
|
||||
.realName(name)
|
||||
|
@ -132,6 +139,7 @@ public class LoginSecurityConverter implements Converter {
|
|||
.locWorld(resultSet.getString("world"))
|
||||
.locYaw(resultSet.getFloat("yaw"))
|
||||
.locPitch(resultSet.getFloat("pitch"))
|
||||
.uuid(uuid)
|
||||
.build();
|
||||
}
|
||||
|
||||
|
@ -185,7 +193,7 @@ public class LoginSecurityConverter implements Converter {
|
|||
return DriverManager.getConnection(
|
||||
"jdbc:sqlite:" + path, "trump", "donald");
|
||||
} catch (SQLException e) {
|
||||
ConsoleLogger.logException("Could not connect to SQLite database", e);
|
||||
logger.logException("Could not connect to SQLite database", e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
@ -195,7 +203,7 @@ public class LoginSecurityConverter implements Converter {
|
|||
return DriverManager.getConnection(
|
||||
"jdbc:mysql://" + mySqlHost + "/" + mySqlDatabase, mySqlUser, mySqlPassword);
|
||||
} catch (SQLException e) {
|
||||
ConsoleLogger.logException("Could not connect to SQLite database", e);
|
||||
logger.logException("Could not connect to SQLite database", e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@ import fr.xephi.authme.ConsoleLogger;
|
|||
import fr.xephi.authme.data.auth.PlayerAuth;
|
||||
import fr.xephi.authme.datasource.DataSource;
|
||||
import fr.xephi.authme.initialization.DataFolder;
|
||||
import fr.xephi.authme.output.ConsoleLoggerFactory;
|
||||
import fr.xephi.authme.security.PasswordSecurity;
|
||||
import fr.xephi.authme.security.crypts.HashedPassword;
|
||||
import fr.xephi.authme.settings.Settings;
|
||||
|
@ -25,6 +26,7 @@ import java.util.Map.Entry;
|
|||
*/
|
||||
public class RakamakConverter implements Converter {
|
||||
|
||||
private final ConsoleLogger logger = ConsoleLoggerFactory.get(RakamakConverter.class);
|
||||
private final DataSource database;
|
||||
private final Settings settings;
|
||||
private final File pluginFolder;
|
||||
|
@ -88,7 +90,7 @@ public class RakamakConverter implements Converter {
|
|||
}
|
||||
Utils.logAndSendMessage(sender, "Rakamak database has been imported successfully");
|
||||
} catch (IOException ex) {
|
||||
ConsoleLogger.logException("Can't open the rakamak database file! Does it exist?", ex);
|
||||
logger.logException("Can't open the rakamak database file! Does it exist?", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@ import fr.xephi.authme.AuthMe;
|
|||
import fr.xephi.authme.ConsoleLogger;
|
||||
import fr.xephi.authme.data.auth.PlayerAuth;
|
||||
import fr.xephi.authme.datasource.DataSource;
|
||||
import fr.xephi.authme.output.ConsoleLoggerFactory;
|
||||
import org.bukkit.OfflinePlayer;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.configuration.file.FileConfiguration;
|
||||
|
@ -11,6 +12,7 @@ import org.bukkit.configuration.file.YamlConfiguration;
|
|||
|
||||
import javax.inject.Inject;
|
||||
import java.io.File;
|
||||
import java.util.Locale;
|
||||
|
||||
import static fr.xephi.authme.util.FileUtils.makePath;
|
||||
|
||||
|
@ -18,6 +20,9 @@ public class RoyalAuthConverter implements Converter {
|
|||
|
||||
private static final String LAST_LOGIN_PATH = "timestamps.quit";
|
||||
private static final String PASSWORD_PATH = "login.password";
|
||||
|
||||
private final ConsoleLogger logger = ConsoleLoggerFactory.get(RoyalAuthConverter.class);
|
||||
|
||||
private final AuthMe plugin;
|
||||
private final DataSource dataSource;
|
||||
|
||||
|
@ -31,7 +36,7 @@ public class RoyalAuthConverter implements Converter {
|
|||
public void execute(CommandSender sender) {
|
||||
for (OfflinePlayer player : plugin.getServer().getOfflinePlayers()) {
|
||||
try {
|
||||
String name = player.getName().toLowerCase();
|
||||
String name = player.getName().toLowerCase(Locale.ROOT);
|
||||
File file = new File(makePath(".", "plugins", "RoyalAuth", "userdata", name + ".yml"));
|
||||
|
||||
if (dataSource.isAuthAvailable(name) || !file.exists()) {
|
||||
|
@ -48,7 +53,7 @@ public class RoyalAuthConverter implements Converter {
|
|||
dataSource.saveAuth(auth);
|
||||
dataSource.updateSession(auth);
|
||||
} catch (Exception e) {
|
||||
ConsoleLogger.logException("Error while trying to import " + player.getName() + " RoyalAuth data", e);
|
||||
logger.logException("Error while trying to import " + player.getName() + " RoyalAuth data", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@ import fr.xephi.authme.ConsoleLogger;
|
|||
import fr.xephi.authme.data.auth.PlayerAuth;
|
||||
import fr.xephi.authme.datasource.DataSource;
|
||||
import fr.xephi.authme.initialization.DataFolder;
|
||||
import fr.xephi.authme.output.ConsoleLoggerFactory;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.OfflinePlayer;
|
||||
import org.bukkit.command.CommandSender;
|
||||
|
@ -11,6 +12,7 @@ import org.bukkit.command.CommandSender;
|
|||
import javax.inject.Inject;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.Locale;
|
||||
import java.util.Scanner;
|
||||
import java.util.UUID;
|
||||
|
||||
|
@ -18,6 +20,7 @@ import static fr.xephi.authme.util.FileUtils.makePath;
|
|||
|
||||
public class VAuthConverter implements Converter {
|
||||
|
||||
private final ConsoleLogger logger = ConsoleLoggerFactory.get(VAuthConverter.class);
|
||||
private final DataSource dataSource;
|
||||
private final File vAuthPasswordsFile;
|
||||
|
||||
|
@ -46,19 +49,19 @@ public class VAuthConverter implements Converter {
|
|||
continue;
|
||||
}
|
||||
auth = PlayerAuth.builder()
|
||||
.name(pname.toLowerCase())
|
||||
.name(pname.toLowerCase(Locale.ROOT))
|
||||
.realName(pname)
|
||||
.password(password, null).build();
|
||||
} else {
|
||||
auth = PlayerAuth.builder()
|
||||
.name(name.toLowerCase())
|
||||
.name(name.toLowerCase(Locale.ROOT))
|
||||
.realName(name)
|
||||
.password(password, null).build();
|
||||
}
|
||||
dataSource.saveAuth(auth);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
ConsoleLogger.logException("Error while trying to import some vAuth data", e);
|
||||
logger.logException("Error while trying to import some vAuth data", e);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -18,6 +18,7 @@ import java.sql.ResultSet;
|
|||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
import static fr.xephi.authme.util.FileUtils.makePath;
|
||||
|
||||
|
@ -66,7 +67,7 @@ public class XAuthConverter implements Converter {
|
|||
String psw = getPassword(id);
|
||||
if (psw != null && !psw.isEmpty() && pl != null) {
|
||||
PlayerAuth auth = PlayerAuth.builder()
|
||||
.name(pl.toLowerCase())
|
||||
.name(pl.toLowerCase(Locale.ROOT))
|
||||
.realName(pl)
|
||||
.password(psw, null).build();
|
||||
database.saveAuth(auth);
|
||||
|
@ -89,7 +90,7 @@ public class XAuthConverter implements Converter {
|
|||
if (!rs.next()) {
|
||||
return null;
|
||||
}
|
||||
realPass = rs.getString("playername").toLowerCase();
|
||||
realPass = rs.getString("playername").toLowerCase(Locale.ROOT);
|
||||
} catch (SQLException e) {
|
||||
xAuthLog.severe("Failed to retrieve name for account: " + id, e);
|
||||
return null;
|
||||
|
|
|
@ -30,73 +30,55 @@ class WordpressExtension extends MySqlExtension {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves the required data to Wordpress tables.
|
||||
*
|
||||
* @param auth the player data
|
||||
* @param id the player id
|
||||
* @param con the sql connection
|
||||
* @throws SQLException .
|
||||
*/
|
||||
private void saveSpecifics(PlayerAuth auth, int id, Connection con) throws SQLException {
|
||||
String sql = "INSERT INTO " + wordpressPrefix + "usermeta (user_id, meta_key, meta_value) VALUES (?,?,?)";
|
||||
try (PreparedStatement pst = con.prepareStatement(sql)) {
|
||||
// First Name
|
||||
pst.setInt(1, id);
|
||||
pst.setString(2, "first_name");
|
||||
pst.setString(3, "");
|
||||
pst.addBatch();
|
||||
// Last Name
|
||||
pst.setInt(1, id);
|
||||
pst.setString(2, "last_name");
|
||||
pst.setString(3, "");
|
||||
pst.addBatch();
|
||||
// Nick Name
|
||||
pst.setInt(1, id);
|
||||
pst.setString(2, "nickname");
|
||||
pst.setString(3, auth.getNickname());
|
||||
pst.addBatch();
|
||||
// Description
|
||||
pst.setInt(1, id);
|
||||
pst.setString(2, "description");
|
||||
pst.setString(3, "");
|
||||
pst.addBatch();
|
||||
// Rich_Editing
|
||||
pst.setInt(1, id);
|
||||
pst.setString(2, "rich_editing");
|
||||
pst.setString(3, "true");
|
||||
pst.addBatch();
|
||||
// Comments_Shortcuts
|
||||
pst.setInt(1, id);
|
||||
pst.setString(2, "comment_shortcuts");
|
||||
pst.setString(3, "false");
|
||||
pst.addBatch();
|
||||
// admin_color
|
||||
pst.setInt(1, id);
|
||||
pst.setString(2, "admin_color");
|
||||
pst.setString(3, "fresh");
|
||||
pst.addBatch();
|
||||
// use_ssl
|
||||
pst.setInt(1, id);
|
||||
pst.setString(2, "use_ssl");
|
||||
pst.setString(3, "0");
|
||||
pst.addBatch();
|
||||
// show_admin_bar_front
|
||||
pst.setInt(1, id);
|
||||
pst.setString(2, "show_admin_bar_front");
|
||||
pst.setString(3, "true");
|
||||
pst.addBatch();
|
||||
// wp_capabilities
|
||||
pst.setInt(1, id);
|
||||
pst.setString(2, wordpressPrefix + "capabilities");
|
||||
pst.setString(3, "a:1:{s:10:\"subscriber\";b:1;}");
|
||||
pst.addBatch();
|
||||
// wp_user_level
|
||||
pst.setInt(1, id);
|
||||
pst.setString(2, wordpressPrefix + "user_level");
|
||||
pst.setString(3, "0");
|
||||
pst.addBatch();
|
||||
// default_password_nag
|
||||
pst.setInt(1, id);
|
||||
pst.setString(2, "default_password_nag");
|
||||
pst.setString(3, "");
|
||||
pst.addBatch();
|
||||
|
||||
new UserMetaBatchAdder(pst, id)
|
||||
.addMetaRow("first_name", "")
|
||||
.addMetaRow("last_name", "")
|
||||
.addMetaRow("nickname", auth.getNickname())
|
||||
.addMetaRow("description", "")
|
||||
.addMetaRow("rich_editing", "true")
|
||||
.addMetaRow("comment_shortcuts", "false")
|
||||
.addMetaRow("admin_color", "fresh")
|
||||
.addMetaRow("use_ssl", "0")
|
||||
.addMetaRow("show_admin_bar_front", "true")
|
||||
.addMetaRow(wordpressPrefix + "capabilities", "a:1:{s:10:\"subscriber\";b:1;}")
|
||||
.addMetaRow(wordpressPrefix + "user_level", "0")
|
||||
.addMetaRow("default_password_nag", "");
|
||||
|
||||
// Execute queries
|
||||
pst.executeBatch();
|
||||
pst.clearBatch();
|
||||
}
|
||||
}
|
||||
|
||||
/** Helper to add batch entries to the wrapped prepared statement. */
|
||||
private static final class UserMetaBatchAdder {
|
||||
|
||||
private final PreparedStatement pst;
|
||||
private final int userId;
|
||||
|
||||
UserMetaBatchAdder(PreparedStatement pst, int userId) {
|
||||
this.pst = pst;
|
||||
this.userId = userId;
|
||||
}
|
||||
|
||||
UserMetaBatchAdder addMetaRow(String metaKey, String metaValue) throws SQLException {
|
||||
pst.setInt(1, userId);
|
||||
pst.setString(2, metaKey);
|
||||
pst.setString(3, metaValue);
|
||||
pst.addBatch();
|
||||
return this;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,12 +5,12 @@ import fr.xephi.authme.data.auth.PlayerCache;
|
|||
import fr.xephi.authme.datasource.CacheDataSource;
|
||||
import fr.xephi.authme.datasource.DataSource;
|
||||
import fr.xephi.authme.datasource.DataSourceType;
|
||||
import fr.xephi.authme.datasource.FlatFile;
|
||||
import fr.xephi.authme.datasource.MariaDB;
|
||||
import fr.xephi.authme.datasource.MySQL;
|
||||
import fr.xephi.authme.datasource.PostgreSqlDataSource;
|
||||
import fr.xephi.authme.datasource.SQLite;
|
||||
import fr.xephi.authme.datasource.converter.ForceFlatToSqlite;
|
||||
import fr.xephi.authme.datasource.mysqlextensions.MySqlExtensionsFactory;
|
||||
import fr.xephi.authme.output.ConsoleLoggerFactory;
|
||||
import fr.xephi.authme.service.BukkitService;
|
||||
import fr.xephi.authme.settings.Settings;
|
||||
import fr.xephi.authme.settings.properties.DatabaseSettings;
|
||||
|
@ -18,7 +18,6 @@ import fr.xephi.authme.settings.properties.DatabaseSettings;
|
|||
import javax.inject.Inject;
|
||||
import javax.inject.Provider;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.sql.SQLException;
|
||||
|
||||
/**
|
||||
|
@ -26,9 +25,10 @@ import java.sql.SQLException;
|
|||
*/
|
||||
public class DataSourceProvider implements Provider<DataSource> {
|
||||
|
||||
private static final String FLATFILE_FILENAME = "auths.db";
|
||||
private static final int SQLITE_MAX_SIZE = 4000;
|
||||
|
||||
private final ConsoleLogger logger = ConsoleLoggerFactory.get(DataSourceProvider.class);
|
||||
|
||||
@Inject
|
||||
@DataFolder
|
||||
private File dataFolder;
|
||||
|
@ -49,7 +49,7 @@ public class DataSourceProvider implements Provider<DataSource> {
|
|||
try {
|
||||
return createDataSource();
|
||||
} catch (Exception e) {
|
||||
ConsoleLogger.logException("Could not create data source:", e);
|
||||
logger.logException("Could not create data source:", e);
|
||||
throw new IllegalStateException("Error during initialization of data source", e);
|
||||
}
|
||||
}
|
||||
|
@ -57,21 +57,19 @@ public class DataSourceProvider implements Provider<DataSource> {
|
|||
/**
|
||||
* Sets up the data source.
|
||||
*
|
||||
* @return the constructed datasource
|
||||
* @throws SQLException when initialization of a SQL datasource failed
|
||||
* @throws IOException if flat file cannot be read
|
||||
* @return the constructed data source
|
||||
* @throws SQLException when initialization of a SQL data source failed
|
||||
*/
|
||||
private DataSource createDataSource() throws SQLException, IOException {
|
||||
private DataSource createDataSource() throws SQLException {
|
||||
DataSourceType dataSourceType = settings.getProperty(DatabaseSettings.BACKEND);
|
||||
DataSource dataSource;
|
||||
switch (dataSourceType) {
|
||||
case FILE:
|
||||
File source = new File(dataFolder, FLATFILE_FILENAME);
|
||||
dataSource = new FlatFile(source);
|
||||
break;
|
||||
case MYSQL:
|
||||
dataSource = new MySQL(settings, mySqlExtensionsFactory);
|
||||
break;
|
||||
case MARIADB:
|
||||
dataSource = new MariaDB(settings, mySqlExtensionsFactory);
|
||||
break;
|
||||
case POSTGRESQL:
|
||||
dataSource = new PostgreSqlDataSource(settings, mySqlExtensionsFactory);
|
||||
break;
|
||||
|
@ -82,8 +80,6 @@ public class DataSourceProvider implements Provider<DataSource> {
|
|||
throw new UnsupportedOperationException("Unknown data source type '" + dataSourceType + "'");
|
||||
}
|
||||
|
||||
dataSource = convertFlatfileToSqlite(dataSource);
|
||||
|
||||
if (settings.getProperty(DatabaseSettings.USE_CACHING)) {
|
||||
dataSource = new CacheDataSource(dataSource, playerCache);
|
||||
}
|
||||
|
@ -97,36 +93,9 @@ public class DataSourceProvider implements Provider<DataSource> {
|
|||
bukkitService.runTaskAsynchronously(() -> {
|
||||
int accounts = dataSource.getAccountsRegistered();
|
||||
if (accounts >= SQLITE_MAX_SIZE) {
|
||||
ConsoleLogger.warning("YOU'RE USING THE SQLITE DATABASE WITH "
|
||||
logger.warning("YOU'RE USING THE SQLITE DATABASE WITH "
|
||||
+ accounts + "+ ACCOUNTS; FOR BETTER PERFORMANCE, PLEASE UPGRADE TO MYSQL!!");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts the data source from the deprecated FLATFILE type to SQLITE.
|
||||
*
|
||||
* @param dataSource the data source to convert if necessary
|
||||
* @return the data source to use: the converted datasource (SQLite),
|
||||
* or the same data source if no conversion was performed
|
||||
*/
|
||||
private DataSource convertFlatfileToSqlite(DataSource dataSource) {
|
||||
if (DataSourceType.FILE == settings.getProperty(DatabaseSettings.BACKEND)) {
|
||||
ConsoleLogger.warning("FlatFile backend has been detected and is now deprecated; it will be changed "
|
||||
+ "to SQLite... Connection will be impossible until conversion is done!");
|
||||
FlatFile flatFile = (FlatFile) dataSource;
|
||||
try {
|
||||
SQLite sqlite = new SQLite(settings, dataFolder);
|
||||
ForceFlatToSqlite converter = new ForceFlatToSqlite(flatFile, sqlite);
|
||||
converter.execute(null);
|
||||
settings.setProperty(DatabaseSettings.BACKEND, DataSourceType.SQLITE);
|
||||
settings.save();
|
||||
return sqlite;
|
||||
} catch (Exception e) {
|
||||
ConsoleLogger.logException("Error during conversion from Flatfile to SQLite", e);
|
||||
throw new IllegalStateException(e);
|
||||
}
|
||||
}
|
||||
return dataSource;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,8 +6,6 @@ import fr.xephi.authme.data.limbo.LimboService;
|
|||
import fr.xephi.authme.datasource.DataSource;
|
||||
import fr.xephi.authme.service.BukkitService;
|
||||
import fr.xephi.authme.service.ValidationService;
|
||||
import fr.xephi.authme.service.bungeecord.BungeeSender;
|
||||
import fr.xephi.authme.service.bungeecord.MessageType;
|
||||
import fr.xephi.authme.settings.Settings;
|
||||
import fr.xephi.authme.settings.SpawnLoader;
|
||||
import fr.xephi.authme.settings.properties.RestrictionSettings;
|
||||
|
@ -16,6 +14,7 @@ import org.bukkit.Location;
|
|||
import org.bukkit.entity.Player;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import java.util.Locale;
|
||||
|
||||
/**
|
||||
* Saves all players' data when the plugin shuts down.
|
||||
|
@ -36,8 +35,6 @@ public class OnShutdownPlayerSaver {
|
|||
private PlayerCache playerCache;
|
||||
@Inject
|
||||
private LimboService limboService;
|
||||
@Inject
|
||||
private BungeeSender bungeeSender;
|
||||
|
||||
OnShutdownPlayerSaver() {
|
||||
}
|
||||
|
@ -52,7 +49,7 @@ public class OnShutdownPlayerSaver {
|
|||
}
|
||||
|
||||
private void savePlayer(Player player) {
|
||||
final String name = player.getName().toLowerCase();
|
||||
String name = player.getName().toLowerCase(Locale.ROOT);
|
||||
if (PlayerUtils.isNpc(player) || validationService.isUnrestricted(name)) {
|
||||
return;
|
||||
}
|
||||
|
@ -67,12 +64,12 @@ public class OnShutdownPlayerSaver {
|
|||
private void saveLoggedinPlayer(Player player) {
|
||||
if (settings.getProperty(RestrictionSettings.SAVE_QUIT_LOCATION)) {
|
||||
Location loc = spawnLoader.getPlayerLocationOrSpawn(player);
|
||||
final PlayerAuth auth = PlayerAuth.builder()
|
||||
.name(player.getName().toLowerCase())
|
||||
PlayerAuth auth = PlayerAuth.builder()
|
||||
.name(player.getName().toLowerCase(Locale.ROOT))
|
||||
.realName(player.getName())
|
||||
.location(loc).build();
|
||||
dataSource.updateQuitLoc(auth);
|
||||
bungeeSender.sendAuthMeBungeecordMessage(MessageType.REFRESH_QUITLOC, player.getName());
|
||||
// TODO: send an update when a messaging service will be implemented (QUITLOC)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@ package fr.xephi.authme.initialization;
|
|||
import fr.xephi.authme.AuthMe;
|
||||
import fr.xephi.authme.ConsoleLogger;
|
||||
import fr.xephi.authme.datasource.DataSource;
|
||||
import fr.xephi.authme.output.ConsoleLoggerFactory;
|
||||
import fr.xephi.authme.message.MessageKey;
|
||||
import fr.xephi.authme.message.Messages;
|
||||
import fr.xephi.authme.output.ConsoleFilter;
|
||||
|
@ -14,10 +15,13 @@ import fr.xephi.authme.settings.properties.EmailSettings;
|
|||
import fr.xephi.authme.settings.properties.PluginSettings;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.bstats.bukkit.Metrics;
|
||||
import org.bstats.charts.SimplePie;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.scheduler.BukkitRunnable;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import java.util.List;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import static fr.xephi.authme.service.BukkitService.TICKS_PER_MINUTE;
|
||||
|
@ -28,6 +32,8 @@ import static fr.xephi.authme.settings.properties.EmailSettings.RECALL_PLAYERS;
|
|||
*/
|
||||
public class OnStartupTasks {
|
||||
|
||||
private static ConsoleLogger consoleLogger = ConsoleLoggerFactory.get(OnStartupTasks.class);
|
||||
|
||||
@Inject
|
||||
private DataSource dataSource;
|
||||
@Inject
|
||||
|
@ -47,28 +53,27 @@ public class OnStartupTasks {
|
|||
* @param settings the settings
|
||||
*/
|
||||
public static void sendMetrics(AuthMe plugin, Settings settings) {
|
||||
final Metrics metrics = new Metrics(plugin);
|
||||
final Metrics metrics = new Metrics(plugin, 164);
|
||||
|
||||
metrics.addCustomChart(new Metrics.SimplePie("messages_language",
|
||||
metrics.addCustomChart(new SimplePie("messages_language",
|
||||
() -> settings.getProperty(PluginSettings.MESSAGES_LANGUAGE)));
|
||||
metrics.addCustomChart(new Metrics.SimplePie("database_backend",
|
||||
metrics.addCustomChart(new SimplePie("database_backend",
|
||||
() -> settings.getProperty(DatabaseSettings.BACKEND).toString()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets up the console filter if enabled.
|
||||
*
|
||||
* @param settings the settings
|
||||
* @param logger the plugin logger
|
||||
* @param logger the plugin logger
|
||||
*/
|
||||
public static void setupConsoleFilter(Settings settings, Logger logger) {
|
||||
public static void setupConsoleFilter(Logger logger) {
|
||||
// Try to set the log4j filter
|
||||
try {
|
||||
Class.forName("org.apache.logging.log4j.core.filter.AbstractFilter");
|
||||
setLog4JFilter();
|
||||
} catch (ClassNotFoundException | NoClassDefFoundError e) {
|
||||
// log4j is not available
|
||||
ConsoleLogger.info("You're using Minecraft 1.6.x or older, Log4J support will be disabled");
|
||||
consoleLogger.info("You're using Minecraft 1.6.x or older, Log4J support will be disabled");
|
||||
ConsoleFilter filter = new ConsoleFilter();
|
||||
logger.setFilter(filter);
|
||||
Bukkit.getLogger().setFilter(filter);
|
||||
|
@ -91,12 +96,18 @@ public class OnStartupTasks {
|
|||
if (!settings.getProperty(RECALL_PLAYERS)) {
|
||||
return;
|
||||
}
|
||||
bukkitService.runTaskTimerAsynchronously(() -> {
|
||||
for (String playerWithoutMail : dataSource.getLoggedPlayersWithEmptyMail()) {
|
||||
Player player = bukkitService.getPlayerExact(playerWithoutMail);
|
||||
if (player != null) {
|
||||
messages.send(player, MessageKey.ADD_EMAIL_MESSAGE);
|
||||
}
|
||||
bukkitService.runTaskTimerAsynchronously(new BukkitRunnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
List<String> loggedPlayersWithEmptyMail = dataSource.getLoggedPlayersWithEmptyMail();
|
||||
bukkitService.runTask(() -> {
|
||||
for (String playerWithoutMail : loggedPlayersWithEmptyMail) {
|
||||
Player player = bukkitService.getPlayerExact(playerWithoutMail);
|
||||
if (player != null) {
|
||||
messages.send(player, MessageKey.ADD_EMAIL_MESSAGE);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}, 1, TICKS_PER_MINUTE * settings.getProperty(EmailSettings.DELAY_RECALL));
|
||||
}
|
||||
|
|
|
@ -25,5 +25,4 @@ public class BlockListener implements Listener {
|
|||
event.setCancelled(true);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
package fr.xephi.authme.listener;
|
||||
|
||||
import fr.xephi.authme.ConsoleLogger;
|
||||
import org.bukkit.entity.LivingEntity;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.entity.Projectile;
|
||||
import org.bukkit.event.EventHandler;
|
||||
|
@ -15,29 +13,19 @@ import org.bukkit.event.entity.EntityShootBowEvent;
|
|||
import org.bukkit.event.entity.EntityTargetEvent;
|
||||
import org.bukkit.event.entity.FoodLevelChangeEvent;
|
||||
import org.bukkit.event.entity.ProjectileLaunchEvent;
|
||||
import org.bukkit.projectiles.ProjectileSource;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
public class EntityListener implements Listener {
|
||||
|
||||
private final ListenerService listenerService;
|
||||
private Method getShooter;
|
||||
private boolean shooterIsLivingEntity;
|
||||
|
||||
@Inject
|
||||
EntityListener(ListenerService listenerService) {
|
||||
this.listenerService = listenerService;
|
||||
try {
|
||||
getShooter = Projectile.class.getDeclaredMethod("getShooter");
|
||||
shooterIsLivingEntity = getShooter.getReturnType() == LivingEntity.class;
|
||||
} catch (NoSuchMethodException | SecurityException e) {
|
||||
ConsoleLogger.logException("Cannot load getShooter() method on Projectile class", e);
|
||||
}
|
||||
}
|
||||
|
||||
// Note #360: npc status can be used to bypass security!!!
|
||||
@EventHandler(ignoreCancelled = true, priority = EventPriority.LOWEST)
|
||||
public void onDamage(EntityDamageEvent event) {
|
||||
if (listenerService.shouldCancelEvent(event)) {
|
||||
|
@ -56,7 +44,7 @@ public class EntityListener implements Listener {
|
|||
|
||||
@EventHandler(ignoreCancelled = true, priority = EventPriority.LOWEST)
|
||||
public void onEntityTarget(EntityTargetEvent event) {
|
||||
if (listenerService.shouldCancelEvent(event)) {
|
||||
if (listenerService.shouldCancelEvent(event.getTarget())) {
|
||||
event.setTarget(null);
|
||||
event.setCancelled(true);
|
||||
}
|
||||
|
@ -77,6 +65,7 @@ public class EntityListener implements Listener {
|
|||
}
|
||||
}
|
||||
|
||||
//TODO sgdc3 20190808: We listen at the same event twice, does it make any sense?
|
||||
@EventHandler(ignoreCancelled = true, priority = EventPriority.HIGHEST)
|
||||
public void onEntityInteract(EntityInteractEvent event) {
|
||||
if (listenerService.shouldCancelEvent(event)) {
|
||||
|
@ -93,26 +82,10 @@ public class EntityListener implements Listener {
|
|||
|
||||
@EventHandler(ignoreCancelled = true, priority = EventPriority.LOWEST)
|
||||
public void onProjectileLaunch(ProjectileLaunchEvent event) {
|
||||
if (event.getEntity() == null) {
|
||||
return;
|
||||
}
|
||||
final Projectile projectile = event.getEntity();
|
||||
|
||||
Projectile projectile = event.getEntity();
|
||||
// In the Bukkit API prior to 1.7, getShooter() returns a LivingEntity instead of a ProjectileSource
|
||||
Object shooterRaw = null;
|
||||
if (shooterIsLivingEntity) {
|
||||
try {
|
||||
if (getShooter == null) {
|
||||
getShooter = Projectile.class.getMethod("getShooter");
|
||||
}
|
||||
shooterRaw = getShooter.invoke(projectile);
|
||||
} catch (NoSuchMethodException | InvocationTargetException | IllegalAccessException e) {
|
||||
ConsoleLogger.logException("Error getting shooter", e);
|
||||
}
|
||||
} else {
|
||||
shooterRaw = projectile.getShooter();
|
||||
}
|
||||
if (shooterRaw instanceof Player && listenerService.shouldCancelEvent((Player) shooterRaw)) {
|
||||
ProjectileSource shooter = projectile.getShooter();
|
||||
if (shooter instanceof Player && listenerService.shouldCancelEvent((Player) shooter)) {
|
||||
event.setCancelled(true);
|
||||
}
|
||||
}
|
||||
|
@ -123,5 +96,4 @@ public class EntityListener implements Listener {
|
|||
event.setCancelled(true);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,66 +0,0 @@
|
|||
package fr.xephi.authme.listener;
|
||||
|
||||
import fr.xephi.authme.permission.PermissionNode;
|
||||
import fr.xephi.authme.permission.PermissionsManager;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.util.function.BiFunction;
|
||||
|
||||
/**
|
||||
* Represents a player joining the server, which depending on the available
|
||||
* information may be his name or the actual Player object.
|
||||
*/
|
||||
public final class JoiningPlayer {
|
||||
|
||||
private final String name;
|
||||
private final BiFunction<PermissionsManager, PermissionNode, Boolean> permissionLookupFunction;
|
||||
|
||||
/**
|
||||
* Hidden constructor.
|
||||
*
|
||||
* @param name the player's name
|
||||
* @param permFunction the function to use for permission lookups
|
||||
*/
|
||||
private JoiningPlayer(String name, BiFunction<PermissionsManager, PermissionNode, Boolean> permFunction) {
|
||||
this.name = name;
|
||||
this.permissionLookupFunction = permFunction;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a {@link JoiningPlayer} instance from the given name.
|
||||
*
|
||||
* @param name the player's name
|
||||
* @return the created instance
|
||||
*/
|
||||
public static JoiningPlayer fromName(String name) {
|
||||
return new JoiningPlayer(name, (manager, perm) -> manager.hasPermissionOffline(name, perm));
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a {@link JoiningPlayer} instance from the given Player object.
|
||||
*
|
||||
* @param player the player
|
||||
* @return the created instance
|
||||
*/
|
||||
public static JoiningPlayer fromPlayerObject(Player player) {
|
||||
return new JoiningPlayer(player.getName(), (manager, perm) -> manager.hasPermission(player, perm));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the player's name
|
||||
*/
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the function to use for permission lookups. Takes two arguments: the PermissionsManager instance,
|
||||
* and the permission node to look up. The result is a boolean indicating whether or not this joining player
|
||||
* has permission.
|
||||
*
|
||||
* @return the permissions lookup function to use
|
||||
*/
|
||||
public BiFunction<PermissionsManager, PermissionNode, Boolean> getPermissionLookupFunction() {
|
||||
return permissionLookupFunction;
|
||||
}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue