Compare commits

...

274 Commits

Author SHA1 Message Date
0de8e247cb Update dependency org.apache.commons:commons-lang3 to v3.18.0 2025-09-11 22:01:52 +00:00
8d4f331880 Update dependency gradle to v8.14.3 2025-09-11 21:03:00 +00:00
7f1b77ce19 Update dependency dnsjava:dnsjava to v3.6.3 2025-09-11 21:02:17 +00:00
d4080bb2e5 Update dependency commons-io:commons-io to v2.20.0 2025-09-11 20:01:55 +00:00
0106364680 Update dependency commons-codec:commons-codec to v1.19.0 2025-09-11 20:01:50 +00:00
b1ef1b9aa1 Update dependency com.mchange:c3p0 to v0.11.2 2025-09-11 19:02:25 +00:00
84b4c9c3ed Update dependency com.github.ben-manes:gradle-versions-plugin to v0.52.0 2025-09-11 19:02:18 +00:00
dedce04961 Update dependency org.postgresql:postgresql to v42.7.7 2025-09-11 18:01:43 +00:00
a4e99fcc79 Update dependency org.xerial:sqlite-jdbc to v3.50.3.0 2025-09-11 17:02:23 +00:00
d568678df5 Update dependency com.twilio.sdk:twilio to v10.9.2 2025-09-11 17:02:19 +00:00
31210f4e71 Update dependency org.apache.directory.api:api-all to v2.1.7 2025-09-11 17:02:08 +00:00
df70b65ac3 Update dependency org.mariadb.jdbc:mariadb-java-client to v3.5.6 2025-09-11 16:01:44 +00:00
949bfc38f8 Merge pull request 'Update dependency com.mchange:c3p0 to v0.10.1' (#51) from renovate/com.mchange-c3p0-0.x into master
Reviewed-on: #51
2024-05-09 12:15:33 +00:00
c5e5f643a2 Merge pull request 'Update dependency com.googlecode.libphonenumber:libphonenumber to v8.13.36' (#50) from renovate/com.googlecode.libphonenumber-libphonenumber-8.x into master
Reviewed-on: #50
2024-05-09 12:15:23 +00:00
5820156512 Merge pull request 'Update dependency commons-codec:commons-codec to v1.17.0' (#49) from renovate/commons-codec-commons-codec-1.x into master
Reviewed-on: #49
2024-05-09 12:15:15 +00:00
7cc4be7cd6 Update dependency com.mchange:c3p0 to v0.10.1 2024-05-07 15:01:15 +00:00
5e31ff9b69 Update dependency com.googlecode.libphonenumber:libphonenumber to v8.13.36 2024-05-02 09:01:21 +00:00
d910472db5 Update dependency commons-codec:commons-codec to v1.17.0 2024-04-27 14:01:32 +00:00
ca56afad5d Merge pull request 'Update dependency io.undertow:undertow-core to v2.3.13.Final' (#48) from renovate/io.undertow-undertow-core-2.x into master
Reviewed-on: #48
2024-04-23 11:58:50 +00:00
541aeee3c2 Merge pull request 'Update dependency com.twilio.sdk:twilio to v10.1.5' (#47) from renovate/com.twilio.sdk-twilio-10.x into master
Reviewed-on: #47
2024-04-23 11:58:42 +00:00
19257a0290 Merge pull request 'Update dependency com.googlecode.libphonenumber:libphonenumber to v8.13.35' (#46) from renovate/com.googlecode.libphonenumber-libphonenumber-8.x into master
Reviewed-on: #46
2024-04-23 11:58:32 +00:00
8d91e7d5a3 Merge pull request 'Update dependency commons-cli:commons-cli to v1.7.0' (#45) from renovate/commons-cli-commons-cli-1.x into master
Reviewed-on: #45
2024-04-23 11:58:23 +00:00
c0671acf60 Merge pull request 'Update dependency org.xerial:sqlite-jdbc to v3.45.3.0' (#44) from renovate/org.xerial-sqlite-jdbc-3.x into master
Reviewed-on: #44
2024-04-23 11:58:14 +00:00
0b8300c774 Merge pull request 'Update dependency org.slf4j:slf4j-simple to v2.0.13' (#43) from renovate/slf4j-monorepo into master
Reviewed-on: #43
2024-04-23 11:58:05 +00:00
cac55d5f06 Merge pull request 'Update dependency commons-io:commons-io to v2.16.1' (#42) from renovate/commons-io-commons-io-2.x into master
Reviewed-on: #42
2024-04-23 11:57:55 +00:00
aa3aadbb53 Merge pull request 'Update dependency com.kohlschutter.junixsocket:junixsocket-core to v2.9.1' (#41) from renovate/com.kohlschutter.junixsocket-junixsocket-core-2.x into master
Reviewed-on: #41
2024-04-23 11:57:45 +00:00
da7fa9edd6 Update dependency io.undertow:undertow-core to v2.3.13.Final 2024-04-19 13:01:54 +00:00
a1a21e8d60 Update dependency com.twilio.sdk:twilio to v10.1.5 2024-04-18 15:01:47 +00:00
dc2932cf51 Update dependency com.googlecode.libphonenumber:libphonenumber to v8.13.35 2024-04-18 10:01:42 +00:00
bb84e32719 Update dependency commons-cli:commons-cli to v1.7.0 2024-04-18 02:01:51 +00:00
12aa40b160 Update dependency org.xerial:sqlite-jdbc to v3.45.3.0 2024-04-16 04:01:50 +00:00
9d4fddcb2d Update dependency org.slf4j:slf4j-simple to v2.0.13 2024-04-12 15:01:46 +00:00
4654cff158 Update dependency commons-io:commons-io to v2.16.1 2024-04-08 18:01:40 +00:00
b1888fed96 Update dependency com.kohlschutter.junixsocket:junixsocket-core to v2.9.1 2024-04-05 16:01:34 +00:00
d7e8b3d62a Java 21 2024-04-02 18:02:39 +02:00
56bfdda18c Update Java 2024-04-02 17:57:00 +02:00
fb3debfb49 Replace apk with apt 2024-04-02 17:52:14 +02:00
49f812f867 Bump Java to 22 2024-04-02 17:45:01 +02:00
de0a3152c3 Bump JRE to 21 2024-04-02 16:08:59 +02:00
cc5d047c3f Merge pull request 'Update dependency com.googlecode.libphonenumber:libphonenumber to v8.13.34' (#40) from renovate/com.googlecode.libphonenumber-libphonenumber-8.x into master
Reviewed-on: #40
2024-04-02 13:54:24 +00:00
350776df17 Merge pull request 'Update dependency com.twilio.sdk:twilio to v10.1.3' (#39) from renovate/com.twilio.sdk-twilio-10.x into master
Reviewed-on: #39
2024-04-02 13:54:13 +00:00
7b6560e9c8 Merge pull request 'Update dependency commons-io:commons-io to v2.16.0' (#38) from renovate/commons-io-commons-io-2.x into master
Reviewed-on: #38
2024-04-02 13:54:00 +00:00
4fd4fdac60 Updates to build sucessfully - breaking changes in Firebase and SendGrid 2024-04-02 15:42:15 +02:00
dfad9d9ce8 Update dependency com.googlecode.libphonenumber:libphonenumber to v8.13.34 2024-04-02 13:01:23 +00:00
d2fc4e3bef Update dependency com.twilio.sdk:twilio to v10.1.3 2024-04-01 11:01:26 +00:00
4416c17216 Update dependency commons-io:commons-io to v2.16.0 2024-03-28 23:01:26 +00:00
f54ed462b1 Update shadowJar to new config format 2024-03-27 16:28:52 +01:00
7498dcf122 Merge pull request 'Update dependency org.yaml:snakeyaml to v2' (#37) from renovate/org.yaml-snakeyaml-2.x into master
Reviewed-on: #37
2024-03-27 14:28:16 +00:00
7e5665a56f Merge pull request 'Update dependency org.slf4j:slf4j-simple to v2' (#36) from renovate/major-slf4j-monorepo into master
Reviewed-on: #36
2024-03-27 14:28:05 +00:00
f633e9d256 Merge pull request 'Update dependency org.mariadb.jdbc:mariadb-java-client to v3' (#35) from renovate/org.mariadb.jdbc-mariadb-java-client-3.x into master
Reviewed-on: #35
2024-03-27 14:27:56 +00:00
bdfe4a00a9 Merge pull request 'Update dependency org.apache.directory.api:api-all to v2' (#34) from renovate/org.apache.directory.api-api-all-2.x into master
Reviewed-on: #34
2024-03-27 14:27:48 +00:00
50d4f0fa30 Update dependency org.yaml:snakeyaml to v2 2024-03-27 14:01:31 +00:00
bb190230b2 Update dependency org.slf4j:slf4j-simple to v2 2024-03-27 14:01:29 +00:00
c9bafd9af2 Update ma1sd to mxids 2024-03-27 14:10:04 +01:00
3c9c8ca1b5 Update dependency org.mariadb.jdbc:mariadb-java-client to v3 2024-03-27 13:01:32 +00:00
dacf96140c Update dependency org.apache.directory.api:api-all to v2 2024-03-27 13:01:30 +00:00
1d228d75e6 Update .github/workflows/codeql-analysis.yml.disabled 2024-03-27 12:39:33 +00:00
62530eda08 Update .github/workflows/codeql-analysis.disable 2024-03-27 12:39:21 +00:00
15c3e6b425 Update .github/workflows/codeql-analysis.disable.yml
Some checks failed
CodeQL / Analyze (java) (push) Failing after 31s
2024-03-27 12:38:58 +00:00
945a2dbdf5 Merge pull request 'Update dependency gradle to v8' (#33) from renovate/gradle-8.x into master
Some checks failed
CodeQL / Analyze (java) (push) Failing after 28s
Reviewed-on: #33
2024-03-27 12:33:46 +00:00
d5cebf103d Merge pull request 'Update dependency dnsjava:dnsjava to v3' (#32) from renovate/dnsjava-dnsjava-3.x into master
Some checks failed
CodeQL / Analyze (java) (push) Has been cancelled
Reviewed-on: #32
2024-03-27 12:33:26 +00:00
de14f80a40 Merge pull request 'Update dependency com.unboundid:unboundid-ldapsdk to v7' (#31) from renovate/com.unboundid-unboundid-ldapsdk-7.x into master
Some checks failed
CodeQL / Analyze (java) (push) Has been cancelled
Reviewed-on: #31
2024-03-27 12:33:12 +00:00
7ed6db537d Update codeql api version
Some checks failed
CodeQL / Analyze (java) (push) Failing after 1m33s
2024-03-27 12:28:02 +00:00
9d8d88527c Update .github/workflows/codeql-analysis.yml
Some checks failed
CodeQL / Analyze (java) (push) Failing after 33s
2024-03-27 12:26:01 +00:00
a1c82878f2 Update dependency gradle to v8
Some checks failed
CodeQL / Analyze (java) (pull_request) Failing after 21s
2024-03-27 12:02:36 +00:00
ab95c8ee32 Update dependency dnsjava:dnsjava to v3
Some checks failed
CodeQL / Analyze (java) (pull_request) Failing after 20s
2024-03-27 12:02:04 +00:00
e50a49b198 Update dependency com.unboundid:unboundid-ldapsdk to v7
Some checks failed
CodeQL / Analyze (java) (pull_request) Failing after 20s
2024-03-27 12:02:04 +00:00
4492888557 Merge pull request 'Update dependency com.twilio.sdk:twilio to v10' (#30) from renovate/com.twilio.sdk-twilio-10.x into master
Reviewed-on: #30
2024-03-27 11:52:25 +00:00
ed5407fc42 Merge pull request 'Update dependency com.sendgrid:sendgrid-java to v4' (#29) from renovate/com.sendgrid-sendgrid-java-4.x into master
Reviewed-on: #29
2024-03-27 11:52:16 +00:00
a2911f2ace Merge pull request 'Update dependency com.j256.ormlite:ormlite-jdbc to v6' (#28) from renovate/com.j256.ormlite-ormlite-jdbc-6.x into master
Reviewed-on: #28
2024-03-27 11:52:03 +00:00
e99578d168 Merge pull request 'Update dependency com.icegreen:greenmail to v2' (#27) from renovate/com.icegreen-greenmail-2.x into master
Reviewed-on: #27
2024-03-27 11:51:53 +00:00
d471ea71d7 Merge pull request 'Update dependency com.google.firebase:firebase-admin to v9' (#26) from renovate/com.google.firebase-firebase-admin-9.x into master
Reviewed-on: #26
2024-03-27 11:51:42 +00:00
56115df282 Merge pull request 'Update dependency com.github.tomakehurst:wiremock to v3' (#25) from renovate/com.github.tomakehurst-wiremock-3.x into master
Reviewed-on: #25
2024-03-27 11:51:27 +00:00
2e1194d216 Merge pull request 'Update dependency org.yaml:snakeyaml to v1.33' (#24) from renovate/org.yaml-snakeyaml-1.x into master
Reviewed-on: #24
2024-03-27 11:51:18 +00:00
ee001d543c Merge pull request 'Update dependency org.apache.commons:commons-lang3 to v3.14.0' (#21) from renovate/org.apache.commons-commons-lang3-3.x into master
Reviewed-on: #21
2024-03-27 11:51:06 +00:00
a826eb319e Merge pull request 'Update dependency commons-codec:commons-codec to v1.16.1' (#17) from renovate/commons-codec-commons-codec-1.x into master
Reviewed-on: #17
2024-03-27 11:50:56 +00:00
6b557e9954 Update dependency com.twilio.sdk:twilio to v10 2024-03-27 10:02:03 +00:00
041a4d1b73 Update dependency com.sendgrid:sendgrid-java to v4 2024-03-27 09:02:08 +00:00
c1a1741bfb Update dependency com.j256.ormlite:ormlite-jdbc to v6 2024-03-27 09:02:07 +00:00
6e1058c484 Update dependency com.icegreen:greenmail to v2 2024-03-27 08:02:04 +00:00
5f6fb38485 Update dependency com.google.firebase:firebase-admin to v9 2024-03-27 08:02:03 +00:00
c9046ffbd0 Update dependency com.github.tomakehurst:wiremock to v3 2024-03-27 07:02:17 +00:00
cf97c5a88f Update dependency org.yaml:snakeyaml to v1.33 2024-03-27 07:02:15 +00:00
3d1a8c4495 Update dependency org.apache.commons:commons-lang3 to v3.14.0 2024-03-27 07:02:14 +00:00
46dc07ef07 Update dependency commons-codec:commons-codec to v1.16.1 2024-03-27 07:02:13 +00:00
d9ab2b8739 Merge pull request 'Update dependency org.xerial:sqlite-jdbc to v3.45.2.0' (#23) from renovate/org.xerial-sqlite-jdbc-3.x into master
Reviewed-on: #23
2024-03-27 06:10:34 +00:00
14032aaf50 Merge pull request 'Update dependency org.postgresql:postgresql to v42.7.3' (#22) from renovate/org.postgresql-postgresql-42.x into master
Reviewed-on: #22
2024-03-27 06:10:23 +00:00
73051c3d00 Merge pull request 'Update dependency io.undertow:undertow-core to v2.3.12.Final' (#20) from renovate/io.undertow-undertow-core-2.x into master
Reviewed-on: #20
2024-03-27 06:10:04 +00:00
a3c8c4a8cf Merge pull request 'Update dependency gradle to v7.6.4' (#19) from renovate/gradle-7.x into master
Reviewed-on: #19
2024-03-27 06:09:47 +00:00
453751a39e Merge pull request 'Update dependency commons-io:commons-io to v2.15.1' (#18) from renovate/commons-io-commons-io-2.x into master
Reviewed-on: #18
2024-03-27 06:09:06 +00:00
ad23e91ece Merge pull request 'Update dependency commons-cli:commons-cli to v1.6.0' (#16) from renovate/commons-cli-commons-cli-1.x into master
Reviewed-on: #16
2024-03-27 06:08:42 +00:00
baabdfc2ef Merge pull request 'Update dependency com.twilio.sdk:twilio to v7.55.3' (#15) from renovate/com.twilio.sdk-twilio-7.x into master
Reviewed-on: #15
2024-03-27 06:08:20 +00:00
263e3260c9 Merge pull request 'Update dependency com.squareup.okhttp3:okhttp to v4.12.0' (#14) from renovate/okhttp-monorepo into master
Reviewed-on: #14
2024-03-27 06:08:10 +00:00
a281bdbf77 Update dependency org.xerial:sqlite-jdbc to v3.45.2.0 2024-03-26 22:02:15 +00:00
338e7f4aa2 Update dependency org.postgresql:postgresql to v42.7.3 2024-03-26 22:02:13 +00:00
a9212ce73a Update dependency io.undertow:undertow-core to v2.3.12.Final 2024-03-26 21:02:09 +00:00
f2e1fcb25f Update dependency gradle to v7.6.4 2024-03-26 20:02:39 +00:00
f5630bc4d9 Update dependency commons-io:commons-io to v2.15.1 2024-03-26 20:02:09 +00:00
dbccaecfd6 Update dependency commons-cli:commons-cli to v1.6.0 2024-03-26 19:02:15 +00:00
de0842d3a8 Update dependency com.twilio.sdk:twilio to v7.55.3 2024-03-26 18:02:10 +00:00
05424f14b8 Update dependency com.squareup.okhttp3:okhttp to v4.12.0 2024-03-26 18:02:08 +00:00
2587e6be7c Merge pull request 'Update dependency com.mchange:c3p0 to v0.10.0' (#13) from renovate/com.mchange-c3p0-0.x into master
Reviewed-on: #13
2024-03-26 17:39:03 +00:00
20062fe5bc Merge pull request 'Update dependency com.kohlschutter.junixsocket:junixsocket-core to v2.9.0' (#12) from renovate/com.kohlschutter.junixsocket-junixsocket-core-2.x into master
Reviewed-on: #12
2024-03-26 17:38:51 +00:00
0ec6462ff4 Update dependency com.mchange:c3p0 to v0.10.0 2024-03-26 17:02:16 +00:00
567c7bb972 Update dependency com.kohlschutter.junixsocket:junixsocket-core to v2.9.0 2024-03-26 17:02:14 +00:00
1c6322f1c2 Merge pull request 'Update dependency com.j256.ormlite:ormlite-jdbc to v5.7' (#11) from renovate/com.j256.ormlite-ormlite-jdbc-5.x into master
Reviewed-on: #11
2024-03-26 16:05:03 +00:00
603cdd1340 Merge pull request 'Update dependency com.icegreen:greenmail to v1.6.15' (#10) from renovate/com.icegreen-greenmail-1.x into master
Reviewed-on: #10
2024-03-26 16:04:50 +00:00
a6164379c5 Update dependency com.j256.ormlite:ormlite-jdbc to v5.7 2024-03-26 16:02:05 +00:00
fc9d6b3a36 Update dependency com.icegreen:greenmail to v1.6.15 2024-03-26 16:02:03 +00:00
8b14664dc7 Merge pull request 'Update dependency com.googlecode.libphonenumber:libphonenumber to v8.13.33' (#9) from renovate/com.googlecode.libphonenumber-libphonenumber-8.x into master
Reviewed-on: #9
2024-03-26 15:18:14 +00:00
f0922d67df Merge pull request 'Update dependency com.google.firebase:firebase-admin to v5.11.0' (#8) from renovate/com.google.firebase-firebase-admin-5.x into master
Reviewed-on: #8
2024-03-26 15:18:02 +00:00
6e05b51fdc Update dependency com.googlecode.libphonenumber:libphonenumber to v8.13.33 2024-03-26 15:02:08 +00:00
0999ef6309 Update dependency com.google.firebase:firebase-admin to v5.11.0 2024-03-26 15:02:06 +00:00
cae00f4606 Merge pull request 'Update dependency com.github.ben-manes:gradle-versions-plugin to v0.51.0' (#7) from renovate/com.github.ben-manes-gradle-versions-plugin-0.x into master
Reviewed-on: #7
2024-03-26 14:15:58 +00:00
941ae697e7 Merge pull request 'Update openjdk Docker tag to v11.0.16-jre-slim' (#6) from renovate/openjdk-11.x into master
Reviewed-on: #6
2024-03-26 14:15:43 +00:00
fbf1ea8f5b Merge pull request 'Update dependency org.slf4j:slf4j-simple to v1.7.36' (#5) from renovate/slf4j-monorepo into master
Reviewed-on: #5
2024-03-26 14:15:25 +00:00
4eef3ac40d Merge pull request 'Update dependency org.mariadb.jdbc:mariadb-java-client to v2.7.12' (#4) from renovate/org.mariadb.jdbc-mariadb-java-client-2.x into master
Reviewed-on: #4
2024-03-26 14:15:06 +00:00
e6c90aa00f Update dependency com.github.ben-manes:gradle-versions-plugin to v0.51.0 2024-03-26 14:02:17 +00:00
ca306a3212 Update openjdk Docker tag to v11.0.16-jre-slim 2024-03-26 14:02:15 +00:00
e8864afe02 Update dependency org.slf4j:slf4j-simple to v1.7.36 2024-03-26 13:02:02 +00:00
f09ede8780 Update dependency org.mariadb.jdbc:mariadb-java-client to v2.7.12 2024-03-26 13:02:01 +00:00
98146d3468 Merge pull request 'Update dependency org.apache.httpcomponents:httpclient to v4.5.14' (#3) from renovate/org.apache.httpcomponents-httpclient-4.x into master
Reviewed-on: #3
2024-03-26 12:25:59 +00:00
5f64b72a91 Merge pull request 'Update dependency com.unboundid:unboundid-ldapsdk to v4.0.14' (#2) from renovate/com.unboundid-unboundid-ldapsdk-4.x into master
Reviewed-on: #2
2024-03-26 12:25:43 +00:00
acb2b5a37d Update ma1sd to mxids 2024-03-26 13:21:48 +01:00
9f9c48aaa7 Update dependency org.apache.httpcomponents:httpclient to v4.5.14 2024-03-26 12:21:43 +00:00
eb6e541e15 Update dependency com.unboundid:unboundid-ldapsdk to v4.0.14 2024-03-26 12:21:41 +00:00
e45ac5a78a Merge pull request 'Add renovate.json' (#1) from tomas.kracmar-add-renovatebot-support into master
Reviewed-on: #1
2024-03-14 09:06:29 +00:00
aebcb7b5e1 Add renovate.json 2024-03-14 09:06:12 +00:00
c45f95ce3f Merge pull request 'Upgrade to V3 API' (#1) from ext/v3_update into master
Reviewed-on: cqrenet/ma1sd#1
2024-03-11 08:51:06 +00:00
640fa8e9f1 Upgrade to V3 API 2024-03-11 09:50:09 +01:00
0f3c37bf6a Get access_token from header correctly 2024-03-05 17:50:29 +01:00
Anatoliy Sablin
ae5864cd91 Bump dependencies. 2021-04-16 21:48:19 +03:00
Anatoliy Sablin
e456724caf Bump gradle to 7.0. Replace jcenter with mavenCentral and gradle plugin portal. 2021-04-16 20:58:32 +03:00
Anatoliy Sablin
ed9dcc4061 Respond with application/json for the register submitToken. 2021-02-04 21:10:25 +03:00
Anatoliy Sablin
ea8e386939 Add internal API to manually invoke invitation manager. 2021-01-25 22:45:18 +03:00
Anatoliy Sablin
e0ec887118 Add config print full display name of the invited person. 2021-01-17 20:06:09 +03:00
Anatoliy Sablin
a71d32ba77 Add config option to specify period dimension of the invitation scheduler. 2021-01-13 22:09:30 +03:00
Anatoliy Sablin
a0f6fe9b0d Add forgotten M_TERMS_NOT_SIGNED error message. 2021-01-13 21:41:21 +03:00
ma1uta
c25647156a Merge pull request #77 from mrjohnson22/master
#76 Set a message for error responses
2020-12-20 11:14:20 +00:00
Xavier Johnson
e7c4c12a98 #76 Set a message for error responses
Without one, clients might treat errors as generic failures instead of
handling them in a manner appropriate for their error code
2020-12-18 23:00:06 -05:00
Anatoliy Sablin
90b2b5301c #68 Mark thusted_third_party_id_servers synapse parameter as deprecated. 2020-12-07 20:39:47 +03:00
Anatoliy Sablin
0d93a26e6d #65 Encode query parameters in the validation link. 2020-12-07 20:32:59 +03:00
ma1uta
c29fc0f0eb Merge pull request #71 from q-wertz/master
Force MatrixID to be lowercase
2020-11-29 08:22:45 +00:00
Clemens Sonnleitner
e421c851c9 Force MatrixID to be lowercase 2020-11-27 13:08:45 +01:00
ma1uta
5b2b45233a Merge pull request #67 from Higgs1/master
Add support for unix sockets.
2020-11-05 05:56:26 +00:00
Lexxy Fox
888f7a4209 Added support for unix sockets. 2020-11-04 08:21:35 -08:00
Anatoliy Sablin
0c301a49c7 Change column type to text for postgresql. 2020-10-26 23:26:15 +03:00
ma1uta
1fda2dd3b7 Create codeql-analysis.yml 2020-10-01 14:51:31 +03:00
ma1uta
c4a20efe5e Merge pull request #58 from nE0sIghT/wip/multidomain
Support for Active Directory multidomain forest
2020-09-19 13:14:19 +00:00
ma1uta
fc45f1b090 Merge pull request #55 from mattcen/docker-build-cleanup
Docker build cleanup
2020-09-19 13:13:16 +00:00
Matt Cengia
1480507d76 Only build .jar on current build platform
Because the .jar is platform-independent, we don't need to build it for every architecture.
2020-09-18 12:45:33 +10:00
Matt Cengia
a1ab1e8e0a Tidy Gradle dockerBuildX target
Build linux/amd64, linux/arm64, and linux/arm/v7 (arm 32-bit) targets
all at once.
This still requires Gradle and JDK on the local machine (i.e. outside of
the Docker build container), because it seems pointless to build the
.jar 3 times, once for each architecture, but tags all the images with
the same tag, rather than using a tag for each architecture. This allows
clients to all use the same image tag, but pull down the architecture
that's right for them.

I'd like to have it build the .jar file in a container (so the host
doesn't need JDK and Gradle), but couldn't think how to do that
efficiently (i.e. only once), with this approach.
2020-09-17 10:54:29 +10:00
Matt Cengia
1e5033b461 Don't require Gradle to build Docker image
Update Dockerfile to use a multi-stage build and run Gradle *within* the
builder container, rather than on the host, so the host needn't have
Gradle or JDK installed, then copy the build .jar from the builder
container into the final container.

Update build.gradle's dockerBuild target to not build the jar, but
instead do it within the Docker build process. This results in some
double-handling because it requires Gradle and JDK both on the host
system *and* within the container, and runs two instances of Gradle
during the build, but is added for backwards compatibility. The better
approach (rather than running `./gradlew dockerBuild`) is to manually
run `docker build -t ma1ua/ma1sd .`.

I've tested this process on both a Debian amd64 system and a Raspberry
Pi 3 running Raspbian, and it seems to work (though the RPi is pretty
slow).
2020-09-17 10:54:29 +10:00
Yuri Konotopov
7323851c6e Support for Active Directory multidomain forest
In AD forest samAccountName (or uid) may not be unique in the
entire forest and userPrincipalName contains "@" symbol
disallowed in Matrix User Identifiers.

This commit reflects changes in ldap_auth_provider that adds
mxid generation logic for Active Directory.

Signed-off-by: Yuri Konotopov <ykonotopov@gnome.org>
2020-08-28 15:33:10 +04:00
Anatoliy Sablin
08db73e55b Escape special characters in the LDAP query string. 2020-08-02 16:05:54 +03:00
Anatoliy Sablin
9fba20475b fix #49. 2020-06-23 00:18:27 +03:00
ma1uta
9af5fce014 Merge pull request #50 from lub/patch-1
remove warning about matrix-synapse-ldap3
2020-06-22 19:54:51 +00:00
ma1uta
9843e14c1a Merge pull request #38 from NullIsNot0/NullIsNot0-make-emails-lowercase
Make all 3PID address lowercase to avoid duplicates
2020-06-22 19:51:42 +00:00
lub
60e6f1e23c fix typo
on -> one
2020-06-05 13:23:37 +02:00
lub
6cdbcc69c7 remove warning about matrix-synapse-ldap3
I don't think it's a fair assessment that the project is unmaintaned. When you look at the issues and PRs there still is active development happening.
2020-06-05 13:22:49 +02:00
Anatoliy Sablin
ed7c714738 Fix #41. 2020-05-31 22:56:01 +03:00
Anatoliy Sablin
a9d783192b Add multiple-platform builds. Add experimental arm64 build. 2020-05-31 22:10:32 +03:00
ma1uta
2bb5a734d1 Merge pull request #45 from teutat3s/fix_directory_lookups
Avoid including bridged user in directory lookups
2020-05-19 19:32:31 +00:00
teutat3s
9aa5c4cca9 Avoid including bridged user in directory lookups 2020-05-19 13:04:22 +02:00
Anatoliy Sablin
9c4faab5d8 Add option to log all requests and responses. 2020-05-06 23:46:34 +03:00
Anatoliy Sablin
53c4ffdc4e Add pooling database connection for postgresql. 2020-05-06 20:55:14 +03:00
Anatoliy Sablin
e4144e923a Add error logs. 2020-05-06 19:47:13 +03:00
Anatoliy Sablin
791361c10d Add the migration to fix column types in the postgresql. 2020-05-06 19:39:33 +03:00
NullIsNot0
7c94bd4744 Make all 3PID address lowercase to avoid duplicates
These changes complement #11 where locally saved e-mail address can be "name.surname@example.com", but e-mail address in LDAP can be "Name.Surname@example.com". They are treated as two different e-mail addresses and user gets 2 invitation notification e-mails. We change ThreePid model's address property to convert all info to lowercase and [be915ae](be915aed94) can do it's job better.
The downside of this is that all medium addresses get converted to lowercase, not only e-mails. For now I can't think of any examples where medium values need to stay case sensitive.
2020-05-06 07:41:44 +03:00
Anatoliy Sablin
4b5eecd7e7 Enable v2 by default because Riot require v2 api. 2020-04-21 23:27:20 +03:00
Anatoliy Sablin
a6968fb7e9 Fix #27. 2020-04-07 22:46:14 +03:00
Anatoliy Sablin
d4853b1154 Add config for hostname. 2020-04-07 22:46:14 +03:00
ma1uta
89df4b2425 Merge pull request #33 from aaronraimist/patch-1
ma1sd implements r0.3.0 of the identity server API
2020-04-05 10:20:42 +00:00
Aaron Raimist
0f89121b98 ma1sd implements r0.3.0 of the identity server API 2020-04-04 17:16:25 -05:00
Anatoliy Sablin
8a40ca185b Fix #22. 2020-03-22 12:17:33 +03:00
Anatoliy Sablin
5baeb42623 Fix #29. 2020-03-22 12:12:47 +03:00
Anatoliy Sablin
072e5f66cb #26 Use empty pepper. 2020-02-19 23:35:59 +03:00
Anatoliy Sablin
b2f41d689b #26 fix. 2020-02-19 00:36:05 +03:00
Anatoly Sablin
9b4aff58c7 Add migration documentation. 2020-01-30 23:17:01 +03:00
Anatoly Sablin
a20e41574d Update docs. Add a new options and configuration. 2020-01-28 23:20:29 +03:00
Anatoly Sablin
72977d65ae Workaround for postgresql. 2020-01-28 23:18:39 +03:00
Anatoly Sablin
7555fff1a5 Add the postgresql backend for internal storage. 2020-01-28 22:15:26 +03:00
Anatoly Sablin
aed12e5536 Add the --dump-and-exit option to exit after printing the full configuration. 2020-01-28 01:02:43 +03:00
Anatoly Sablin
75efd9921d Improve logging configuration. Introduce the root and the app log levels. 2020-01-28 00:55:39 +03:00
Anatoly Sablin
9219bd4723 Add logging configuration. Add --dump option to just print the full configuration. 2020-01-25 14:57:22 +03:00
Anatoly Sablin
73526be2ac Add configuration to use the legacy query for old synapse to get room names. 2020-01-25 14:04:40 +03:00
ma1uta
b827efca2c Merge pull request #13 from NullIsNot0/fix-room-names-patch
Fix room name retrieval after Synapse dropped table room_names
2020-01-25 10:50:55 +00:00
NullIsNot0
6b7a4c8a23 Fix room name retrieval after Synapse dropped table room_names
Recently Synapse dropped unused (by Synapse itself) table "room_names" which brakes room name retrieval for ma1sd. There is a table "room_stats_state" from which we can retrieve room name by it's ID. Note that people to people conversations do not contain room names, because they are generated on-the-fly by setting other participants names separated by word "and". That's why this query will only get names for rooms where room names are set during creation process (or changed later) and are the same for all participants.
Link to Synapse code where it drops "room_names" table: https://github.com/matrix-org/synapse/blob/master/synapse/storage/data_stores/main/schema/delta/56/drop_unused_event_tables.sql#L17
2020-01-10 18:23:29 +02:00
Anatoly Sablin
47f6239268 Add equals and hashCode methods for the MemoryThreePid. 2020-01-09 22:28:44 +03:00
ma1uta
0d6f65b469 Merge pull request #11 from NullIsNot0/master
Load DNS overwrite config on startup and remove duplicates from identity store before email notifications
2020-01-09 19:25:13 +00:00
Edgars Voroboks
be915aed94 Remove duplicates from identity store before email notifications
I use LDAP for user store. I have set up "mail" and "otherMailbox" as threepid email attributes. When people get invited to rooms, they receive 2 (sometimes 3) invitation e-mails if they have the same e-mail address in LDAP "mail" and "otherMailbox" fields. I think it's a good idea to check identity store for duplicates before sending invitation e-mails.
2020-01-09 20:14:56 +02:00
NullIsNot0
ce938bb4a5 Load DNS overwrite config on startup
I recently noticed that DNS overwrite does not happen. There are messages in logs: "No DNS overwrite for <REDACTED>", but I definitely have configured DNS overwrithng. I think it's because DNS overwriting config is not loaded when ma1sd starts up.
Documented here: https://github.com/ma1uta/ma1sd/blob/master/docs/features/authentication.md#dns-overwrite and here: https://github.com/ma1uta/ma1sd/blob/master/docs/features/directory.md#dns-overwrite
2020-01-07 22:24:26 +02:00
Anatoly Sablin
15db563e8d Add documentation. 2019-12-26 22:49:25 +03:00
Anatoly Sablin
82a538c750 Add an option to enable/disable hash lookup via the LDAP provider. 2019-12-25 22:51:44 +03:00
Anatoly Sablin
84ca8ebbd9 Add support of the MSC2134 (Identity hash lookup) for the LDAP provider. 2019-12-25 00:13:07 +03:00
Anatoly Sablin
774ebf4fa8 Fix for #9. Proper wrap the handles with the sanitize handler. 2019-12-16 22:47:24 +03:00
Anatoly Sablin
eb1326c56a Add unique id for the accepted table.
Add a little more logs.
2019-12-10 22:29:00 +03:00
Anatoly Sablin
10cdb4360e Fix homeserver verification with wildcards certificates.
Disable v2 by default.
Add migration to fix the accepted table (due to sqlite unable to change constraint, drop table and create again).
Fix displaying the expiration period of the new token.
Remove duplicated code.
Use v1 single lookup when receive the request with `none` algorithm and the only one argument.
Hide v2 endpoint if v2 API disabled.
2019-12-10 00:10:13 +03:00
Anatoly Sablin
17ebc2a421 Fix hash generation. 2019-12-06 23:15:00 +03:00
Anatoly Sablin
cbb9fced8d Clarify the documentation. Add the hash config to the example config. Uses duration in the delay field instead of the seconds. 2019-12-05 23:27:13 +03:00
Anatoly Sablin
7509174611 Add documentation. Add options to enable/disable the hash providers. Add the option for setup barrier for rotation per requests strategy. 2019-12-02 23:23:17 +03:00
Anatoly Sablin
51d9225dda Don't wrap the AcceptTermsHandler with terms checking. Clear the sql hash storage on shutdown. 2019-12-02 22:31:36 +03:00
Anatoly Sablin
6216113400 FIx terms. 2019-11-29 23:38:52 +03:00
Anatoly Sablin
cb32441959 Fix sha256 hashing. Fix v2 lookup. 2019-11-29 00:26:08 +03:00
Anatoly Sablin
0ec4df2c06 Fix bug with token expiration. Increase the default length of the pepper. Update hashes on startup with RotationPerRequest strategy. Don't check for existing pepper on the none hash algorithm. 2019-11-28 00:28:11 +03:00
Anatoly Sablin
86b880069b Wrap with the CheckTermsHandler handlers only with authorization. 2019-11-27 22:55:34 +03:00
Anatoly Sablin
a97273fe77 Wrap with the CheckTermsHandler is necessary. 2019-11-25 23:35:56 +03:00
Anatoly Sablin
f9daf4d58a Make configuration enums in lowercase. Wrap create hashes by try-catch. Add initial part of the documentation. 2019-11-15 23:39:45 +03:00
Anatoly Sablin
9e4cabb69b Fix the token expiration period. 2019-11-15 22:50:08 +03:00
Anatoly Sablin
0b81de3cd0 Make the federation homeserver resolve more accurate (on resolve via DNS record check that the certificate present for the original host). 2019-11-13 23:08:34 +03:00
Anatoly Sablin
698a16ec17 Fix matrix server hostname verification. 2019-11-11 23:48:49 +03:00
Anatoly Sablin
619b70d860 Bump gradle to 6.0. 2019-11-11 23:48:49 +03:00
Anatoly Sablin
494c9e3941 Merge branch 'MSC2140'
# Conflicts:
#	src/main/java/io/kamax/mxisd/session/SessionManager.java
2019-11-07 22:29:25 +03:00
Anatoly Sablin
0786a6520f Bump gradle version. 2019-11-07 00:16:18 +03:00
Anatoly Sablin
430136c391 Bump dependency verions. 2019-11-06 23:26:56 +03:00
Anatoly Sablin
eda4404335 MSC2140 Add populating hashes via exec identity store. 2019-11-06 23:16:27 +03:00
Anatoly Sablin
c52034b18a MSC2140 Add populating hashes via sql and memory stores. 2019-11-06 23:07:42 +03:00
Anatoly Sablin
8d346037b7 MSC2140 Add hash configuration. 2019-11-06 00:20:39 +03:00
Anatoly Sablin
14ad4435bc MSC2140 Add SQL storage for hashes and the time-based rotation policy. 2019-11-05 23:18:11 +03:00
ma1uta
94441d0446 Merge pull request #6 from ma1uta/issues/3
Allow extended character sets for backward compatibility.
2019-10-22 21:14:10 +00:00
Anatoly Sablin
b4776b50e2 https://github.com/ma1uta/ma1sd/issues/3 Allow extended character sets for backward compatibility. 2019-10-23 00:09:29 +03:00
Anatoly Sablin
2458b38b75 Add the configuration description for enable/disable unbind feature in the session.md 2019-10-22 23:54:53 +03:00
ma1uta
249e28a8b5 Merge pull request #5 from eyecreate/patch-2
Allow configuring unbind notifications to be sent or not.
2019-10-22 20:52:46 +00:00
Anatoly Sablin
8ba8756871 Fix account registration. 2019-10-21 23:48:47 +03:00
ma1uta
ba9e2d6121 Merge pull request #4 from eyecreate/patch-1
make sure destination only contains the hostname value and not whole URL
2019-10-21 20:27:33 +00:00
eyecreate
f042b82a50 add missing import 2019-10-21 16:06:23 -04:00
eyecreate
59071177ad typo 2019-10-21 15:33:28 -04:00
eyecreate
6450cd1f20 have session manager check session config for sending notifications on unbinds. 2019-10-21 15:30:46 -04:00
eyecreate
90bc244f3e update docs to something that works. 2019-10-21 15:29:55 -04:00
eyecreate
6e52a509db update session config to allow unbindin emails to not be sent. 2019-10-21 15:28:30 -04:00
eyecreate
5ca666981a make sure destination only contains the hostname value and not whole URL
When testing this, the public URL is containing the protocol "https://" which differs from synapse's values. This code makes sure to remove that extra data to signatures match. Is there ever a situation in which the public url is any different?
2019-10-21 14:31:40 -04:00
Anatoly Sablin
43fe8b1aec Add the hash lookup handler. 2019-10-18 22:52:13 +03:00
Anatoly Sablin
a0270c7d01 Add NoOp configuration. Split classes into packages. 2019-10-16 23:07:14 +03:00
Anatoly Sablin
703044d06a Add initial Hash configuration. Add the HashDetailsHandler. 2019-10-15 23:38:32 +03:00
Anatoly Sablin
add6ed8fd9 Add the TOS API. 2019-10-09 23:12:23 +03:00
Anatoly Sablin
baed894ff8 Update policy configuration. Add Handler to check that user accepts terms. 2019-10-08 00:13:40 +03:00
Anatoly Sablin
14e095a147 Add policy configuration. 2019-10-04 00:03:51 +03:00
Anatoly Sablin
bc8795e940 Add authorization handler. 2019-10-01 23:52:01 +03:00
Anatoly Sablin
5521c0c338 Add account handlers. 2019-09-30 23:53:38 +03:00
Anatoly Sablin
614b3440e2 Registration API. Add DAO, Manager. 2019-09-30 23:16:58 +03:00
Anatoly Sablin
d0fd9fb9b0 Get domain from public url. 2019-09-17 23:17:30 +03:00
Anatoly Sablin
1232e9ce79 MSC2140 MSC2134 Remove the unused path. 2019-09-01 22:38:59 +03:00
Anatoly Sablin
a47a983c10 MSC2140 MSC2134 Refactoring. Move common classes to the share package. 2019-09-01 22:33:03 +03:00
Anatoly Sablin
fbb0d7c7ba MSC2140 Mirroring V1 to V2. 2019-08-31 23:35:58 +03:00
Anatoly Sablin
f1dd309551 MSC2140 Add option to enable/disable v1 and v2 api. 2019-08-31 23:09:20 +03:00
Anatoly Sablin
36f22e5ca6 Update remarks of the fork. 2019-08-15 22:46:53 +03:00
Anatoly Sablin
a112a5e57c Improve request verification. Allow unbind only for configured matrix domain. 2019-08-07 21:47:10 +03:00
Anatoly Sablin
dbc764fe65 Add description about the MSC1915 configuration. 2019-08-05 22:15:53 +03:00
Anatoly Sablin
d5680b2dfe MSC1915. Add the option to enable/disable unbind. 2019-07-31 23:22:21 +03:00
Anatoly Sablin
5aad4fb81e MSC1915. Add unbind email notification. 2019-07-31 00:13:44 +03:00
Anatoly Sablin
a1f64f5159 Reworked MSC1915. Add request validation. 2019-07-27 15:51:01 +03:00
Anatoly Sablin
a96920f533 Add migration guide. 2019-07-21 23:44:42 +03:00
Anatoly Sablin
9ca2ebdad0 Bump dependencies. 2019-07-21 18:25:35 +03:00
Anatoly Sablin
7f284ac71e Add gradle-version-plugin to track dependencies updates. 2019-07-21 18:25:35 +03:00
Anatoly Sablin
4d488a3fc8 Add openjdk-11 dependency. 2019-07-21 18:25:35 +03:00
Anatoly Sablin
7ee3e19de4 Change app name in logs. 2019-07-21 17:48:52 +03:00
Anatoly Sablin
608938c084 Fix links. 2019-07-16 00:14:57 +03:00
Anatoly Sablin
e6fec9199d Rename config file, parameters, application name, package. 2019-07-11 22:26:20 +03:00
Anatoly Sablin
c3262a9f25 Merge the matrix-java-sdk due to it no longer maintained. Remove thirdparty repositories. 2019-07-07 23:13:59 +03:00
Anatoly Sablin
136563c61a Rename project. 2019-06-28 22:50:31 +03:00
Anatoly Sablin
3043cd4e61 Fork! 2019-06-27 00:07:44 +03:00
Max Dor
21d9d0fda1 The End 2019-06-25 11:36:32 +02:00
Max Dor
a964b073bf Restart mxisd service on Debian package upgrade/install if possible 2019-06-12 00:18:25 +02:00
Max Dor
f85345bc97 Update code and links following Matrix 1.0 release
- Support 3PID unbind via 3PID sessions
2019-06-12 00:17:43 +02:00
Max Dor
29603682e5 Clarify how to serve static assets for 3PID session views 2019-06-04 17:06:25 +02:00
Max Dor
d54f1dcb88 Fix various typos in the Registration feature docs 2019-05-30 17:29:47 +02:00
Max Dor
92f10347d1 Fix #123 2019-05-30 14:18:11 +02:00
Max Dor
0298f66212 Fix #128 2019-05-30 13:58:40 +02:00
Max Dor
0ddd086bda Fix response body of /3pid/bind to match spec
- synapse did not check/validate the response as per spec until 0.99.5 it seems
- mxisd was never compliant also
2019-05-30 13:26:38 +02:00
Max Dor
544f8e59f0 Add check for legality of the returned Matrix ID in Auth
- Helps troubleshoot reported issues that might not be obvious at first
- Add basic unit test for auth manager
2019-05-28 19:28:46 +02:00
Max Dor
917f87bf8c Fix broken HTML tag in 3PID template 2019-05-28 16:01:01 +02:00
Max Dor
774795c203 Fix various logging/variable scopes 2019-05-27 17:12:52 +02:00
Max Dor
27b2976e42 Provide URL encoded placeholders in notification template for 3PID data 2019-05-18 02:20:13 +02:00
Max Dor
f16f184253 Minor internal changes
- Fix log statement to include expected value
- Change access level to method
2019-05-18 01:57:40 +02:00
354 changed files with 15496 additions and 1909 deletions

View File

@@ -0,0 +1,71 @@
# For most projects, this workflow file will not need changing; you simply need
# to commit it to your repository.
#
# You may wish to alter this file to override the set of languages analyzed,
# or to provide custom queries or build logic.
name: "CodeQL"
on:
push:
branches: [master]
pull_request:
# The branches below must be a subset of the branches above
branches: [master]
schedule:
- cron: '0 3 * * 6'
jobs:
analyze:
name: Analyze
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
# Override automatic language detection by changing the below list
# Supported options are ['csharp', 'cpp', 'go', 'java', 'javascript', 'python']
language: ['java']
# Learn more...
# https://docs.github.com/en/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#overriding-automatic-language-detection
steps:
- name: Checkout repository
uses: actions/checkout@v2
with:
# We must fetch at least the immediate parents so that if this is
# a pull request then we can checkout the head.
fetch-depth: 0
# If this run was triggered by a pull request event, then checkout
# the head of the pull request instead of the merge commit.
- run: git checkout HEAD^2
if: ${{ github.event_name == 'pull_request' }}
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v2
with:
languages: ${{ matrix.language }}
# If you wish to specify custom queries, you can do so here or in a config file.
# By default, queries listed here will override any specified in a config file.
# Prefix the list here with "+" to use these queries and those in the config file.
# queries: ./path/to/local/query, your-org/your-repo/queries@main
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
# If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild
uses: github/codeql-action/autobuild@v2
# Command-line programs to run using the OS shell.
# 📚 https://git.io/JvXDl
# ✏️ If the Autobuild fails above, remove it and uncomment the following three lines
# and modify them (or add more) to build your code if your project
# uses a compiled language
#- run: |
# make bootstrap
# make release
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v1

4
.gitignore vendored
View File

@@ -7,8 +7,8 @@ out/
.idea/
# Local dev config
/mxisd.yaml
/mxids.yaml
/application.yaml
# Local dev storage
/mxisd.db
/mxids.db

View File

@@ -1,18 +1,36 @@
FROM openjdk:8-jre-alpine
# Use a specific version of OpenJDK based on Debian ("bullseye" in this case)
FROM --platform=$BUILDPLATFORM openjdk:21-jdk-bullseye AS builder
RUN apk update && apk add bash && rm -rf /var/lib/apk/* /var/cache/apk/*
# Replace 'apk' commands with 'apt-get' for Debian-based package management.
# Install required packages such as 'git' and 'gradle'. Remember to update and clean up properly.
RUN apt-get update && \
apt-get install -y gradle git && \
rm -rf /var/lib/apt/lists/*
VOLUME /etc/mxisd
VOLUME /var/mxisd
WORKDIR /mxids
COPY . .
RUN ./gradlew shadowJar
# Second stage: Setup the runtime container
FROM openjdk:21-jdk-bullseye
# Again, switch to 'apt-get' for installing 'bash'. Clean up to keep the image size down.
RUN apt-get update && \
apt-get install -y bash && \
rm -rf /var/lib/apt/lists/*
VOLUME /etc/mxids
VOLUME /var/mxids
EXPOSE 8090
ENV JAVA_OPTS=""
ENV CONF_FILE_PATH="/etc/mxisd/mxisd.yaml"
ENV SIGN_KEY_PATH="/var/mxisd/sign.key"
ENV SQLITE_DATABASE_PATH="/var/mxisd/mxisd.db"
ENV CONF_FILE_PATH="/etc/mxids/mxids.yaml"
ENV SIGN_KEY_PATH="/var/mxids/sign.key"
ENV SQLITE_DATABASE_PATH="/var/mxids/mxids.db"
CMD [ "/start.sh" ]
# It's usually a good practice to use 'COPY' instead of 'ADD' for local files unless you need the extra capabilities of 'ADD' (like auto-extracting tar files).
COPY src/docker/start.sh /start.sh
COPY src/script/mxids /app/mxids
COPY --from=builder /mxids/build/libs/mxids.jar /app/mxids.jar
ADD src/docker/start.sh /start.sh
ADD src/script/mxisd /app/mxisd
ADD build/libs/mxisd.jar /app/mxisd.jar
CMD ["/start.sh"]

16
DockerfileX Normal file
View File

@@ -0,0 +1,16 @@
FROM --platform=$BUILDPLATFORM openjdk:11.0.16-jre-slim
VOLUME /etc/mxids
VOLUME /var/mxids
EXPOSE 8090
ENV JAVA_OPTS=""
ENV CONF_FILE_PATH="/etc/mxids/mxids.yaml"
ENV SIGN_KEY_PATH="/var/mxids/sign.key"
ENV SQLITE_DATABASE_PATH="/var/mxids/mxids.db"
CMD [ "/start.sh" ]
ADD src/docker/start.sh /start.sh
ADD src/script/mxids /app/mxids
ADD build/libs/mxids.jar /app/mxids.jar

View File

@@ -1,6 +1,6 @@
mxisd - Federated Matrix Identity Server
ma1sd - Federated Matrix Identity Server
----------------------------------------
![Travis-CI build status](https://travis-ci.org/kamax-matrix/mxisd.svg?branch=master)
![Travis-CI build status](https://travis-ci.org/ma1uta/ma1sd.svg?branch=master)
- [Overview](#overview)
- [Features](#features)
@@ -8,22 +8,30 @@ mxisd - Federated Matrix Identity Server
- [Getting Started](#getting-started)
- [Support](#support)
- [Contribute](#contribute)
- [Powered by mxisd](#powered-by-mxisd)
- [Powered by ma1sd](#powered-by-ma1sd)
- [FAQ](#faq)
- [Migration from mxisd](#migration-from-mxisd)
- [Contact](#contact)
---
* This project is a fork (not successor) of the https://github.com/kamax-matrix/mxisd, which has been archived and no longer maintained as a standalone product.
Also, ma1sd is supported by the volunteer not developers of the original project.
---
# Overview
mxisd is a Federated Matrix Identity server for self-hosted Matrix infrastructures with [enhanced features](#features).
As an enhanced Identity service, it implements the [Identity service API](https://matrix.org/docs/spec/identity_service/r0.1.0.html)
ma1sd is a Federated Matrix Identity server for self-hosted Matrix infrastructures with [enhanced features](#features).
As an enhanced Identity service, it implements the [Identity service API](https://matrix.org/docs/spec/identity_service/r0.2.0.html)
and several [extra features](#features) that greatly enhance user experience within Matrix.
It is the one stop shop for anything regarding Authentication, Directory and Identity management in Matrix built in a
single coherent product.
mxisd is specifically designed to connect to an existing on-premise Identity store (AD/Samba/LDAP, SQL Database,
Web services/app, etc.) and ease the integration of a Matrix infrastructure within an existing one.
Check [our FAQ entry](docs/faq.md#what-kind-of-setup-is-mxisd-really-designed-for) to know if mxisd is a good fit for you.
The core principle of mxisd is to map between Matrix IDs and 3PIDs (Third-Party IDentifiers) for the Homeserver and its
ma1sd is specifically designed to connect to an existing on-premise Identity store (AD/Samba/LDAP, SQL Database,
Web services/app, etc.) and ease the integration of a Matrix infrastructure within an existing one.
Check [our FAQ entry](docs/faq.md#what-kind-of-setup-is-ma1sd-really-designed-for) to know if ma1sd is a good fit for you.
The core principle of ma1sd is to map between Matrix IDs and 3PIDs (Third-Party IDentifiers) for the Homeserver and its
users. 3PIDs can be anything that uniquely and globally identify a user, like:
- Email address
- Phone number
@@ -34,15 +42,15 @@ users. 3PIDs can be anything that uniquely and globally identify a user, like:
If you are unfamiliar with the Identity vocabulary and concepts in Matrix, **please read this [introduction](docs/concepts.md)**.
# Features
[Identity](docs/features/identity.md): As a [regular Matrix Identity service](https://matrix.org/docs/spec/identity_service/r0.1.0.html#general-principles):
[Identity](docs/features/identity.md): As a [regular Matrix Identity service](https://matrix.org/docs/spec/identity_service/r0.2.0.html#general-principles):
- Search for people by 3PID using its own Identity stores
([Spec](https://matrix.org/docs/spec/identity_service/r0.1.0.html#association-lookup))
([Spec](https://matrix.org/docs/spec/identity_service/r0.2.0.html#association-lookup))
- Invite people to rooms by 3PID using its own Identity stores, with notifications to the invitee (Email, SMS, etc.)
([Spec](https://matrix.org/docs/spec/identity_service/r0.1.0.html#post-matrix-identity-api-v1-store-invite))
- Allow users to add 3PIDs to their settings/profile
([Spec](https://matrix.org/docs/spec/identity_service/r0.1.0.html#establishing-associations))
([Spec](https://matrix.org/docs/spec/identity_service/r0.2.0.html#invitation-storage))
- Allow users to add/remove 3PIDs to their settings/profile via 3PID sessions
([Spec](https://matrix.org/docs/spec/identity_service/r0.2.0.html#establishing-associations))
- Register accounts on your Homeserver with 3PIDs
([Spec](https://matrix.org/docs/spec/identity_service/r0.1.0.html#establishing-associations))
([Spec](https://matrix.org/docs/spec/identity_service/r0.2.0.html#establishing-associations))
As an enhanced Identity service:
- [Federation](docs/features/federation.md): Use a recursive lookup mechanism when searching and inviting people by 3PID,
@@ -69,7 +77,7 @@ As an enhanced Identity service:
- Users can directly find each other using whatever attribute is relevant within your Identity store
- Federate your Identity server so you can discover others and/or others can discover you
Also, check [our FAQ entry](docs/faq.md#what-kind-of-setup-is-mxisd-really-designed-for) to know if mxisd is a good fit for you.
Also, check [our FAQ entry](docs/faq.md#what-kind-of-setup-is-ma1sd-really-designed-for) to know if ma1sd is a good fit for you.
# Getting started
See the [dedicated document](docs/getting-started.md)
@@ -79,38 +87,33 @@ See the [dedicated document](docs/getting-started.md)
A basic troubleshooting guide is available [here](docs/troubleshooting.md).
## Community
Over Matrix: [#mxisd:kamax.io](https://matrix.to/#/#mxisd:kamax.io) ([Preview](https://view.matrix.org/room/!NPRUEisLjcaMtHIzDr:kamax.io/))
Over Matrix: [#ma1sd:ru-matrix.org](https://matrix.to/#/#ma1sd:ru-matrix.org) ([Preview](https://view.matrix.org/room/!CxwBdgAlaphCARnKTA:ru-matrix.org/))
## Commercial
If you would prefer professional support/custom development for mxisd and/or for Matrix in general, including other open
source technologies/products:
- Visit our [website](https://www.kamax.io/) to get in touch with us and get a quote.
- Come in our general Matrix room: [#kamax-matrix:kamax.io](https://matrix.to/#/#kamax-matrix:kamax.io)
Sorry, I cannot provide commercial support (at least now). But always try to help you.
Don't hesitate to ask about project and feel free to create issues at https://github.com/ma1uta/ma1sd
# Contribute
You can contribute as a community member by:
- Giving us feedback about your usage of mxisd, even if it seems unimportant or if all is working well!
- Opening issues for any weird behaviour or bug. mxisd should feel natural, let us know if it does not!
- Giving us feedback about your usage of ma1sd, even if it seems unimportant or if all is working well!
- Opening issues for any weird behaviour or bug. ma1sd should feel natural, let us know if it does not!
- Helping us improve the documentation: tell us what is good or not good (in an issue or in Matrix), or make a PR with
changes you feel improve the doc.
- Contribute code directly: we love contributors! All your contributions will be licensed under AGPLv3.
- [Donate!](https://liberapay.com/maximusdor/) Any donation is welcome, regardless how small or big, and will directly
be used for the fixed costs and developer time of mxisd.
You can contribute as an organisation/corporation by:
- Get a [support contract](#commercial). This is the best way you can help us as it ensures mxisd is
maintained regularly and you get direct access to the support team.
- Sponsoring new features or bug fixes. [Get in touch](#contact) so we can discuss it further.
# Powered by mxisd
The following projects use mxisd under the hood for some or all their features. Check them out!
# Powered by ma1sd
The following projects can use ma1sd under the hood for some or all their features. Check them out!
- [matrix-docker-ansible-deploy](https://github.com/spantaleev/matrix-docker-ansible-deploy)
- [matrix-register-bot](https://github.com/krombel/matrix-register-bot)
# FAQ
See the [dedicated document](docs/faq.md)
# Migration from mxisd
See the [migration guide](docs/migration-from-mxisd.md)
# Contact
Get in touch via:
- Matrix: [#mxisd:kamax.io](https://matrix.to/#/#mxisd:kamax.io)
- Email: see our website: [Kamax.io](https://www.kamax.io)
- Matrix: [#ma1sd:ru-matrix.org](https://matrix.to/#/#ma1sd:ru-matrix.org)

View File

@@ -1,5 +1,5 @@
/*
* mxisd - Matrix Identity Server Daemon
* mxids - Matrix Identity Server
* Copyright (C) 2017 Kamax Sarl
*
* https://www.kamax.io/
@@ -20,21 +20,22 @@
import java.util.regex.Pattern
apply plugin: 'java'
apply plugin: 'java-library'
apply plugin: 'application'
apply plugin: 'com.github.johnrengelman.shadow'
apply plugin: 'idea'
apply plugin: 'com.github.ben-manes.versions'
def confFileName = "mxisd.example.yaml"
def confFileName = "mxids.example.yaml"
def distDir = "${project.buildDir}/dist"
def debBinPath = "/usr/lib/mxisd"
def debConfPath = "/etc/mxisd"
def debDataPath = "/var/lib/mxisd"
def debBinPath = "/usr/lib/mxids"
def debConfPath = "/etc/mxids"
def debDataPath = "/var/lib/mxids"
def debSystemdPath = "/etc/systemd/system"
def debConfFileName = confFileName
def debStartScriptFilename = "mxisd"
def debStartScriptFilename = "mxids"
def debBuildBasePath = "${project.buildDir}/tmp/debian"
def debBuildDebianPath = "${debBuildBasePath}/DEBIAN"
@@ -43,18 +44,18 @@ def debBuildConfPath = "${debBuildBasePath}${debConfPath}"
def debBuildDataPath = "${debBuildBasePath}${debDataPath}"
def debBuildSystemdPath = "${debBuildBasePath}${debSystemdPath}"
def dockerImageName = "kamax/mxisd"
def dockerImageTag = "${dockerImageName}:${mxisdVersion()}"
def dockerImageName = "cqrenet/mxids"
def dockerImageTag = "${dockerImageName}:${mxidsVersion()}"
group = 'io.kamax'
mainClassName = 'io.kamax.mxisd.MxisdStandaloneExec'
sourceCompatibility = '1.8'
targetCompatibility = '1.8'
sourceCompatibility = '11'
targetCompatibility = '11'
String mxisdVersion() {
String mxidsVersion() {
def versionPattern = Pattern.compile("v(\\d+\\.)?(\\d+\\.)?(\\d+)(-.*)?")
String version = System.getenv('MXISD_BUILD_VERSION')
String version = System.getenv('MXIDS_BUILD_VERSION')
if (version == null || version.size() == 0) {
version = gitVersion()
}
@@ -72,108 +73,114 @@ String gitVersion() {
buildscript {
repositories {
jcenter()
gradlePluginPortal()
mavenCentral()
google()
}
dependencies {
classpath 'com.github.jengelman.gradle.plugins:shadow:4.0.3'
classpath 'com.github.johnrengelman:shadow:8.1.1'
classpath 'com.github.ben-manes:gradle-versions-plugin:0.52.0'
}
}
repositories {
jcenter()
maven { url "https://kamax.io/maven/releases/" }
maven { url "https://kamax.io/maven/snapshots/" }
mavenCentral()
}
dependencies {
// Logging
compile 'org.slf4j:slf4j-simple:1.7.25'
api 'org.slf4j:slf4j-simple:2.0.13'
// Easy file management
compile 'commons-io:commons-io:2.5'
api 'commons-io:commons-io:2.20.0'
// Config management
compile 'org.yaml:snakeyaml:1.23'
api 'org.yaml:snakeyaml:1.33'
// Matrix Java SDK
compile 'io.kamax:matrix-java-sdk:0.0.14-8-g0e57ec6'
// Dependencies from old Matrix-java-sdk
api 'org.apache.commons:commons-lang3:3.18.0'
api 'com.squareup.okhttp3:okhttp:4.12.0'
api 'commons-codec:commons-codec:1.19.0'
// ORMLite
compile 'com.j256.ormlite:ormlite-jdbc:5.0'
api 'com.j256.ormlite:ormlite-jdbc:6.1'
// ed25519 handling
compile 'net.i2p.crypto:eddsa:0.1.0'
api 'net.i2p.crypto:eddsa:0.3.0'
// LDAP connector
compile 'org.apache.directory.api:api-all:1.0.0'
api 'org.apache.directory.api:api-all:2.1.7'
// DNS lookups
compile 'dnsjava:dnsjava:2.1.8'
api 'dnsjava:dnsjava:3.6.3'
// HTTP connections
compile 'org.apache.httpcomponents:httpclient:4.5.3'
api 'org.apache.httpcomponents:httpclient:4.5.14'
// Phone numbers validation
compile 'com.googlecode.libphonenumber:libphonenumber:8.7.1'
api 'com.googlecode.libphonenumber:libphonenumber:8.13.36'
// E-mail sending
compile 'javax.mail:javax.mail-api:1.6.2'
compile 'com.sun.mail:javax.mail:1.6.2'
api 'javax.mail:javax.mail-api:1.6.2'
api 'com.sun.mail:javax.mail:1.6.2'
// Google Firebase Authentication backend
compile 'com.google.firebase:firebase-admin:5.3.0'
api 'com.google.firebase:firebase-admin:9.2.0'
// Connection Pool
compile 'com.mchange:c3p0:0.9.5.2'
api 'com.mchange:c3p0:0.11.2'
// SQLite
compile 'org.xerial:sqlite-jdbc:3.20.0'
api 'org.xerial:sqlite-jdbc:3.50.3.0'
// PostgreSQL
compile 'org.postgresql:postgresql:42.2.5'
api 'org.postgresql:postgresql:42.7.7'
// MariaDB/MySQL
compile 'org.mariadb.jdbc:mariadb-java-client:2.1.2'
api 'org.mariadb.jdbc:mariadb-java-client:3.5.6'
// UNIX sockets
api 'com.kohlschutter.junixsocket:junixsocket-core:2.9.1'
// Twilio SDK for SMS
compile 'com.twilio.sdk:twilio:7.14.5'
api 'com.twilio.sdk:twilio:10.9.2'
// SendGrid SDK to send emails from GCE
compile 'com.sendgrid:sendgrid-java:2.2.2'
api 'com.sendgrid:sendgrid-java:4.10.2'
// ZT-Exec for exec identity store
compile 'org.zeroturnaround:zt-exec:1.10'
api 'org.zeroturnaround:zt-exec:1.12'
// HTTP server
compile 'io.undertow:undertow-core:2.0.16.Final'
api 'io.undertow:undertow-core:2.3.13.Final'
// Command parser for AS interface
implementation 'commons-cli:commons-cli:1.4'
api 'commons-cli:commons-cli:1.7.0'
testCompile 'junit:junit:4.12'
testCompile 'com.github.tomakehurst:wiremock:2.8.0'
testCompile 'com.unboundid:unboundid-ldapsdk:4.0.9'
testCompile 'com.icegreen:greenmail:1.5.9'
testImplementation 'junit:junit:4.13.2'
testImplementation 'com.github.tomakehurst:wiremock:3.0.1'
testImplementation 'com.unboundid:unboundid-ldapsdk:7.0.0'
testImplementation 'com.icegreen:greenmail:1.6.15'
}
jar {
manifest {
attributes(
'Implementation-Version': mxisdVersion()
'Implementation-Version': mxidsVersion()
)
}
}
shadowJar {
baseName = project.name
classifier = null
version = null
archiveBaseName.set(project.name)
archiveClassifier.set('') // Set to an empty string if you don't need a classifier.
archiveVersion.set('') // Set to an empty string if you don't want the version in the jar name.
}
task debBuild(dependsOn: shadowJar) {
doLast {
String debVersion = mxisdVersion()
String debVersion = mxidsVersion()
println "Version for package: ${debVersion}"
mkdir distDir
mkdir debBuildBasePath
@@ -184,7 +191,7 @@ task debBuild(dependsOn: shadowJar) {
mkdir debBuildSystemdPath
copy {
from "${project.buildDir}/libs/mxisd.jar"
from "${project.buildDir}/libs/mxids.jar"
into debBuildBinPath
}
@@ -229,9 +236,15 @@ task debBuild(dependsOn: shadowJar) {
value: debDataPath
)
ant.replace(
file: "${debBuildDebianPath}/postinst",
token: '%DEB_CONF_FILE%',
value: "${debConfPath}/mxids.yaml"
)
ant.chmod(
file: "${debBuildDebianPath}/postinst",
perm: 'a+x'
perm: '0755'
)
ant.chmod(
@@ -240,7 +253,7 @@ task debBuild(dependsOn: shadowJar) {
)
copy {
from "${project.file('src/systemd/mxisd.service')}"
from "${project.file('src/systemd/mxids.service')}"
into debBuildSystemdPath
}
@@ -256,7 +269,7 @@ task debBuild(dependsOn: shadowJar) {
}
}
task dockerBuild(type: Exec, dependsOn: shadowJar) {
task dockerBuild(type: Exec) {
commandLine 'docker', 'build', '-t', dockerImageTag, project.rootDir
doLast {
@@ -266,6 +279,15 @@ task dockerBuild(type: Exec, dependsOn: shadowJar) {
}
}
task dockerBuildX(type: Exec, dependsOn: shadowJar) {
commandLine 'docker', 'buildx', 'build', '--push', '--platform', 'linux/arm64,linux/amd64,linux/arm/v7', '-t', dockerImageTag , project.rootDir
doLast {
exec {
commandLine 'docker', 'buildx', 'build', '--push', '--platform', 'linux/arm64,linux/amd64,linux/arm/v7', '-t', "${dockerImageName}:latest-dev", project.rootDir
}
}
}
task dockerPush(type: Exec) {
commandLine 'docker', 'push', dockerImageTag
@@ -275,3 +297,33 @@ task dockerPush(type: Exec) {
}
}
}
task dockerPushX(type: Exec) {
commandLine 'docker', 'push', dockerImageTag
doLast {
exec {
commandLine 'docker', 'push', "${dockerImageName}:latest-dev"
commandLine 'docker', 'push', "${dockerImageName}:latest-amd64-dev"
commandLine 'docker', 'push', "${dockerImageName}:latest-arm64-dev"
}
}
}
tasks.named('assemble').configure {
dependsOn shadowJar
}
tasks.withType(AbstractArchiveTask) {
if (it.name == 'distZip' || it.name == 'distTar') {
dependsOn shadowJar
}
}
tasks.named('startScripts').configure {
mustRunAfter shadowJar
}
tasks.named('startShadowScripts').configure {
dependsOn jar
}

146
docs/MSC2140_MSC2134.md Normal file
View File

@@ -0,0 +1,146 @@
# MSC2140
## V1 vs V2
In the [MSC2140](https://github.com/matrix-org/matrix-doc/pull/2140) the v2 prefix was introduced.
Default values:
```.yaml
matrix:
v1: true # deprecated
v2: false
```
To disable change value to `false`.
NOTE: the v1 is deprecated, therefore recommend to use only v2 and disable v1 (default value can be ommited):
```.yaml
matrix:
v1: false
```
NOTE: Riot Web version 1.5.5 and below checks the v1 for backward compatibility.
NOTE: v2 disabled by default in order to preserve backward compatibility.
## Terms
###### Requires: No.
Administrator can omit terms configuration. In this case the terms checking will be disabled.
Example:
```.yaml
policy:
policies:
term_name: # term name
version: 1.0 # version
terms:
en: # lang
name: term name en # localized name
url: https://ma1sd.host.tld/term_en.html # localized url
fe: # lang
name: term name fr # localized name
url: https://ma1sd.host.tld/term_fr.html # localized url
regexp:
- '/_matrix/identity/v2/account.*'
- '/_matrix/identity/v2/hash_details'
- '/_matrix/identity/v2/lookup'
```
Where:
- `term_name` -- name of the terms.
- `version` -- the terms version.
- `lang` -- the term language.
- `name` -- the name of the term.
- `url` -- the url of the term. Might be any url (i.e. from another host) for a html page.
- `regexp` -- regexp patterns for API which should be available only after accepting the terms.
API will be checks for accepted terms only with authorization.
There are the next API:
- [`GET /_matrix/identity/v2/account`](https://matrix.org/docs/spec/identity_service/r0.3.0#get-matrix-identity-v2-account) - Gets information about what user owns the access token used in the request.
- [`POST /_matrix/identity/v2/account/logout`](https://matrix.org/docs/spec/identity_service/r0.3.0#post-matrix-identity-v2-account-logout) - Logs out the access token, preventing it from being used to authenticate future requests to the server.
- [`GET /_matrix/identity/v2/hash_details`](https://matrix.org/docs/spec/identity_service/r0.3.0#get-matrix-identity-v2-hash-details) - Gets parameters for hashing identifiers from the server. This can include any of the algorithms defined in this specification.
- [`POST /_matrix/identity/v2/lookup`](https://matrix.org/docs/spec/identity_service/r0.3.0#post-matrix-identity-v2-lookup) - Looks up the set of Matrix User IDs which have bound the 3PIDs given, if bindings are available. Note that the format of the addresses is defined later in this specification.
- [`POST /_matrix/identity/v2/validate/email/requestToken`](https://matrix.org/docs/spec/identity_service/r0.3.0#post-matrix-identity-v2-validate-email-requesttoken) - Create a session for validating an email address.
- [`POST /_matrix/identity/v2/validate/email/submitToken`](https://matrix.org/docs/spec/identity_service/r0.3.0#post-matrix-identity-v2-validate-email-submittoken) - Validate ownership of an email address.
- [`GET /_matrix/identity/v2/validate/email/submitToken`](https://matrix.org/docs/spec/identity_service/r0.3.0#get-matrix-identity-v2-validate-email-submittoken) - Validate ownership of an email address.
- [`POST /_matrix/identity/v2/validate/msisdn/requestToken`](https://matrix.org/docs/spec/identity_service/r0.3.0#post-matrix-identity-v2-validate-msisdn-requesttoken) - Create a session for validating a phone number.
- [`POST /_matrix/identity/v2/validate/msisdn/submitToken`](https://matrix.org/docs/spec/identity_service/r0.3.0#post-matrix-identity-v2-validate-msisdn-submittoken) - Validate ownership of a phone number.
- [`GET /_matrix/identity/v2/validate/msisdn/submitToken`](https://matrix.org/docs/spec/identity_service/r0.3.0#get-matrix-identity-v2-validate-msisdn-submittoken) - Validate ownership of a phone number.
- [`GET /_matrix/identity/v2/3pid/getValidated3pid`](https://matrix.org/docs/spec/identity_service/r0.3.0#get-matrix-identity-v2-3pid-getvalidated3pid) - Determines if a given 3pid has been validated by a user.
- [`POST /_matrix/identity/v2/3pid/bind`](https://matrix.org/docs/spec/identity_service/r0.3.0#post-matrix-identity-v2-3pid-bind) - Publish an association between a session and a Matrix user ID.
- [`POST /_matrix/identity/v2/3pid/unbind`](https://matrix.org/docs/spec/identity_service/r0.3.0#post-matrix-identity-v2-3pid-unbind) - Remove an association between a session and a Matrix user ID.
- [`POST /_matrix/identity/v2/store-invite`](https://matrix.org/docs/spec/identity_service/r0.3.0#post-matrix-identity-v2-store-invite) - Store pending invitations to a user's 3pid.
- [`POST /_matrix/identity/v2/sign-ed25519`](https://matrix.org/docs/spec/identity_service/r0.3.0#post-matrix-identity-v2-sign-ed25519) - Sign invitation details.
There is only one exception: [`POST /_matrix/identity/v2/terms`](https://matrix.org/docs/spec/identity_service/r0.3.0#post-matrix-identity-v2-terms) which uses for accepting the terms and requires the authorization.
## [Hash lookup](https://github.com/matrix-org/matrix-doc/blob/hs/hash-identity/proposals/2134-identity-hash-lookup.md)
Hashes and the pepper updates together according to the `rotationPolicy`.
###### Requires: No.
In case the `none` algorithms ma1sd will be lookup using the v1 bulk API.
```.yaml
hashing:
enabled: true # enable or disable the hash lookup MSC2140 (default is false)
pepperLength: 20 # length of the pepper value (default is 20)
rotationPolicy: per_requests # or `per_seconds` how often the hashes will be updating
hashStorageType: sql # or `in_memory` where the hashes will be stored
algorithms:
- none # the same as v1 bulk lookup
- sha256 # hash the 3PID and pepper.
delay: 2m # how often hashes will be updated if rotation policy = per_seconds (default is 10s)
requests: 10 # how many lookup requests will be performed before updating hashes if rotation policy = per_requests (default is 10)
```
When enabled and client requests the `none` algorithms then hash lookups works as v1 bulk lookup.
Delay specified in the format: `2d 4h 12m 34s` - this means 2 days 4 hours 12 minutes and 34 seconds. Zero units may be omitted. For example:
- 12s - 12 seconds
- 3m - 3 minutes
- 5m 6s - 5 minutes and 6 seconds
- 6h 3s - 6 hours and 3 seconds
Sha256 algorithm supports only sql, memory and exec 3PID providers.
For sql provider (i.e. for the `synapseSql`):
```.yaml
synapseSql:
lookup:
query: 'select user_id as mxid, medium, address from user_threepid_id_server' # query for retrive 3PIDs for hashes.
```
For general sql provider:
```.yaml
sql:
lookup:
query: 'select user as mxid, field1 as medium, field2 as address from some_table' # query for retrive 3PIDs for hashes.
```
Each query should return the `mxid`, `medium` and `address` fields.
For memory providers:
```.yaml
memory:
hashEnabled: true # enable the hash lookup (defaults is false)
```
For exec providers:
```.yaml
exec:
identity:
hashEnabled: true # enable the hash lookup (defaults is false)
```
For ldap providers:
```.yaml
ldap:
lookup: true
```
NOTE: Federation requests work only with `none` algorithms.

View File

@@ -16,7 +16,7 @@ TCP 443
+<---------------------------------<+
|
| +-------------------+
TCP 8090 +-> | mxisd |
TCP 8090 +-> | mxids |
| |
| - Profile's 3PIDs |
| - 3PID Invites |
@@ -25,7 +25,7 @@ TCP 443
TCP 443
| +------------------------+
| | Remote Federated |
| | mxisd servers |
| | ma1sd servers |
| | |
+--> - 3PID Invites |
+------------------------+

View File

@@ -1,28 +1,32 @@
# From source
- [Binaries](#binaries)
- [Requirements](#requirements)
- [Build](#build)
- [Debian package](#debian-package)
- [Docker image](#docker-image)
- [Next steps](#next-steps)
- [From source](#from-source)
- [Binaries](#binaries)
- [Requirements](#requirements)
- [Build](#build)
- [Debian package](#debian-package)
- [Docker image](#docker-image)
- [Multi-platform builds](#multi-platform-builds)
- [Next steps](#next-steps)
## Binaries
### Requirements
- JDK 1.8
- OpenJDK 11
- OpenJDK 14
### Build
```bash
git clone https://github.com/kamax-matrix/mxisd.git
cd mxisd
git clone https://github.com/ma1uta/ma1sd.git
cd ma1sd
./gradlew build
```
Create a new configuration file by coping `mxisd.example.yaml` to `mxisd.yaml` and edit to your needs.
Create a new configuration file by coping `mxids.example.yaml` to `mxids.yaml` and edit to your needs.
For advanced configuration, see the [Configure section](configure.md).
Start the server in foreground to validate the build and configuration:
```bash
java -jar build/libs/mxisd.jar
java -jar build/libs/ma1sd.jar
```
Ensure the signing key is available:
@@ -34,9 +38,9 @@ $ curl 'http://localhost:8090/_matrix/identity/api/v1/pubkey/ed25519:0'
Test basic recursive lookup (requires Internet connection with access to TCP 443):
```bash
$ curl 'http://localhost:8090/_matrix/identity/api/v1/lookup?medium=email&address=mxisd-federation-test@kamax.io'
$ curl 'http://localhost:8090/_matrix/identity/api/v1/lookup?medium=email&address=ma1sd-federation-test@kamax.io'
{"address":"mxisd-federation-test@kamax.io","medium":"email","mxid":"@mxisd-lookup-test:kamax.io",...}
{"address":"ma1sd-federation-test@kamax.io","medium":"email","mxid":"@ma1sd-lookup-test:kamax.io",...}
```
If you enabled LDAP, you can also validate your config with a similar request after replacing the `address` value with
@@ -56,7 +60,7 @@ Requirements:
- fakeroot
- dpkg-deb
[Build mxisd](#build) then:
[Build ma1sd](#build) then:
```bash
./gradlew debBuild
```
@@ -64,11 +68,19 @@ You will find the debian package in `build/dist`.
Then follow the instruction in the [Debian package](install/debian.md) document.
## Docker image
[Build mxisd](#build) then:
[Build ma1sd](#build) then:
```bash
./gradlew dockerBuild
```
Then follow the instructions in the [Docker install](install/docker.md#configure) document.
### Multi-platform builds
Provided with experimental docker feature [buildx](https://docs.docker.com/buildx/working-with-buildx/)
To build the arm64 and amd64 images run:
```bash
./gradlew dockerBuildX
```
## Next steps
- [Integrate with your infrastructure](getting-started.md#integrate)

View File

@@ -1,6 +1,6 @@
# Concepts
- [Matrix](#matrix)
- [mxisd](#mxisd)
- [ma1sd](#ma1sd)
## Matrix
The following concepts are part of the Matrix ecosystem and specification.
@@ -15,7 +15,7 @@ A 3PID is a globally unique canonical identifier which is made of:
- Medium, which describes what network it belongs to (Email, Phone, Twitter, Discord, etc.)
- Address, the actual value people typically use on a daily basis.
mxisd core mission is to map those identifiers to Matrix User IDs.
ma1sd core mission is to map those identifiers to Matrix User IDs.
### Homeserver
Where a user **account and data** are stored.
@@ -34,10 +34,10 @@ An Identity server:
### 3PID session
The fact to validate a 3PID (email, phone number, etc.) via the introduction of a token which was sent to the 3PID address.
## mxisd
The following concepts are specific to mxisd.
## ma1sd
The following concepts are specific to ma1sd.
### Identity store
Where your user accounts and 3PID mappings are stored.
mxisd itself **DOES NOT STORE** user accounts or 3PID mappings.
ma1sd itself **DOES NOT STORE** user accounts or 3PID mappings.

View File

@@ -41,13 +41,70 @@ matrix:
Create a list under the label `myOtherServers` containing two Identity servers: `https://other1.example.org` and `https://other2.example.org`.
## Server
- `server.name`: Public hostname of mxisd, if different from the Matrix domain.
- `server.name`: Public hostname of ma1sd, if different from the Matrix domain.
- `server.port`: HTTP port to listen on (unencrypted)
- `server.publicUrl`: Defaults to `https://{server.name}`
## Unbind (MSC1915)
- `session.policy.unbind.enabled`: Enable or disable unbind functionality (MSC1915). (Defaults to true).
## Hash lookups, Term and others (MSC2140, MSC2134)
See the [dedicated document](MSC2140_MSC2134.md) for configuration.
*Warning*: Unbind check incoming request by two ways:
- session validation.
- request signature via `X-Matrix` header and uses `server.publicUrl` property to construct the signing json;
Commonly the `server.publicUrl` should be the same value as the `trusted_third_party_id_servers` property in the synapse config.
## Storage
### SQLite
`storage.provider.sqlite.database`: Absolute location of the SQLite database
```yaml
storage:
backend: sqlite # default
provider:
sqlite:
database: /var/lib/ma1sd/store.db # Absolute location of the SQLite database
```
### Postgresql
```yaml
storage:
backend: postgresql
provider:
postgresql:
database: //localhost:5432/ma1sd
username: ma1sd
password: secret_password
```
See [the migration instruction](migration-to-postgresql.md) from sqlite to postgresql
## Logging
```yaml
logging:
root: error # default level for all loggers (apps and thirdparty libraries)
app: info # log level only for the ma1sd
requests: false # log request and response
```
Possible value: `trace`, `debug`, `info`, `warn`, `error`, `off`.
Default value for root level: `info`.
Value for app level can be specified via `MA1SD_LOG_LEVEL` environment variable, configuration or start options.
Default value for app level: `info`.
| start option | equivalent configuration |
| --- | --- |
| | app: info |
| -v | app: debug |
| -vv | app: trace |
#### WARNING
The setting `logging.requests` *MUST NOT* be used in production due it prints full unmasked request and response into the log and can be cause of the data leak.
This setting can be used only to testing and debugging errors.
## Identity stores
See the [Identity stores](stores/README.md) for specific configuration
@@ -68,7 +125,7 @@ notification:
msisdn: 'raw'
```
- Emails notifications would use the `sendgrid` handler, which define its own configuration under `notification.handlers.sendgrid`
- Phone notification would use the `raw` handler, basic default built-in handler in mxisd
- Phone notification would use the `raw` handler, basic default built-in handler in ma1sd
### Handlers
- `notification.handers.<handler ID>`: Handler-specific configuration for the given handler ID. Repeatable.

View File

@@ -10,32 +10,32 @@ first basic setup running which relies on you reading the documentation in the r
- [Identity stores](stores/README.md) you wish to fetch data from.
- [Features](features) you are interested in that will use your Identity store(s) data.
**IMPORTANT**: Be aware that mxisd tries to fit within the current protocol and existing products and basic understanding
**IMPORTANT**: Be aware that ma1sd tries to fit within the current protocol and existing products and basic understanding
of the Matrix protocol is required for some advanced features.
If all fails, come over to [the project room](https://matrix.to/#/#mxisd:kamax.io) and we'll do our best to get you
If all fails, come over to [the project room](https://matrix.to/#/#ma1sd:ru-matrix.org) and we'll do our best to get you
started and answer questions you might have.
### What kind of setup is mxisd really designed for?
mxisd is primarily designed for setups that:
- [Care for their privacy](https://github.com/kamax-matrix/mxisd/wiki/mxisd-and-your-privacy)
### What kind of setup is ma1sd really designed for?
ma1sd is primarily designed for setups that:
- [Care for their privacy](https://github.com/kamax-matrix/ma1sd/wiki/ma1sd-and-your-privacy)
- Have their own [domains](https://en.wikipedia.org/wiki/Domain_name)
- Use those domains for their email addresses and all other services
- Already have an [Identity store](stores/README.md), typically [LDAP-based](stores/ldap.md).
If you meet all the conditions, then you are the prime use case we designed mxisd for.
If you meet all the conditions, then you are the prime use case we designed ma1sd for.
If you meet some of the conditions, but not all, mxisd will still be a good fit for you but you won't fully enjoy all its
If you meet some of the conditions, but not all, ma1sd will still be a good fit for you but you won't fully enjoy all its
features.
### Do I need to use mxisd if I run a Homeserver?
### Do I need to use ma1sd if I run a Homeserver?
No, but it is strongly recommended, even if you don't use any Identity store or integration.
In its default configuration, mxisd uses other federated public servers when performing queries.
In its default configuration, ma1sd uses other federated public servers when performing queries.
It can also [be configured](features/identity.md#lookups) to use the central matrix.org servers, giving you access to at
least the same information as if you were not running it.
So mxisd is like your gatekeeper and guardian angel. It does not change what you already know, just adds some nice
So ma1sd is like your gatekeeper and guardian angel. It does not change what you already know, just adds some nice
simple features on top of it.
### I'm not sure I understand what an "Identity server" is supposed to be or do...
@@ -44,20 +44,19 @@ what they want to do with that part of the ecosystem. Therefore, "Identity" is c
Given the scope of the current Identity Service API, it would be best called "Invitation service".
Because the current scope is so limited and no integration is done with the Homeserver, there was a big lack of features
for groups/corporations/organisation. This is where mxisd comes in.
for groups/corporations/organisation. This is where ma1sd comes in.
mxisd implements the Identity Service API and also a set of features which are expected by regular users, truly living
ma1sd implements the Identity Service API and also a set of features which are expected by regular users, truly living
up to its "Identity server" name.
### Can I migrate my existing account on another Matrix server with mxisd?
### Can I migrate my existing account on another Matrix server with ma1sd?
No.
Accounts cannot currently migrate/move from one server to another.
See a [brief explanation document](concepts.md) about Matrix and mxisd concepts and vocabulary.
See a [brief explanation document](concepts.md) about Matrix and ma1sd concepts and vocabulary.
### I already use the synapse LDAP3 auth provider. Why should I care about mxisd?
The [synapse LDAP3 auth provider](https://github.com/matrix-org/matrix-synapse-ldap3) is not longer maintained despite
saying so and only handles on specific flow: validate credentials at login.
### I already use the synapse LDAP3 auth provider. Why should I care about ma1sd?
The [synapse LDAP3 auth provider](https://github.com/matrix-org/matrix-synapse-ldap3) only handles one specific flow: validate credentials at login.
It does not:
- Auto-provision user profiles
@@ -65,7 +64,7 @@ It does not:
- Integrate with Directory searches
- Integrate with Profile data
mxisd is a replacement and enhancement of it, offering coherent results in all areas, which the LDAP3 auth provider
ma1sd is a replacement and enhancement of it, offering coherent results in all areas, which the LDAP3 auth provider
does not.
### Sydent is the official Identity server implementation of the Matrix team. Why not use that?
@@ -76,22 +75,22 @@ You can, but [sydent](https://github.com/matrix-org/sydent):
- forces you to duplicate all your identity data, so people can be found by 3PIDs
- forces users to enter all their emails and phone numbers manually in their profile
So really, you should go with mxisd.
So really, you should go with ma1sd.
### Will I loose access to the central Matrix.org/Vector.im Identity data if I use mxisd?
### Will I loose access to the central Matrix.org/Vector.im Identity data if I use ma1sd?
No.
In its default configuration, mxisd does not talk to the central Identity server matrix.org to avoid leaking your private
In its default configuration, ma1sd does not talk to the central Identity server matrix.org to avoid leaking your private
data and those of people you might know.
[You can configure it](features/identity.md#lookups) to talk to the central Identity servers if you wish.
### So mxisd is just a big hack! I don't want to use non-official features!
mxisd primary concerns are your privacy and to always be compatible with the Matrix ecosystem and the Identity service API.
Whenever the API will be updated and/or enhanced, mxisd will follow, remaining 100% compatible with the ecosystem.
### So ma1sd is just a big hack! I don't want to use non-official features!
ma1sd primary concerns are your privacy and to always be compatible with the Matrix ecosystem and the Identity service API.
Whenever the API will be updated and/or enhanced, ma1sd will follow, remaining 100% compatible with the ecosystem.
### Should I use mxisd if I don't host my own Homeserver?
### Should I use ma1sd if I don't host my own Homeserver?
No.
It is possible, but it is not supported and the scope of features will be extremely limited.
Please consider hosting your own Homeserver and using mxisd alongside it.
Please consider hosting your own Homeserver and using ma1sd alongside it.

View File

@@ -3,7 +3,7 @@
- [Basic](#basic)
- [Overview](#overview)
- [synapse](#synapse)
- [mxisd](#mxisd)
- [ma1sd](#ma1sd)
- [Validate](#validate)
- [Next steps](#next-steps)
- [Profile auto-fil](#profile-auto-fill)
@@ -16,15 +16,15 @@
- [DNS Overwrite](#dns-overwrite)
## Description
Authentication is an enhanced feature of mxisd to ensure coherent and centralized identity management.
It allows to use Identity stores configured in mxisd to authenticate users on your Homeserver.
Authentication is an enhanced feature of ma1sd to ensure coherent and centralized identity management.
It allows to use Identity stores configured in ma1sd to authenticate users on your Homeserver.
Authentication is divided into two parts:
- [Basic](#basic): authenticate with a regular username.
- [Advanced](#advanced): same as basic with extra abilities like authenticate using a 3PID or do username rewrite.
## Basic
Authentication by username is possible by linking synapse and mxisd together using a specific module for synapse, also
Authentication by username is possible by linking synapse and ma1sd together using a specific module for synapse, also
known as password provider.
### Overview
@@ -33,7 +33,7 @@ An overview of the Basic Authentication process:
Identity stores
Client +------+
| +-------------------------+ +--> | LDAP |
| +---------------+ /_matrix/identity | mxisd | | +------+
| +---------------+ /_matrix/identity | ma1sd | | +------+
+-> | Reverse proxy | >------------------+ | | |
+--|------------+ | | | | +--------+
| +-----> Check ID stores >------+--> | SQL DB |
@@ -49,20 +49,20 @@ An overview of the Basic Authentication process:
| user profiles | If valid credentials and supported by Identity store(s)
+--------------------------+
```
Performed on [synapse with REST auth module](https://github.com/kamax-io/matrix-synapse-rest-auth/blob/master/README.md)
Performed on [synapse with REST auth module](https://github.com/ma1uta/matrix-synapse-rest-password-provider/blob/master/README.md)
### Synapse
- Install the [password provider](https://github.com/kamax-io/matrix-synapse-rest-auth)
- Install the [password provider](https://github.com/ma1uta/matrix-synapse-rest-password-provider)
- Edit your **synapse** configuration:
- As described by the auth module documentation
- Set `endpoint` to `http://mxisdAddress:8090` - Replace `mxisdAddress` by an IP/host name that provides a direct
connection to mxisd.
- Set `endpoint` to `http://ma1sdAddress:8090` - Replace `ma1sdAddress` by an IP/host name that provides a direct
connection to ma1sd.
This **MUST NOT** be a public address, and SHOULD NOT go through a reverse proxy.
- Restart synapse
### mxisd
### ma1sd
- Configure and enable at least one [Identity store](../stores/README.md)
- Restart mxisd
- Restart ma1sd
### Validate
Login on the Homeserver using credentials present in one of your Identity stores.
@@ -93,7 +93,7 @@ This is performed by intercepting the Homeserver endpoint `/_matrix/client/r0/lo
| | Step 1 +---------------------------+ Step 2
| | | |
Client+---->| /_matrix/client/r0/login +---------------->| | Look up address +---------+
| ^ | | mxisd - Identity server +----------------->| Backend |
| ^ | | ma1sd - Identity server +----------------->| Backend |
| | | | | +---------+
| /_matrix/* +--+ +---------------------+ |
| | | +---------------+-----------+
@@ -110,7 +110,7 @@ Client+---->| /_matrix/client/r0/login +---------------->|
```
Steps of user authentication using a 3PID:
1. The intercepted login request is directly sent to mxisd instead of the Homeserver.
1. The intercepted login request is directly sent to ma1sd instead of the Homeserver.
2. Identity stores are queried for a matching user identity in order to modify the request to use the user name.
3. The Homeserver, from which the request was intercepted, is queried using the request at previous step.
Its address is resolved using the DNS Overwrite feature to reach its internal address on a non-encrypted port.
@@ -129,7 +129,7 @@ The specific configuration to put under the relevant `VirtualHost`:
```apache
ProxyPass /_matrix/client/r0/login http://localhost:8090/_matrix/client/r0/login
```
`ProxyPreserveHost` or equivalent **must** be enabled to detect to which Homeserver mxisd should talk to when building results.
`ProxyPreserveHost` or equivalent **must** be enabled to detect to which Homeserver ma1sd should talk to when building results.
Your VirtualHost should now look similar to:
```apache
@@ -188,10 +188,10 @@ server {
#### DNS Overwrite
Just like you need to configure a reverse proxy to send client requests to mxisd, you also need to configure mxisd with
Just like you need to configure a reverse proxy to send client requests to ma1sd, you also need to configure ma1sd with
the internal IP of the Homeserver so it can talk to it directly to integrate its directory search.
To do so, put the following configuration in your mxisd configuration:
To do so, put the following configuration in your ma1sd configuration:
```yaml
dns:
overwrite:
@@ -214,7 +214,7 @@ The following features are available after you have a working Advanced setup:
- Username rewrite: Allows you to rewrite the username of a regular login/pass authentication to a 3PID, that then gets resolved using the regular lookup process. Most common use case is to allow login with numerical usernames on synapse, which is not possible out of the box.
#### Username rewrite
In mxisd config:
In ma1sd config:
```yaml
auth:
rewrite:

View File

@@ -1,11 +1,11 @@
# Bridge Integration
To help natural bridge integration into the regular usage of a Matrix client, mxisd provides a way for bridge to reply
To help natural bridge integration into the regular usage of a Matrix client, ma1sd provides a way for bridge to reply
to 3PID queries if no mapping was found, allowing seamless bridging to a network.
This is performed by implementing a specific endpoint on the bridge to map a 3PID lookup to a virtual user.
**NOTE**: This document is incomplete and might be misleading. In doubt, come in our Matrix room.
You can also look at our [Email Bridge README](https://github.com/kamax-matrix/matrix-appservice-email#mxisd) for an example
You can also look at our [Email Bridge README](https://github.com/kamax-matrix/matrix-appservice-email#ma1sd) for an example
of working configuration.
## Configuration

View File

@@ -22,9 +22,9 @@ By enabling this feature, you can by default:
- Search for users which you are not in contact with yet. Super useful for corporations who want to give Matrix access
internally, so users can just find themselves **prior** to having any common room(s)
- Add extra attributes of your backend to extend the search
- Include your homeserver search results to those found by mxisd
- Include your homeserver search results to those found by ma1sd
By integrating mxisd, you get the default behaviour and a bunch of extras, ensuring your users will always find each other.
By integrating ma1sd, you get the default behaviour and a bunch of extras, ensuring your users will always find each other.
## Overview
This is performed by intercepting the Homeserver endpoint `/_matrix/client/r0/user_directory/search` like so:
@@ -33,7 +33,7 @@ This is performed by intercepting the Homeserver endpoint `/_matrix/client/r0/us
Client --> | Reverse proxy Step 2
| Step 1 +-------------------------+
| /_matrix/client/r0/user_directory/search ----------> | | Search in +---------+
| /\ | mxisd - Identity server | -----------> | Backend |
| /\ | ma1sd - Identity server | -----------> | Backend |
| /_matrix/* \----------------------------- | | all users +---------+
| | Step 4: Send back merged results +-------------------------+
+ | |
@@ -44,7 +44,7 @@ Client --> | Reverse proxy
+------------+ /_matrix/client/r0/user_directory/search
```
Steps:
1. The intercepted request is directly sent to mxisd instead of the Homeserver.
1. The intercepted request is directly sent to ma1sd instead of the Homeserver.
2. Identity stores are queried for any match on the search value sent by the client.
3. The Homeserver, from which the request was intercepted, is queried using the same request as the client.
Its address is resolved using the DNS Overwrite feature to reach its internal address on a non-encrypted port.
@@ -52,7 +52,7 @@ Steps:
which directly answered the request.
## Requirements
- Reverse proxy setup, which you should already have in place if you use mxisd
- Reverse proxy setup, which you should already have in place if you use ma1sd
- At least one compatible [Identity store](../stores/README.md) enabled
## Configuration
@@ -62,7 +62,7 @@ The specific configuration to put under the relevant `VirtualHost`:
```apache
ProxyPass /_matrix/client/r0/user_directory/ http://0.0.0.0:8090/_matrix/client/r0/user_directory/
```
`ProxyPreserveHost` or equivalent must be enabled to detect to which Homeserver mxisd should talk to when building
`ProxyPreserveHost` or equivalent must be enabled to detect to which Homeserver ma1sd should talk to when building
results.
Your `VirtualHost` should now look like this:
@@ -118,7 +118,7 @@ server {
```
### DNS Overwrite
Just like you need to configure a reverse proxy to send client requests to mxisd, you also need to configure mxisd with
Just like you need to configure a reverse proxy to send client requests to ma1sd, you also need to configure ma1sd with
the internal IP of the Homeserver so it can talk to it directly to integrate its directory search.
To do so, use the following configuration:
@@ -136,7 +136,7 @@ dns:
## Next steps
### Homeserver results
You can configure if the Homeserver should be queried at all when doing a directory search.
To disable Homeserver results, set the following in mxisd configuration file:
To disable Homeserver results, set the following in ma1sd configuration file:
```yaml
directory:
exclude:

View File

@@ -1,6 +1,6 @@
# Application Service
**WARNING:** These features are currently highly experimental. They can be removed or modified without notice.
All the features requires a Homeserver capable of connecting [Application Services](https://matrix.org/docs/spec/application_service/r0.1.0.html).
All the features requires a Homeserver capable of connecting [Application Services](https://matrix.org/docs/spec/application_service/r0.1.1.html).
The following capabilities are provided in this feature:
- [Admin commands](#admin-commands)
@@ -11,7 +11,7 @@ The following capabilities are provided in this feature:
> **NOTE:** Make sure you are familiar with [configuration format and rules](../../configure.md).
Integration as an Application service is a three steps process:
1. Create the baseline mxisd configuration to allow integration.
1. Create the baseline ma1sd configuration to allow integration.
2. Integrate with the homeserver.
3. Configure the specific capabilities, if applicable.
@@ -22,11 +22,11 @@ Under the `appsvc` namespace:
| Key | Type | Required | Default | Purpose |
|-----------------------|---------|----------|---------|----------------------------------------------------------------|
| `enabled` | boolean | No | `false` | Globally enable/disable the feature |
| `user.main` | string | No | `mxisd` | Localpart for the main appservice user |
| `user.main` | string | No | `ma1sd` | Localpart for the main appservice user |
| `endpoint.toHS.url` | string | Yes | *None* | Base URL to the Homeserver |
| `endpoint.toHS.token` | string | Yes | *None* | Token to use when sending requests to the Homeserver |
| `endpoint.toAS.url` | string | Yes | *None* | Base URL to mxisd from the Homeserver |
| `endpoint.toAS.token` | string | Yes | *None* | Token for the Homeserver to use when sending requests to mxisd |
| `endpoint.toAS.url` | string | Yes | *None* | Base URL to ma1sd from the Homeserver |
| `endpoint.toAS.token` | string | Yes | *None* | Token for the Homeserver to use when sending requests to ma1sd |
#### Example
```yaml
@@ -46,7 +46,7 @@ Under the `appsvc.registration.synapse` namespace:
| Key | Type | Required | Default | Purpose |
|--------|--------|----------|--------------------|--------------------------------------------------------------------------|
| `id` | string | No | `appservice-mxisd` | The unique, user-defined ID of this application service. See spec. |
| `id` | string | No | `appservice-ma1sd` | The unique, user-defined ID of this application service. See spec. |
| `file` | string | Yes | *None* | If defined, the synapse registration file that should be created/updated |
##### Example
@@ -54,17 +54,17 @@ Under the `appsvc.registration.synapse` namespace:
appsvc:
registration:
synapse:
file: '/etc/matrix-synapse/mxisd-appservice-registration.yaml'
file: '/etc/matrix-synapse/ma1sd-appservice-registration.yaml'
```
Edit your `homeserver.yaml` and add a new entry to the appservice config file, which should look something like this:
```yaml
app_service_config_files:
- '/etc/matrix-synapse/mxisd-appservice-registration.yaml'
- '/etc/matrix-synapse/ma1sd-appservice-registration.yaml'
- ...
```
Restart synapse when done to register mxisd.
Restart synapse when done to register ma1sd.
#### Others
See your Homeserver documentation on how to integrate.
@@ -86,9 +86,9 @@ appsvc:
#### Use
The following steps assume:
- `matrix.domain` set to `example.org`
- `appsvc.user.main` set to `mxisd` or not set
- `appsvc.user.main` set to `ma1sd` or not set
1. Invite `@mxisd:example.org` to a new direct chat
1. Invite `@ma1sd:example.org` to a new direct chat
2. Type `!help` to get all available commands
### Email Notification about room invites by Matrix IDs
@@ -100,7 +100,7 @@ account was already provisioned on the Homeserver.
- At least one email entry in the identity store for each user that could be invited.
#### Configuration
In your mxisd config file:
In your ma1sd config file:
```yaml
synapseSql:
enabled: false ## Do not use this line if Synapse is used as an Identity Store

View File

@@ -5,7 +5,7 @@ Federated Identity server using the DNS domain part of the 3PID.
Emails are the best candidate for this kind of resolution which are DNS domain based already.
On the other hand, Phone numbers cannot be resolved this way.
For 3PIDs which are not compatible with the DNS system, mxisd can be configured to talk to fallback Identity servers like
For 3PIDs which are not compatible with the DNS system, ma1sd can be configured to talk to fallback Identity servers like
the central matrix.org one. See the [Identity feature](identity.md#lookups) for instructions on how to enable it.
Outbound federation is enabled by default while inbound federation is opt-in and require a specific DNS record.
@@ -13,7 +13,7 @@ Outbound federation is enabled by default while inbound federation is opt-in and
## Overview
```
+-------------------+ +-------------> +----------+
| mxisd | | | Backends |
| ma1sd | | | Backends |
| | | +------> +----------+
| | | |
| Invites / Lookups | | |
@@ -23,7 +23,7 @@ Outbound federation is enabled by default while inbound federation is opt-in and
| | |
| +--------+ | | +-------------------+
Homeserver --->| Local |>------------------+------> | Remote Federated |
and clients | +--------+ | | mxisd servers |
and clients | +--------+ | | ma1sd servers |
+-------------------+ +-------------------+
```
@@ -34,11 +34,11 @@ If you would like to be reachable for lookups over federation, create the follow
_matrix-identity._tcp.example.com. 3600 IN SRV 10 0 443 matrix.example.com.
```
The port must be HTTPS capable which is what you get in a regular setup with a reverse proxy from 443 to TCP 8090 of mxisd.
The port must be HTTPS capable which is what you get in a regular setup with a reverse proxy from 443 to TCP 8090 of ma1sd.
## Outbound
If you would like to disable outbound federation and isolate your identity server from the rest of the Matrix network,
use the following mxisd configuration options:
use the following ma1sd configuration options:
```yaml
lookup:
recursive:

View File

@@ -1,5 +1,5 @@
# Identity
Implementation of the [Identity Service API r0.1.0](https://matrix.org/docs/spec/identity_service/r0.1.0.html).
Implementation of the [Identity Service API r0.3.0](https://matrix.org/docs/spec/identity_service/r0.3.0.html).
- [Lookups](#lookups)
- [Invitations](#invitations)
@@ -17,7 +17,7 @@ forward:
- 'matrix-org'
```
**NOTE:** You should carefully consider enabling this option, which is discouraged.
For more info, see the [relevant issue](https://github.com/kamax-matrix/mxisd/issues/76).
For more info, see the [relevant issue](https://github.com/kamax-matrix/ma1sd/issues/76).
## Invitations
### Expiration
@@ -25,10 +25,10 @@ For more info, see the [relevant issue](https://github.com/kamax-matrix/mxisd/is
Matrix does not provide a mean to remove/cancel pending 3PID invitations with the APIs. The current reference
implementations also do not provide any mean to do so. This leads to 3PID invites forever stuck in rooms.
To provide this functionality, mxisd uses a workaround: resolve the invite to a dedicated User ID, which can be
controlled by mxisd or a bot/service that will then reject the invite.
To provide this functionality, ma1sd uses a workaround: resolve the invite to a dedicated User ID, which can be
controlled by ma1sd or a bot/service that will then reject the invite.
If this dedicated User ID is to be controlled by mxisd, the [Application Service](experimental/application-service.md)
If this dedicated User ID is to be controlled by ma1sd, the [Application Service](experimental/application-service.md)
feature must be configured and integrated with your Homeserver, as well as the *Auto-reject 3PID invite capability*.
#### Configuration
@@ -63,7 +63,7 @@ It's a middle ground between a closed server, where every user must be created o
and an open server, where anyone can register.
#### Integration
Because Identity Servers do not control 3PID invites as per Matrix spec, mxisd needs to intercept a set of Homeserver
Because Identity Servers do not control 3PID invites as per Matrix spec, ma1sd needs to intercept a set of Homeserver
endpoints to apply the policies.
##### Reverse Proxy
@@ -101,7 +101,7 @@ Resolution of 3PID invitations can be customized using the following configurati
`invite.resolution.timer`
- Default value: `1`
- Description: How often, in minutes, mxisd should try to resolve pending invites.
- Description: How often, in minutes, ma1sd should try to resolve pending invites.
## 3PIDs Management
See the [3PID session documents](../threepids/session)

View File

@@ -3,7 +3,7 @@
- [Integration](#integration)
- [Reverse Proxy](#reverse-proxy)
- [nginx](#nginx)
- [Apache](#apache)
- [Apache2](#apache2)
- [Homeserver](#homeserver)
- [synapse](#synapse)
- [Configuration](#configuration)
@@ -13,10 +13,10 @@
## Overview
**NOTE**: This feature is beta: it is considered stable enough for production but is incomplete and may contain bugs.
Registration is an enhanced feature of mxisd to control registrations involving 3PIDs on a Homeserver based on policies:
Registration is an enhanced feature of ma1sd to control registrations involving 3PIDs on a Homeserver based on policies:
- Match pending 3PID invites on the server
- Match 3PID pattern, like a specific set of domains for emails
- In futher releases, use 3PIDs found in Identity stores
- In further releases, use 3PIDs found in Identity stores
It aims to help open or invite-only registration servers control what is possible to do and ensure only approved people
can register on a given server in a implementation-agnostic manner.
@@ -28,7 +28,7 @@ As such, it relies on the homeserver to require 3PIDs with the registration flow
This feature is not part of the Matrix Identity Server spec.
## Integration
mxisd needs to be integrated at several levels for this feature to work:
ma1sd needs to be integrated at several levels for this feature to work:
- Reverse proxy: intercept the 3PID register endpoints and act on them
- Homeserver: require 3PID to be part of the registration data
@@ -36,14 +36,14 @@ Later version(s) of this feature may directly control registration itself to cre
### Reverse Proxy
#### nginx
```nginx
location ^/_matrix/client/r0/register/[^/]/?$ {
proxy_pass http://127.0.0.1:8090;
location ~* ^/_matrix/client/r0/register/[^/]+/requestToken$ {
proxy_pass http://localhost:8090;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $remote_addr;
}
```
#### apache
#### Apache2
> TBC
### Homeserver
@@ -55,8 +55,8 @@ registrations_require_3pid:
```
## Configuration
See the [Configuration](../configuration.md) introduction doc on how to read the configuration keys.
An example of working configuration is avaiable at the end of this section.
See the [Configuration](../configure.md) introduction doc on how to read the configuration keys.
An example of working configuration is available at the end of this section.
### Enable/Disable
`register.allowed`, taking a boolean, can be used to enable/disable registration if the attempt is not 3PID-based.
`false` is the default value to prevent open registration, as you must allow it on the homeserver side.
@@ -72,7 +72,7 @@ At this time, only `email` is supported with 3PID specific configuration with th
**Base key**: `register.threepid.email`
##### Domain whitelist/blacklist
If you would like to control which domains are allowed to be used when registrating with an email, the following sub-keys
If you would like to control which domains are allowed to be used when registering with an email, the following sub-keys
are available:
- `domain.whitelist`
- `domain.blacklist`
@@ -82,7 +82,7 @@ The value format is an hybrid between glob patterns and postfix configuration fi
- `.<domain>` will only match sub-domain(s)
- `<domain>` will only match the exact domain
The following table illustrates pattern and maching status against example values:
The following table illustrates pattern and matching status against example values:
| Config value | Matches `example.org` | Matches `sub.example.org` |
|--------------- |-----------------------|---------------------------|

View File

@@ -12,8 +12,8 @@ This will be a good ground work for further integration with features and your e
---
If you would like a more fully integrated setup out of the box, the [matrix-docker-ansible-deploy](https://github.com/spantaleev/matrix-docker-ansible-deploy)
project provides a turn-key full-stack solution, including LDAP and the various mxisd features enabled and ready.
We work closely with the project owner so the latest mxisd version is always supported.
project provides a turn-key full-stack solution, including LDAP and the various ma1sd features enabled and ready.
We work closely with the project owner so the latest ma1sd version is always supported.
If you choose to use it, this Getting Started guide is not applicable - See the project documentation. You may then
directly go to the [Next steps](#next-steps).
@@ -21,21 +21,21 @@ directly go to the [Next steps](#next-steps).
## Preparation
You will need:
- Working Homeserver, ideally with working federation
- Reverse proxy with regular TLS/SSL certificate (Let's encrypt) for your mxisd domain
- Reverse proxy with regular TLS/SSL certificate (Let's encrypt) for your ma1sd domain
If you use synapse:
- It requires an HTTPS connection when talking to an Identity service, **a reverse proxy is required** as mxisd does
- It requires an HTTPS connection when talking to an Identity service, **a reverse proxy is required** as ma1sd does
not support HTTPS listener at this time.
- HTTPS is hardcoded when talking to the Identity server. If your Identity server URL in your client is `https://matrix.example.org/`,
then you need to ensure `https://matrix.example.org/_matrix/identity/api/v1/...` will reach mxisd if called from the synapse host.
then you need to ensure `https://matrix.example.org/_matrix/identity/api/v1/...` will reach ma1sd if called from the synapse host.
In doubt, test with `curl` or similar.
For maximum integration, it is best to have your Homeserver and mxisd reachable via the same public hostname.
For maximum integration, it is best to have your Homeserver and ma1sd reachable via the same public hostname.
Be aware of a [NAT/Reverse proxy gotcha](https://github.com/kamax-matrix/mxisd/wiki/Gotchas#nating) if you use the same
Be aware of a [NAT/Reverse proxy gotcha](https://github.com/ma1uta/ma1sd/wiki/Gotchas#nating) if you use the same
host.
The following Quick Start guide assumes you will host the Homeserver and mxisd under the same hostname.
The following Quick Start guide assumes you will host the Homeserver and ma1sd under the same hostname.
If you would like a high-level view of the infrastructure and how each feature is integrated, see the
[dedicated document](architecture.md)
@@ -47,14 +47,14 @@ Install via:
- [NixOS](install/nixos.md)
- [Sources](build.md)
See the [Latest release](https://github.com/kamax-matrix/mxisd/releases/latest) for links to each.
See the [Latest release](https://github.com/ma1uta/ma1sd/releases/latest) for links to each.
## Configure
> **NOTE**: Please view the install instruction for your platform, as this step might be optional or already handled for you.
> **NOTE**: Details about configuration syntax and format are described [here](configure.md)
If you haven't created a configuration file yet, copy `mxisd.example.yaml` to where the configuration file is stored given
If you haven't created a configuration file yet, copy `ma1sd.example.yaml` to where the configuration file is stored given
your installation method and edit to your needs.
The following items must be at least configured:
@@ -62,15 +62,15 @@ The following items must be at least configured:
- `key.path` will store the signing keys, which must be kept safe! If the file does not exist, keys will be generated for you.
- `storage.provider.sqlite.database` is the location of the SQLite Database file which will hold state (invites, etc.)
If your HS/mxisd hostname is not the same as your Matrix domain, configure `server.name`.
If your HS/ma1sd hostname is not the same as your Matrix domain, configure `server.name`.
Complete configuration guide is available [here](configure.md).
## Integrate
For an overview of a typical mxisd infrastructure, see the [dedicated document](architecture.md)
For an overview of a typical ma1sd infrastructure, see the [dedicated document](architecture.md)
### Reverse proxy
#### Apache2
In the `VirtualHost` section handling the domain with SSL, add the following and replace `0.0.0.0` by the internal
hostname/IP pointing to mxisd.
hostname/IP pointing to ma1sd.
**This line MUST be present before the one for the homeserver!**
```apache
ProxyPass /_matrix/identity http://0.0.0.0:8090/_matrix/identity
@@ -91,7 +91,7 @@ Typical configuration would look like:
#### nginx
In the `server` section handling the domain with SSL, add the following and replace `0.0.0.0` with the internal
hostname/IP pointing to mxisd.
hostname/IP pointing to ma1sd.
**This line MUST be present before the one for the homeserver!**
```nginx
location /_matrix/identity {
@@ -121,37 +121,35 @@ server {
}
```
### Synapse
Add your mxisd domain into the `homeserver.yaml` at `trusted_third_party_id_servers` and restart synapse.
### Synapse (Deprecated with synapse v1.4.0)
Add your ma1sd domain into the `homeserver.yaml` at `trusted_third_party_id_servers` and restart synapse.
In a typical configuration, you would end up with something similar to:
```yaml
trusted_third_party_id_servers:
- matrix.example.org
```
It is **highly recommended** to remove `matrix.org` and `vector.im` (or any other default entry) from your configuration
so only your own Identity server is authoritative for your HS.
## Validate
## Validate (Under reconstruction)
**NOTE:** In case your homeserver has no working federation, step 5 will not happen. If step 4 took place, consider
your installation validated.
1. Log in using your Matrix client and set `https://matrix.example.org` as your Identity server URL, replacing `matrix.example.org`
by the relevant hostname which you configured in your reverse proxy.
2. Create a new empty room. All further actions will take place in this room.
3. Invite `mxisd-federation-test@kamax.io`
4. The 3PID invite should be turned into a Matrix invite to `@mxisd-lookup-test:kamax.io`.
3. Invite `ma1sd-federation-test@kamax.io`
4. The 3PID invite should be turned into a Matrix invite to `@ma1sd-lookup-test:kamax.io`.
5. The invited test user will join the room, send a congratulation message and leave.
**NOTE:** You might not see a suggestion for the e-mail address, which is normal. Still proceed with the invite.
If it worked, it means you are up and running and can enjoy mxisd in its basic mode! Congratulations!
If it worked, it means you are up and running and can enjoy ma1sd in its basic mode! Congratulations!
If it did not work, read the basic [troubleshooting guide](troubleshooting.md), [get in touch](../README.md#support) and
we'll do our best to get you started.
## Next steps
Once your mxisd server is up and running, there are several ways you can enhance and integrate further with your
Once your ma1sd server is up and running, there are several ways you can enhance and integrate further with your
infrastructure:
- [Enable extra features](features/)
- [Use your own Identity stores](stores/README.md)
- [Hardening your mxisd installation](install/security.md)
- [Hardening your ma1sd installation](install/security.md)
- [Learn about day-to-day operations](operations.md)

View File

@@ -1,3 +1,9 @@
---
** Outdated due to migrating to fork. **
---
# Arch Linux package
An Arch Linux package in the AUR repos is maintained by [r3pek](https://matrix.to/#/@r3pek:r3pek.org), a community member.
See https://aur.archlinux.org/packages/mxisd/

View File

@@ -3,40 +3,40 @@
- Any distribution that supports Java 8
## Install
1. Download the [latest release](https://github.com/kamax-matrix/mxisd/releases/latest)
1. Download the [latest release](https://github.com/ma1uta/ma1sd/releases/latest)
2. Run:
```bash
dpkg -i /path/to/downloaded/mxisd.deb
dpkg -i /path/to/downloaded/ma1sd.deb
```
## Files
| Location | Purpose |
|-------------------------------------|----------------------------------------------|
| `/etc/mxisd` | Configuration directory |
| `/etc/mxisd/mxisd.yaml` | Main configuration file |
| `/etc/systemd/system/mxisd.service` | Systemd configuration file for mxisd service |
| `/usr/lib/mxisd` | Binaries |
| `/var/lib/mxisd` | Data |
| `/var/lib/mxisd/signing.key` | Default location for mxisd signing keys |
| `/etc/ma1sd` | Configuration directory |
| `/etc/ma1sd/ma1sd.yaml` | Main configuration file |
| `/etc/systemd/system/ma1sd.service` | Systemd configuration file for ma1sd service |
| `/usr/lib/ma1sd` | Binaries |
| `/var/lib/ma1sd` | Data |
| `/var/lib/ma1sd/signing.key` | Default location for ma1sd signing keys |
## Control
Start mxisd using:
Start ma1sd using:
```bash
sudo systemctl start mxisd
sudo systemctl start ma1sd
```
Stop mxisd using:
Stop ma1sd using:
```bash
sudo systemctl stop mxisd
sudo systemctl stop ma1sd
```
## Troubleshoot
All logs are sent to `STDOUT` which are saved in `/var/log/syslog` by default.
You can:
- grep & tail using `mxisd`:
- grep & tail using `ma1sd`:
```
tail -n 99 -f /var/log/syslog | grep mxisd
tail -n 99 -f /var/log/syslog | grep ma1sd
```
- use Systemd's journal:
```
journalctl -f -n 99 -u mxisd
journalctl -f -n 99 -u ma1sd
```

View File

@@ -1,13 +1,19 @@
---
** Outdated due to migrating to fork. **
---
# Docker
## Fetch
Pull the latest stable image:
```bash
docker pull kamax/mxisd
docker pull ma1uta/ma1sd
```
## Configure
On first run, simply using `MATRIX_DOMAIN` as an environment variable will create a default config for you.
You can also provide a configuration file named `mxisd.yaml` in the volume mapped to `/etc/mxisd` before starting your
You can also provide a configuration file named `ma1sd.yaml` in the volume mapped to `/etc/ma1sd` before starting your
container.
## Run
@@ -16,10 +22,10 @@ Use the following command after adapting to your needs:
- The volumes host paths
```bash
docker run --rm -e MATRIX_DOMAIN=example.org -v /data/mxisd/etc:/etc/mxisd -v /data/mxisd/var:/var/mxisd -p 8090:8090 -t kamax/mxisd
docker run --rm -e MATRIX_DOMAIN=example.org -v /data/ma1sd/etc:/etc/ma1sd -v /data/ma1sd/var:/var/ma1sd -p 8090:8090 -t ma1uta/ma1sd
```
For more info, including the list of possible tags, see [the public repository](https://hub.docker.com/r/kamax/mxisd/)
For more info, including the list of possible tags, see [the public repository](https://hub.docker.com/r/ma1uta/ma1sd/)
## Troubleshoot
Please read the [Troubleshooting guide](../troubleshooting.md).
Please read the [Troubleshooting guide](../troubleshooting.md).

View File

@@ -1,3 +1,9 @@
---
** Outdated due to migrating to fork. **
---
# NixOS package
mxisd is available as a NixOS package in the official repos.

View File

@@ -5,23 +5,23 @@ avoid leak of credentials/key pairs
## Configuration
Your config file should have the following ownership:
- Dedicated user for mxisd, used to run the software
- Dedicated group for mxisd, used by other applications to access and read configuration files
- Dedicated user for ma1sd, used to run the software
- Dedicated group for ma1sd, used by other applications to access and read configuration files
Your config file should have the following access:
- Read and write for the mxisd user
- Read for the mxisd group
- Read and write for the ma1sd user
- Read for the ma1sd group
- Nothing for others
This translates into `640` and be applied with `chmod 640 /path/to/config/file.yaml`.
## Data
The only sensible place is the key store where mxisd's signing keys are stored. You should therefore limit access to only
the mxisd user, and deny access to anything else.
The only sensible place is the key store where ma1sd's signing keys are stored. You should therefore limit access to only
the ma1sd user, and deny access to anything else.
Your key store should have the following access:
- Read and write for the mxisd user
- Nothing for the mxisd group
- Read and write for the ma1sd user
- Nothing for the ma1sd group
- Nothing for others
The identity store can either be a file or a directory, depending on your version. v1.4 and higher are using a directory,

View File

@@ -5,40 +5,40 @@ Follow the [build instructions](../build.md) then:
### Prepare files and directories:
```bash
# Create a dedicated user
useradd -r mxisd
useradd -r ma1sd
# Create config directory
mkdir -p /etc/mxisd
mkdir -p /etc/ma1sd
# Create data directory and set ownership
mkdir -p /var/lib/mxisd
chown -R mxisd /var/lib/mxisd
mkdir -p /var/lib/ma1sd
chown -R ma1sd /var/lib/ma1sd
# Create bin directory, copy the jar and launch scriot to bin directory
mkdir /usr/lib/mxisd
cp ./build/libs/mxisd.jar /usr/lib/mxisd/
cp ./src/script/mxisd /usr/lib/mxisd
chown -R mxisd /usr/lib/mxisd
chmod a+x /usr/lib/mxisd/mxisd
mkdir /usr/lib/ma1sd
cp ./build/libs/ma1sd.jar /usr/lib/ma1sd/
cp ./src/script/ma1sd /usr/lib/ma1sd
chown -R ma1sd /usr/lib/ma1sd
chmod a+x /usr/lib/ma1sd/ma1sd
# Create symlink for easy exec
ln -s /usr/lib/mxisd/mxisd /usr/bin/mxisd
ln -s /usr/lib/ma1sd/ma1sd /usr/bin/ma1sd
```
### Prepare config file
Copy the configuration file you've created following the build instructions to `/etc/mxisd/mxisd.yaml`
Copy the configuration file you've created following the build instructions to `/etc/ma1sd/ma1sd.yaml`
### Prepare Systemd
1. Copy `src/systemd/mxisd.service` to `/etc/systemd/system/` and edit if needed
1. Copy `src/systemd/ma1sd.service` to `/etc/systemd/system/` and edit if needed
2. Enable service for auto-startup
```bash
systemctl enable mxisd
systemctl enable ma1sd
```
### Run
```bash
systemctl start mxisd
systemctl start ma1sd
```
## Debug
mxisd logs to stdout, which is normally sent to `/var/log/syslog` or `/var/log/messages`.
ma1sd logs to stdout, which is normally sent to `/var/log/syslog` or `/var/log/messages`.

View File

@@ -0,0 +1,16 @@
# Migration from mxisd
Version 2.0.0 of the ma1sd uses the same format of the database schema and main configuration file as mxisd.
Migration from mxisd:
- install ma1sd via deb package, docker image or zip/tar archive
- stop mxisd
- copy configuration file (by default /etc/mxisd/mxisd.yaml to /etc/ma1sd/ma1sd.yaml)
- copy key store (by default /var/lib/mxisd/keys folder to /var/lib/ma1sd/keys)
- copy storage (by default /var/lib/mxisd/store.db to /var/lib/ma1sd/store.db)
- change paths in the new config file (ma1sd.yaml). There are options: `key.path` and `storage.provider.sqlite`
- start ma1sd
Due to ma1sd uses the same ports by default as mxisd it isn't necessary to change nginx/apache configuration.
If you have any troubles with migration don't hesitate to ask questions in [#ma1sd:ru-matrix.org](https://matrix.to/#/#ma1sd:ru-matrix.org) room.

View File

@@ -0,0 +1,41 @@
# Migration from sqlite to postgresql
Starting from the version 2.3.0 ma1sd support postgresql for internal storage in addition to sqlite (parameters `storage.backend`).
#### Migration steps
1. create the postgresql database and user for ma1sd storage
2. create a backup for sqlite storage (default location: /var/lib/ma1sd/store.db)
3. migrate data from sqlite to postgresql
4. change ma1sd configuration to use the postgresql
For data migration is it possible to use https://pgloader.io tool.
Example of the migration command:
```shell script
pgloader --with "quote identifiers" /path/to/store.db pgsql://ma1sd_user:ma1sd_password@host:port/database
```
or (short version for database on localhost)
```shell script
pgloader --with "quote identifiers" /path/to/store.db pgsql://ma1sd_user:ma1sd_password@localhost/ma1sd
```
An option `--with "quote identifies"` used to create case sensitive tables.
ma1sd_user - postgresql user for ma1sd.
ma1sd_password - password of the postgresql user.
host - postgresql host
post - database port (default 5432)
database - database name.
Configuration example for postgresql storage:
```yaml
storage:
backend: postgresql
provider:
postgresql:
database: '//localhost/ma1sd' # or full variant //192.168.1.100:5432/ma1sd_database
username: 'ma1sd_user'
password: 'ma1sd_password'
```

View File

@@ -1,21 +1,24 @@
# Operations Guide
- [Overview](#overview)
- [Maintenance](#maintenance)
- [Backuo](#backup)
- [Operations Guide](#operations-guide)
- [Overview](#overview)
- [Maintenance](#maintenance)
- [Backup](#backup)
- [Run](#run)
- [Restore](#restore)
## Overview
This document gives various information for the day-to-day management and operations of mxisd.
This document gives various information for the day-to-day management and operations of ma1sd.
## Maintenance
mxisd does not require any maintenance task to run at optimal performance.
ma1sd does not require any maintenance task to run at optimal performance.
## Backup
### Run
mxisd requires all file in its configuration and data directory to be backed up.
ma1sd requires all file in its configuration and data directory to be backed up.
They are usually located at:
- `/etc/mxisd`
- `/var/lib/mxisd`
- `/etc/ma1sd`
- `/var/lib/ma1sd`
### Restore
Reinstall mxisd, restore the two folders above in the appropriate location (depending on your install method) and you
will be good to go. Simply start mxisd to restore functionality.
Reinstall ma1sd, restore the two folders above in the appropriate location (depending on your install method) and you
will be good to go. Simply start ma1sd to restore functionality.

View File

@@ -42,7 +42,7 @@
| [Profile](../features/profile.md) | Yes |
This Identity Store lets you run arbitrary commands to handle the various requests in each support feature.
It is the most versatile Identity store of mxisd, allowing you to connect any kind of logic with any executable/script.
It is the most versatile Identity store of ma1sd, allowing you to connect any kind of logic with any executable/script.
## Overview
Each request can be mapping to a fully customizable command configuration.
@@ -190,7 +190,7 @@ The following types are available:
exec:
auth:
enabled: true
command: '/opt/mxisd-exec/auth.sh'
command: '/opt/ma1sd-exec/auth.sh'
args: ['{localpart}']
input:
type: 'plain'
@@ -198,7 +198,7 @@ exec:
env:
DOMAIN: '{domain}'
```
With Authentication enabled, run `/opt/mxisd-exec/auth.sh` when validating credentials, providing:
With Authentication enabled, run `/opt/ma1sd-exec/auth.sh` when validating credentials, providing:
- A single command-line argument to provide the `localpart` as username
- A plain text string with the password token for standard input, which will be replaced by the password to check
- A single environment variable `DOMAIN` containing Matrix ID domain, if given

View File

@@ -17,19 +17,19 @@ For NetIQ, replace all the `ldap` prefix in the configuration by `netiq`.
## Getting started
### Base
To use your LDAP backend, add the bare minimum configuration in mxisd config file:
To use your LDAP backend, add the bare minimum configuration in ma1sd config file:
```yaml
ldap:
enabled: true
connection:
host: 'ldapHostnameOrIp'
port: 389
bindDn: 'CN=My Mxisd User,OU=Users,DC=example,DC=org'
bindDn: 'CN=My User,OU=Users,DC=example,DC=org'
bindPassword: 'TheUserPassword'
baseDNs:
- 'OU=Users,DC=example,DC=org'
```
These are standard LDAP connection configuration. mxisd will try to connect on port default port 389 without encryption.
These are standard LDAP connection configuration. ma1sd will try to connect on port default port 389 without encryption.
If you would like to use several Base DNs, simply add more entries under `baseDNs`.

View File

@@ -20,13 +20,13 @@ To integrate this backend with your webapp, you will need to implement the REST
|--------------------------------------|------------------------------------------------|------------------------------------------------------|
| `rest.enabled` | `false` | Globally enable/disable the REST backend |
| `rest.host` | *None* | Default base URL to use for the different endpoints. |
| `rest.endpoints.auth` | `/_mxisd/backend/api/v1/auth/login` | Validate credentials and get user profile |
| `rest.endpoints.directory` | `/_mxisd/backend/api/v1/directory/user/search` | Search for users by arbitrary input |
| `rest.endpoints.identity.single` | `/_mxisd/backend/api/v1/identity/single` | Endpoint to query a single 3PID |
| `rest.endpoints.identity.bulk` | `/_mxisd/backend/api/v1/identity/bulk` | Endpoint to query a list of 3PID |
| `rest.endpoints.profile.displayName` | `/_mxisd/backend/api/v1/profile/displayName` | Query the display name for a Matrix ID
| `rest.endpoints.profile.threepids` | `/_mxisd/backend/api/v1/profile/threepids` | Query the 3PIDs for a Matrix ID
| `rest.endpoints.profile.roles` | `/_mxisd/backend/api/v1/profile/roles` | Query the Roles for a Matrix ID
| `rest.endpoints.auth` | `/_ma1sd/backend/api/v1/auth/login` | Validate credentials and get user profile |
| `rest.endpoints.directory` | `/_ma1sd/backend/api/v1/directory/user/search` | Search for users by arbitrary input |
| `rest.endpoints.identity.single` | `/_ma1sd/backend/api/v1/identity/single` | Endpoint to query a single 3PID |
| `rest.endpoints.identity.bulk` | `/_ma1sd/backend/api/v1/identity/bulk` | Endpoint to query a list of 3PID |
| `rest.endpoints.profile.displayName` | `/_ma1sd/backend/api/v1/profile/displayName` | Query the display name for a Matrix ID
| `rest.endpoints.profile.threepids` | `/_ma1sd/backend/api/v1/profile/threepids` | Query the 3PIDs for a Matrix ID
| `rest.endpoints.profile.roles` | `/_ma1sd/backend/api/v1/profile/roles` | Query the Roles for a Matrix ID
Endpoint values can handle two formats:
- URL Path starting with `/` that gets happened to the `rest.host`

View File

@@ -80,7 +80,7 @@ sql:
type: <string>
value: <string>
```
For each query, `type` can be used to tell mxisd how to process the ID column:
For each query, `type` can be used to tell ma1sd how to process the ID column:
- `localpart` will append the `matrix.domain` to it
- `mxid` will use the ID as-is. If it is not a valid Matrix ID, the search will fail.
@@ -114,7 +114,7 @@ sql:
medium:
mediumTypeExample: <dedicated query>
```
`type` is used to tell mxisd how to process the returned `uid` column containing the User ID:
`type` is used to tell ma1sd how to process the returned `uid` column containing the User ID:
- `localpart` will build a full Matrix ID using the `matrix.domain` value.
- `mxid` will use the ID as-is. If it is not a valid Matrix ID, lookup(s) will fail.
@@ -135,8 +135,8 @@ sql:
```
For the `role` query, `type` can be used to tell mxisd how to inject the User ID in the query:
- `localpart` will extract and set only the localpart.
For the `role` query, `type` can be used to tell ma1sd how to inject the User ID in the query:
- `uid` will extract and set only the localpart.
- `mxid` will use the ID as-is.
On each query, the first parameter `?` is set as a string with the corresponding ID format.

View File

@@ -29,9 +29,9 @@ define('JWT_AUTH_SECRET_KEY', 'your-top-secret-key');
#### Rewrite of `index.php`
Wordpress is normally configured with rewrite of `index.php` so it does not appear in URLs.
If this is not the case for your installation, the mxisd URL will need to be appended with `/index.php`
If this is not the case for your installation, the ma1sd URL will need to be appended with `/index.php`
### mxisd
### ma1sd
Enable in the configuration:
```yaml
wordpress:

View File

@@ -31,8 +31,8 @@ notification:
text: <Path to file containing the raw text part of the email. Do not set to not use one>
html: <Path to file containing the HTML part of the email. Do not set to not use one>
unbind:
fraudulent:
subject: <Subject of the email notification sent for potentially fraudulent 3PID unbinds>
notification:
subject: <Subject of the email notification sent for 3PID unbinds>
body:
text: <Path to file containing the raw text part of the email. Do not set to not use one>
html: <Path to file containing the raw text part of the email. Do not set to not use one>

View File

@@ -9,7 +9,7 @@ provide your own custom templates.
Templates for the following events/actions are available:
- [3PID invite](../../features/identity.md)
- [3PID session: validation](../session/session.md)
- [3PID session: fraudulent unbind](https://github.com/kamax-matrix/mxisd/wiki/mxisd-and-your-privacy#improving-your-privacy-one-commit-at-the-time)
- [3PID session: unbind](https://github.com/kamax-matrix/ma1sd/wiki/ma1sd-and-your-privacy#improving-your-privacy-one-commit-at-the-time)
- [Matrix ID invite](../../features/experimental/application-service.md#email-notification-about-room-invites-by-matrix-ids)
## Placeholders
@@ -19,29 +19,33 @@ All placeholders **MUST** be surrounded with `%` in the template. Per example, t
### Global
The following placeholders are available in every template:
| Placeholder | Purpose |
|---------------------|------------------------------------------------------------------------------|
| `DOMAIN` | Identity server authoritative domain, as configured in `matrix.domain` |
| `DOMAIN_PRETTY` | Same as `DOMAIN` with the first letter upper case and all other lower case |
| `FROM_EMAIL` | Email address configured in `threepid.medium.<3PID medium>.identity.from` |
| `FROM_NAME` | Name configured in `threepid.medium.<3PID medium>.identity.name` |
| `RECIPIENT_MEDIUM` | The 3PID medium, like `email` or `msisdn` |
| `RECIPIENT_ADDRESS` | The address to which the notification is sent |
| Placeholder | Purpose |
|---------------------------------|------------------------------------------------------------------------------|
| `DOMAIN` | Identity server authoritative domain, as configured in `matrix.domain` |
| `DOMAIN_PRETTY` | Same as `DOMAIN` with the first letter upper case and all other lower case |
| `FROM_EMAIL` | Email address configured in `threepid.medium.<3PID medium>.identity.from` |
| `FROM_NAME` | Name configured in `threepid.medium.<3PID medium>.identity.name` |
| `RECIPIENT_MEDIUM` | The 3PID medium, like `email` or `msisdn` |
| `RECIPIENT_MEDIUM_URL_ENCODED` | URL encoded value of `RECIPIENT_MEDIUM` |
| `RECIPIENT_ADDRESS` | The address to which the notification is sent |
| `RECIPIENT_ADDRESS_URL_ENCODED` | URL encoded value of `RECIPIENT_ADDRESS` |
### Room invitation
Specific placeholders:
| Placeholder | Purpose |
|---------------------|------------------------------------------------------------------------------------------|
| `SENDER_ID` | Matrix ID of the user who made the invite |
| `SENDER_NAME` | Display name of the user who made the invite, if not available/set, empty |
| `SENDER_NAME_OR_ID` | Display name of the user who made the invite. If not available/set, its Matrix ID |
| `INVITE_MEDIUM` | The 3PID medium for the invite. |
| `INVITE_ADDRESS` | The 3PID address for the invite. |
| `ROOM_ID` | The Matrix ID of the Room in which the invite took place |
| `ROOM_NAME` | The Name of the room in which the invite took place. If not available/set, empty |
| `ROOM_NAME_OR_ID` | The Name of the room in which the invite took place. If not available/set, its Matrix ID |
| `REGISTER_URL` | The URL to provide to the user allowing them to register their account, if needed |
| Placeholder | Purpose |
|------------------------------|-----------------------------------------------------------------------------------|
| `SENDER_ID` | Matrix ID of the user who made the invite |
| `SENDER_NAME` | Display name of the user who made the invite, if not available/set, empty |
| `SENDER_NAME_OR_ID` | Display name of the user who made the invite. If not available/set, its Matrix ID |
| `INVITE_MEDIUM` | The 3PID medium for the invite. |
| `INVITE_MEDIUM_URL_ENCODED` | URL encoded value of `INVITE_MEDIUM` |
| `INVITE_ADDRESS` | The 3PID address for the invite. |
| `INVITE_ADDRESS_URL_ENCODED` | URL encoded value of `INVITE_ADDRESS` |
| `ROOM_ID` | The Matrix ID of the Room in which the invite took place |
| `ROOM_NAME` | The Name of the room in which the invite took place. If not available/set, empty |
| `ROOM_NAME_OR_ID` | The Name of the room in which the invite took place. If not available/set, its ID |
| `REGISTER_URL` | The URL to provide to the user allowing them to register their account, if needed |
### Validation of 3PID Session
Specific placeholders:
@@ -53,8 +57,8 @@ Specific placeholders:
| `NEXT_URL` | URL to redirect to after the sessions has been validated. |
## Templates
mxisd comes with a set of builtin templates to easily get started. Those templates can be found
[in the repository](https://github.com/kamax-matrix/mxisd/tree/master/src/main/resources/threepids). If you want to use
ma1sd comes with a set of builtin templates to easily get started. Those templates can be found
[in the repository](https://github.com/ma1uta/ma1sd/tree/master/src/main/resources/threepids). If you want to use
customized templates, we recommend using the builtin templates as a starting point.
> **NOTE**: The link above point to the latest version of the built-in templates. Those might be different from your
@@ -67,7 +71,7 @@ under the namespace `threepid.medium.<medium>.generators.template`.
Under such namespace, the following keys are available:
- `invite`: Path to the 3PID invite notification template
- `session.validation`: Path to the 3PID session validation notification template
- `session.unbind.fraudulent`: Path to the 3PID session fraudulent unbind notification template
- `session.unbind`: Path to the 3PID session unbind notification template
- `generic.matrixId`: Path to the Matrix ID invite notification template
- `placeholder`: Map of key/values to set static values for some placeholders.
@@ -100,7 +104,7 @@ threepid:
session:
validation: '/path/to/validate-template.eml'
unbind:
fraudulent: '/path/to/unbind-fraudulent-template.eml'
notification: '/path/to/unbind-notification-template.eml'
generic:
matrixId: '/path/to/mxid-invite-template.eml'
placeholder:

View File

@@ -26,6 +26,14 @@ Two configuration keys are available that accept paths to HTML templates:
- `success`
- `failure`
### Serving static assets
ma1sd will not serve any static asset (images, JS, CSS, etc.). If such are needed, you will need to serve them using the
reverse proxy sitting in front of ma1sd using a path outside of the `/_matrix/identity/` namespace. We advise using
the base path `/static/` for such use cases, allowing to remain under the same hostname/origin.
You can also serve such assets using absolute URL, possibly under other domains, but be aware of Cross-Origin restrictions
in browsers which are out of scope of ma1sd.
## Placeholders
### Success
No object/placeholder are currently available.

View File

@@ -30,11 +30,11 @@ by a 3PID, allowing it to be resolved to a Matrix ID.
## Restrictions
### Bindings
mxisd does not store bindings directly. While a user can see its email, phone number or any other 3PID in its
ma1sd does not store bindings directly. While a user can see its email, phone number or any other 3PID in its
settings/profile, it does **NOT** mean it is published/saved anywhere or can be used to invite/search the user.
Identity stores are the ones holding such data, irrelevant if a user added a 3PID to their profile. When queried for
bindings, mxisd will query Identity stores which are responsible to store this kind of information.
bindings, ma1sd will query Identity stores which are responsible to store this kind of information.
Therefore, by default, any 3PID added to a user profile which is NOT within a configured and enabled Identity backend
will simply not be usable for search or invites, **even on the same Homeserver!**
@@ -60,7 +60,7 @@ Example: a user from Homeserver `example.org` adds an email `john@gmail.com`.
If a federated lookup was performed, Identity servers would try to find the 3PID bind at the `gmail.com` server, and
not `example.org`.
As mxisd is built for self-hosted use cases, mainly for orgs/corps, this is usually not a problem for emails.
As ma1sd is built for self-hosted use cases, mainly for orgs/corps, this is usually not a problem for emails.
Sadly, there is currently no mechanism to make this work for phone numbers.
## Notifications
@@ -68,7 +68,7 @@ Sadly, there is currently no mechanism to make this work for phone numbers.
Identity server that received the request. This is usually done by means of a URL to visit for email or a short number
received by SMS for phone numbers.
mxisd use two components for this:
ma1sd use two components for this:
- Generator which produces the message to be sent with the necessary information the user needs to validate their session.
- Connector which actually send the notification (e.g. SMTP for email).
@@ -103,8 +103,8 @@ session:
validation:
enabled: true
unbind:
fraudulent:
sendWarning: true
notifications: true
enabled: true
# DO NOT COPY/PASTE AS-IS IN YOUR CONFIGURATION
# CONFIGURATION EXAMPLE
@@ -115,11 +115,7 @@ are allowed to do in terms of 3PID sessions. The policy has a global on/off swit
---
`unbind.fraudulent` controls warning notifications if an illegal/fraudulent 3PID removal is attempted on the Identity server.
This is directly related to synapse disregard for privacy and new GDPR laws in Europe in an attempt to inform users about
potential privacy leaks.
For more information, see the corresponding [synapse issue](https://github.com/matrix-org/synapse/issues/4540).
`unbind` controls warning notifications for 3PID removal. Setting `notifications` for `unbind` to false will prevent unbind emails from sending.
### Web views
Once a user click on a validation link, it is taken to the Identity Server validation page where the token is submitted.
@@ -134,8 +130,8 @@ on how to configure/customize/brand those pages to your liking.
This configuration would disable 3PID sessions altogether, preventing users from validating emails and/or phone numbers
and any subsequent actions that requires them, like adding them to their profiles.
This would be used if mxisd is also performing authentication for the Homeserver, typically with synapse and the
[REST password provider](https://github.com/kamax-matrix/matrix-synapse-rest-auth), where 3PID mappings would be
This would be used if ma1sd is also performing authentication for the Homeserver, typically with synapse and the
[REST password provider](https://github.com/ma1uta/matrix-synapse-rest-password-provider), where 3PID mappings would be
auto-populated.
Use the following values to enable this mode:

View File

@@ -7,11 +7,11 @@
- [Submit an issue](#submit-an-issue)
## Purpose
This document describes basic troubleshooting steps for mxisd.
This document describes basic troubleshooting steps for ma1sd.
## Logs
### Locations
mxisd logs to `STDOUT` (Standard Output) and `STDERR` (Standard Error) only, which gets redirected
ma1sd logs to `STDOUT` (Standard Output) and `STDERR` (Standard Error) only, which gets redirected
to log file(s) depending on your system.
If you use the [Debian package](install/debian.md), this goes to `syslog`.
@@ -22,13 +22,13 @@ For any other platform, please refer to your package maintainer.
### Increase verbosity
To increase log verbosity and better track issues, the following means are available:
- Add the `-v` command line parameter
- Use the environment variable and value `MXISD_LOG_LEVEL=debug`
- Use the environment variable and value `MA1SD_LOG_LEVEL=debug`
### Reading them
Before reporting an issue, it is important to produce clean and complete logs so they can be understood.
It is usually useless to try to troubleshoot an issue based on a single log line. Any action or API request
in mxisd would trigger more than one log lines, and those would be considered necessary context to
in ma1sd would trigger more than one log lines, and those would be considered necessary context to
understand what happened.
You may also find things called *stacktraces*. Those are important to pin-point bugs and the likes and should

Binary file not shown.

View File

@@ -1,5 +1,7 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-5.3.1-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.14.3-all.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists

301
gradlew vendored
View File

@@ -1,13 +1,13 @@
#!/usr/bin/env sh
#!/bin/sh
#
# Copyright 2015 the original author or authors.
# Copyright © 2015-2021 the original authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
@@ -15,80 +15,115 @@
# See the License for the specific language governing permissions and
# limitations under the License.
#
# SPDX-License-Identifier: Apache-2.0
#
##############################################################################
##
## Gradle start up script for UN*X
##
#
# Gradle start up script for POSIX generated by Gradle.
#
# Important for running:
#
# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
# noncompliant, but you have some other compliant shell such as ksh or
# bash, then to run this script, type that shell name before the whole
# command line, like:
#
# ksh Gradle
#
# Busybox and similar reduced shells will NOT work, because this script
# requires all of these POSIX shell features:
# * functions;
# * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
# «${var#prefix}», «${var%suffix}», and «$( cmd )»;
# * compound commands having a testable exit status, especially «case»;
# * various built-in commands including «command», «set», and «ulimit».
#
# Important for patching:
#
# (2) This script targets any POSIX shell, so it avoids extensions provided
# by Bash, Ksh, etc; in particular arrays are avoided.
#
# The "traditional" practice of packing multiple parameters into a
# space-separated string is a well documented source of bugs and security
# problems, so this is (mostly) avoided, by progressively accumulating
# options in "$@", and eventually passing that to Java.
#
# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
# see the in-line comments for details.
#
# There are tweaks for specific operating systems such as AIX, CygWin,
# Darwin, MinGW, and NonStop.
#
# (3) This script is generated from the Groovy template
# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
# within the Gradle project.
#
# You can find Gradle at https://github.com/gradle/gradle/.
#
##############################################################################
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
PRG="$0"
# Need this for relative symlinks.
while [ -h "$PRG" ] ; do
ls=`ls -ld "$PRG"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
PRG="$link"
else
PRG=`dirname "$PRG"`"/$link"
fi
app_path=$0
# Need this for daisy-chained symlinks.
while
APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
[ -h "$app_path" ]
do
ls=$( ls -ld "$app_path" )
link=${ls#*' -> '}
case $link in #(
/*) app_path=$link ;; #(
*) app_path=$APP_HOME$link ;;
esac
done
SAVED="`pwd`"
cd "`dirname \"$PRG\"`/" >/dev/null
APP_HOME="`pwd -P`"
cd "$SAVED" >/dev/null
APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"`
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
# This is normally unused
# shellcheck disable=SC2034
APP_BASE_NAME=${0##*/}
# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s\n' "$PWD" ) || exit
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum"
MAX_FD=maximum
warn () {
echo "$*"
}
} >&2
die () {
echo
echo "$*"
echo
exit 1
}
} >&2
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
nonstop=false
case "`uname`" in
CYGWIN* )
cygwin=true
;;
Darwin* )
darwin=true
;;
MINGW* )
msys=true
;;
NONSTOP* )
nonstop=true
;;
case "$( uname )" in #(
CYGWIN* ) cygwin=true ;; #(
Darwin* ) darwin=true ;; #(
MSYS* | MINGW* ) msys=true ;; #(
NONSTOP* ) nonstop=true ;;
esac
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
CLASSPATH="\\\"\\\""
# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD="$JAVA_HOME/jre/sh/java"
JAVACMD=$JAVA_HOME/jre/sh/java
else
JAVACMD="$JAVA_HOME/bin/java"
JAVACMD=$JAVA_HOME/bin/java
fi
if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
@@ -97,92 +132,120 @@ Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
JAVACMD="java"
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
JAVACMD=java
if ! command -v java >/dev/null 2>&1
then
die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
fi
# Increase the maximum file descriptors if we can.
if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
MAX_FD_LIMIT=`ulimit -H -n`
if [ $? -eq 0 ] ; then
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
MAX_FD="$MAX_FD_LIMIT"
fi
ulimit -n $MAX_FD
if [ $? -ne 0 ] ; then
warn "Could not set maximum file descriptor limit: $MAX_FD"
fi
else
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
fi
fi
# For Darwin, add options to specify how the application appears in the dock
if $darwin; then
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
fi
# For Cygwin, switch paths to Windows format before running java
if $cygwin ; then
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
JAVACMD=`cygpath --unix "$JAVACMD"`
# We build the pattern for arguments to be converted via cygpath
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
SEP=""
for dir in $ROOTDIRSRAW ; do
ROOTDIRS="$ROOTDIRS$SEP$dir"
SEP="|"
done
OURCYGPATTERN="(^($ROOTDIRS))"
# Add a user-defined pattern to the cygpath arguments
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
fi
# Now convert the arguments - kludge to limit ourselves to /bin/sh
i=0
for arg in "$@" ; do
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
else
eval `echo args$i`="\"$arg\""
fi
i=$((i+1))
done
case $i in
(0) set -- ;;
(1) set -- "$args0" ;;
(2) set -- "$args0" "$args1" ;;
(3) set -- "$args0" "$args1" "$args2" ;;
(4) set -- "$args0" "$args1" "$args2" "$args3" ;;
(5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
(6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
(7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
(8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
(9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
case $MAX_FD in #(
max*)
# In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
# shellcheck disable=SC2039,SC3045
MAX_FD=$( ulimit -H -n ) ||
warn "Could not query maximum file descriptor limit"
esac
case $MAX_FD in #(
'' | soft) :;; #(
*)
# In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
# shellcheck disable=SC2039,SC3045
ulimit -n "$MAX_FD" ||
warn "Could not set maximum file descriptor limit to $MAX_FD"
esac
fi
# Escape application args
save () {
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
echo " "
}
APP_ARGS=$(save "$@")
# Collect all arguments for the java command, stacking in reverse order:
# * args from the command line
# * the main class name
# * -classpath
# * -D...appname settings
# * --module-path (only if needed)
# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
# Collect all arguments for the java command, following the shell quoting and substitution rules
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
# For Cygwin or MSYS, switch paths to Windows format before running java
if "$cygwin" || "$msys" ; then
APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
cd "$(dirname "$0")"
JAVACMD=$( cygpath --unix "$JAVACMD" )
# Now convert the arguments - kludge to limit ourselves to /bin/sh
for arg do
if
case $arg in #(
-*) false ;; # don't mess with options #(
/?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
[ -e "$t" ] ;; #(
*) false ;;
esac
then
arg=$( cygpath --path --ignore --mixed "$arg" )
fi
# Roll the args list around exactly as many times as the number of
# args, so each arg winds up back in the position where it started, but
# possibly modified.
#
# NB: a `for` loop captures its iteration list before it begins, so
# changing the positional parameters here affects neither the number of
# iterations, nor the values presented in `arg`.
shift # remove old arg
set -- "$@" "$arg" # push replacement arg
done
fi
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
# Collect all arguments for the java command:
# * DEFAULT_JVM_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
# and any embedded shellness will be escaped.
# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be
# treated as '${Hostname}' itself on the command line.
set -- \
"-Dorg.gradle.appname=$APP_BASE_NAME" \
-classpath "$CLASSPATH" \
-jar "$APP_HOME/gradle/wrapper/gradle-wrapper.jar" \
"$@"
# Stop when "xargs" is not available.
if ! command -v xargs >/dev/null 2>&1
then
die "xargs is not available"
fi
# Use "xargs" to parse quoted args.
#
# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
#
# In Bash we could simply go:
#
# readarray ARGS < <( xargs -n1 <<<"$var" ) &&
# set -- "${ARGS[@]}" "$@"
#
# but POSIX shell has neither arrays nor command substitution, so instead we
# post-process each arg (as a line of input to sed) to backslash-escape any
# character that might be a shell metacharacter, then use eval to reverse
# that process (while maintaining the separation between arguments), and wrap
# the whole thing up as a single "set" statement.
#
# This will of course break if any of these variables contains a newline or
# an unmatched quote.
#
eval "set -- $(
printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
xargs -n1 |
sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
tr '\n' ' '
)" '"$@"'
exec "$JAVACMD" "$@"

194
gradlew.bat vendored
View File

@@ -1,100 +1,94 @@
@rem
@rem Copyright 2015 the original author or authors.
@rem
@rem Licensed under the Apache License, Version 2.0 (the "License");
@rem you may not use this file except in compliance with the License.
@rem You may obtain a copy of the License at
@rem
@rem http://www.apache.org/licenses/LICENSE-2.0
@rem
@rem Unless required by applicable law or agreed to in writing, software
@rem distributed under the License is distributed on an "AS IS" BASIS,
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@rem See the License for the specific language governing permissions and
@rem limitations under the License.
@rem
@if "%DEBUG%" == "" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@rem
@rem ##########################################################################
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto init
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto init
echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:init
@rem Get command-line arguments, handling Windows variants
if not "%OS%" == "Windows_NT" goto win9xME_args
:win9xME_args
@rem Slurp the command line arguments.
set CMD_LINE_ARGS=
set _SKIP=2
:win9xME_args_slurp
if "x%~1" == "x" goto execute
set CMD_LINE_ARGS=%*
:execute
@rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
:end
@rem End local scope for the variables with windows NT shell
if "%ERRORLEVEL%"=="0" goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
exit /b 1
:mainEnd
if "%OS%"=="Windows_NT" endlocal
:omega
@rem
@rem Copyright 2015 the original author or authors.
@rem
@rem Licensed under the Apache License, Version 2.0 (the "License");
@rem you may not use this file except in compliance with the License.
@rem You may obtain a copy of the License at
@rem
@rem https://www.apache.org/licenses/LICENSE-2.0
@rem
@rem Unless required by applicable law or agreed to in writing, software
@rem distributed under the License is distributed on an "AS IS" BASIS,
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@rem See the License for the specific language governing permissions and
@rem limitations under the License.
@rem
@rem SPDX-License-Identifier: Apache-2.0
@rem
@if "%DEBUG%"=="" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@rem
@rem ##########################################################################
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
set DIRNAME=%~dp0
if "%DIRNAME%"=="" set DIRNAME=.
@rem This is normally unused
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if %ERRORLEVEL% equ 0 goto execute
echo. 1>&2
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2
echo. 1>&2
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
echo location of your Java installation. 1>&2
goto fail
:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto execute
echo. 1>&2
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2
echo. 1>&2
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
echo location of your Java installation. 1>&2
goto fail
:execute
@rem Setup the command line
set CLASSPATH=
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %*
:end
@rem End local scope for the variables with windows NT shell
if %ERRORLEVEL% equ 0 goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
set EXIT_CODE=%ERRORLEVEL%
if %EXIT_CODE% equ 0 set EXIT_CODE=1
if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
exit /b %EXIT_CODE%
:mainEnd
if "%OS%"=="Windows_NT" endlocal
:omega

219
mxids.example.yaml Normal file
View File

@@ -0,0 +1,219 @@
# Sample configuration file explaining the minimum required keys to be set to run ma1sd
#
# For a complete list of options, see https://github.com/ma1uta/ma1sd/docs/README.md
#
# Please follow the Getting Started guide if this is your first time using/configuring ma1sd
#
# -- https://github.com/ma1uta/ma1sd/blob/master/docs/getting-started.md#getting-started
#
#######################
# Matrix config items #
#######################
# Matrix domain, same as the domain configure in your Homeserver configuration.
# NOTE: in Synapse Homeserver, the Matrix domain is defined as 'server_name' in configuration file.
#
# This is used to build the various identifiers in all the features.
#
# If the hostname of the public URL used to reach your Matrix services is different from your Matrix domain,
# per example matrix.domain.tld vs domain.tld, then use the server.name configuration option.
# See the "Configure" section of the Getting Started guide for more info.
#
matrix:
domain: ''
v1: false # deprecated
v2: true # MSC2140 API v2. Riot require enabled V2 API.
################
# Signing keys #
################
# Absolute path for the Identity Server signing keys database.
# /!\ THIS MUST **NOT** BE YOUR HOMESERVER KEYS FILE /!\
# If this path does not exist, it will be auto-generated.
#
# During testing, /var/tmp/mxids/keys is a possible value
# For production, recommended location shall be one of the following:
# - /var/lib/mxids/keys
# - /var/opt/mxids/keys
# - /var/local/mxids/keys
#
key:
path: ''
# Path to the SQLite DB file for ma1sd internal storage
# /!\ THIS MUST **NOT** BE YOUR HOMESERVER DATABASE /!\
#
# Examples:
# - /var/opt/mxids/store.db
# - /var/local/mxids/store.db
# - /var/lib/mxids/store.db
#
storage:
# backend: sqlite # or postgresql
provider:
sqlite:
database: '/path/to/mxids.db'
# postgresql:
# # Wrap all string values with quotes to avoid yaml parsing mistakes
# database: '//localhost/mxids' # or full variant //192.168.1.100:5432/mxids_database
# username: 'mxids_user'
# password: 'mxids_password'
#
# # Pool configuration for postgresql backend.
# #######
# # Enable or disable pooling
# pool: false
#
# #######
# # Check database connection before get from pool
# testBeforeGetFromPool: false # or true
#
# #######
# # There is an internal thread which checks each of the database connections as a keep-alive mechanism. This set the
# # number of milliseconds it sleeps between checks -- default is 30000. To disable the checking thread, set this to
# # 0 before you start using the connection source.
# checkConnectionsEveryMillis: 30000
#
# #######
# # Set the number of connections that can be unused in the available list.
# maxConnectionsFree: 5
#
# #######
# # Set the number of milliseconds that a connection can stay open before being closed. Set to 9223372036854775807 to have
# # the connections never expire.
# maxConnectionAgeMillis: 3600000
###################
# Identity Stores #
###################
# If you are using synapse standalone and do not have an Identity store,
# see https://github.com/ma1uta/ma1sd/blob/master/docs/stores/synapse.md#synapse-identity-store
#
# If you would like to integrate with your AD/Samba/LDAP server,
# see https://github.com/ma1uta/ma1sd/blob/master/docs/stores/ldap.md
#
# For any other Identity store, or to simply discover them,
# see https://github.com/ma1uta/ma1sd/blob/master/docs/stores/README.md
#################################################
# Notifications for invites/addition to profile #
#################################################
# This is mandatory to deal with anything e-mail related.
#
# For an introduction to sessions, invites and 3PIDs in general,
# see https://github.com/ma1uta/ma1sd/blob/master/docs/threepids/session/session.md#3pid-sessions
#
# If you would like to change the content of the notifications,
# see https://github.com/ma1uta/ma1sd/blob/master/docs/threepids/notification/template-generator.md
#
#### E-mail connector
threepid:
medium:
email:
identity:
# The e-mail to send as.
from: "matrix-identity@example.org"
connectors:
smtp:
# SMTP host
host: "smtp.example.org"
# TLS mode for the connection
# Possible values:
# 0 Disable any kind of TLS entirely
# 1 Enable STARTLS if supported by server (default)
# 2 Force STARTLS and fail if not available
# 3 Use full TLS/SSL instead of STARTLS
#
tls: 1
# SMTP port
# Be sure to adapt depending on your TLS choice, if changed from default
port: 587
# Login for SMTP
login: "matrix-identity@example.org"
# Password for the account
password: "ThePassword"
#### MSC2134 (hash lookup)
#hashing:
# enabled: false # enable or disable the hash lookup MSC2140 (default is false)
# pepperLength: 20 # length of the pepper value (default is 20)
# rotationPolicy: per_requests # or `per_seconds` how often the hashes will be updating
# hashStorageType: sql # or `in_memory` where the hashes will be stored
# algorithms:
# - none # the same as v1 bulk lookup
# - sha256 # hash the 3PID and pepper.
# delay: 2m # how often hashes will be updated if rotation policy = per_seconds (default is 10s)
# requests: 10 # how many lookup requests will be performed before updating hashes if rotation policy = per_requests (default is 10)
### hash lookup for synapseSql provider.
# synapseSql:
# lookup:
# query: 'select user_id as mxid, medium, address from user_threepid_id_server' # query for retrive 3PIDs for hashes.
# legacyRoomNames: false # use the old query to get room names.
### hash lookup for ldap provider (with example of the ldap configuration)
# ldap:
# enabled: true
# lookup: true # hash lookup
# activeDirectory: false
# defaultDomain: ''
# connection:
# host: 'ldap.domain.tld'
# port: 389
# bindDn: 'cn=admin,dc=domain,dc=tld'
# bindPassword: 'Secret'
# baseDNs:
# - 'dc=domain,dc=tld'
# attribute:
# uid:
# type: 'uid' # or mxid
# value: 'cn'
# name: 'displayName'
# identity:
# filter: '(objectClass=inetOrgPerson)'
#### MSC2140 (Terms)
#policy:
# policies:
# term_name: # term name
# version: 1.0 # version
# terms:
# en: # lang
# name: term name en # localized name
# url: https://mxids.host.tld/term_en.html # localized url
# fe: # lang
# name: term name fr # localized name
# url: https://mxids.host.tld/term_fr.html # localized url
# regexp:
# - '/_matrix/identity/v2/account.*'
# - '/_matrix/identity/v2/hash_details'
# - '/_matrix/identity/v2/lookup'
#
# logging:
# root: error # default level for all loggers (apps and thirdparty libraries)
# app: info # log level only for the ma1sd
# requests: false # or true to dump full requests and responses
# Config invitation manager
#invite:
# fullDisplayName: true # print full name of the invited user (default false)
# resolution:
# timer: 10
# period: seconds # search invites every 10 seconds (by default 5 minutes)
# Internal API
#internal:
# enabled: true # default to false

View File

@@ -1,111 +0,0 @@
# Sample configuration file explaining the minimum required keys to be set to run mxisd
#
# For a complete list of options, see https://github.com/kamax-matrix/mxisd/docs/README.md
#
# Please follow the Getting Started guide if this is your first time using/configuring mxisd
#
# -- https://github.com/kamax-matrix/mxisd/blob/master/docs/getting-started.md#getting-started
#
#######################
# Matrix config items #
#######################
# Matrix domain, same as the domain configure in your Homeserver configuration.
# NOTE: in Synapse Homeserver, the Matrix domain is defined as 'server_name' in configuration file.
#
# This is used to build the various identifiers in all the features.
#
# If the hostname of the public URL used to reach your Matrix services is different from your Matrix domain,
# per example matrix.domain.tld vs domain.tld, then use the server.name configuration option.
# See the "Configure" section of the Getting Started guide for more info.
#
matrix:
domain: ''
################
# Signing keys #
################
# Absolute path for the Identity Server signing keys database.
# /!\ THIS MUST **NOT** BE YOUR HOMESERVER KEYS FILE /!\
# If this path does not exist, it will be auto-generated.
#
# During testing, /var/tmp/mxisd/keys is a possible value
# For production, recommended location shall be one of the following:
# - /var/lib/mxisd/keys
# - /var/opt/mxisd/keys
# - /var/local/mxisd/keys
#
key:
path: ''
# Path to the SQLite DB file for mxisd internal storage
# /!\ THIS MUST **NOT** BE YOUR HOMESERVER DATABASE /!\
#
# Examples:
# - /var/opt/mxisd/store.db
# - /var/local/mxisd/store.db
# - /var/lib/mxisd/store.db
#
storage:
provider:
sqlite:
database: '/path/to/mxisd.db'
###################
# Identity Stores #
###################
# If you are using synapse standalone and do not have an Identity store,
# see https://github.com/kamax-matrix/mxisd/blob/master/docs/stores/synapse.md#synapse-identity-store
#
# If you would like to integrate with your AD/Samba/LDAP server,
# see https://github.com/kamax-matrix/mxisd/blob/master/docs/stores/ldap.md
#
# For any other Identity store, or to simply discover them,
# see https://github.com/kamax-matrix/mxisd/blob/master/docs/stores/README.md
#################################################
# Notifications for invites/addition to profile #
#################################################
# This is mandatory to deal with anything e-mail related.
#
# For an introduction to sessions, invites and 3PIDs in general,
# see https://github.com/kamax-matrix/mxisd/blob/master/docs/threepids/session/session.md#3pid-sessions
#
# If you would like to change the content of the notifications,
# see https://github.com/kamax-matrix/mxisd/blob/master/docs/threepids/notification/template-generator.md
#
#### E-mail connector
threepid:
medium:
email:
identity:
# The e-mail to send as.
from: "matrix-identity@example.org"
connectors:
smtp:
# SMTP host
host: "smtp.example.org"
# TLS mode for the connection
# Possible values:
# 0 Disable any kind of TLS entirely
# 1 Enable STARTLS if supported by server (default)
# 2 Force STARTLS and fail if not available
# 3 Use full TLS/SSL instead of STARTLS
#
tls: 1
# SMTP port
# Be sure to adapt depending on your TLS choice, if changed from default
port: 587
# Login for SMTP
login: "matrix-identity@example.org"
# Password for the account
password: "ThePassword"

11
renovate.json Normal file
View File

@@ -0,0 +1,11 @@
{
"extends": [
"config:base"
],
"packageRules": [
{
"updateTypes": ["minor", "patch", "pin", "digest"],
"automerge": true
}
]
}

View File

@@ -1,9 +1,9 @@
Package: mxisd
Maintainer: Kamax.io <foss@kamax.io>
Homepage: https://github.com/kamax-matrix/mxisd
Package: mxids
Maintainer: ma1uta <sablintolya@gmail.com>
Homepage: https://git.cqre.net/cqrenet/mxids.git
Description: Federated Matrix Identity Server
Architecture: all
Section: net
Priority: optional
Depends: openjdk-8-jre | openjdk-8-jre-headless | openjdk-8-jdk | openjdk-8-jdk-headless
Depends: openjdk-8-jre | openjdk-8-jre-headless | openjdk-8-jdk | openjdk-8-jdk-headless | openjdk-11-jre | openjdk-11-jre-headless | openjdk-11-jdk | openjdk-11-jdk-headless
Version: 0

View File

@@ -1,13 +1,19 @@
#!/bin/bash -e
# Add service account
useradd -r mxisd || true
useradd -r mxids || true
# Set permissions for data directory
chown -R mxisd:mxisd %DEB_DATA_DIR%
chown -R mxids:mxids %DEB_DATA_DIR%
# Create symlink to mxisd run script
ln -sfT /usr/lib/mxisd/mxisd /usr/bin/mxisd
# Create symlink to mxids run script
ln -sfT /usr/lib/mxids/mxids /usr/bin/mxids
# Enable systemd service
systemctl enable mxisd.service
systemctl enable mxids.service
# If we already have a config file setup, we attempt to run mxids automatically
# Specifically targeted at upgrades where the service needs to be restarted
if [ -f "%DEB_CONF_FILE%" ]; then
systemctl restart mxids.service
fi

View File

@@ -1,10 +1,10 @@
#!/bin/bash
# Stop running instance if needed
systemctl stop mxisd.service
systemctl stop mxids.service
# Disable service if exists
systemctl disable mxisd.service
systemctl disable mxids.service
# remove symlink
rm /usr/bin/mxisd
rm /usr/bin/mxids

View File

@@ -27,8 +27,8 @@ if [[ -n "$CONF_FILE_PATH" ]] && [ ! -f "$CONF_FILE_PATH" ]; then
echo >> "$CONF_FILE_PATH"
fi
echo "Starting mxisd..."
echo "Starting mxids..."
echo
fi
exec java -jar /app/mxisd.jar -c /etc/mxisd/mxisd.yaml
exec java -jar /app/mxids.jar -c /etc/mxids/mxids.yaml

View File

@@ -0,0 +1,33 @@
/*
* matrix-java-sdk - Matrix Client SDK for Java
* Copyright (C) 2018 Kamax Sarl
*
* https://www.kamax.io/
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package io.kamax.matrix;
public class MalformedEventException extends MatrixException {
public MalformedEventException(String s) {
super("M_NOT_JSON", s);
}
public static MalformedEventException forId(String id) {
return new MalformedEventException("Event " + id + " is malformed");
}
}

View File

@@ -0,0 +1,44 @@
/*
* matrix-java-sdk - Matrix Client SDK for Java
* Copyright (C) 2017 Kamax Sarl
*
* https://www.kamax.io/
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package io.kamax.matrix;
public class MatrixErrorInfo {
private String errcode;
private String error;
public MatrixErrorInfo(String errcode) {
this.errcode = errcode;
}
public MatrixErrorInfo(Throwable t) {
this.errcode = "AS_INTERNAL_SERVER_ERROR";
}
public String getErrcode() {
return errcode;
}
public String getError() {
return error;
}
}

View File

@@ -0,0 +1,48 @@
/*
* matrix-java-sdk - Matrix Client SDK for Java
* Copyright (C) 2018 Kamax Sarl
*
* https://www.kamax.io/
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package io.kamax.matrix;
public class MatrixException extends RuntimeException {
private String errorCode;
private String error;
public MatrixException(String errorCode, String error) {
super(errorCode + ": " + error);
this.errorCode = errorCode;
this.error = error;
}
public MatrixException(String errorCode, String error, Throwable t) {
super(errorCode + ": " + error, t);
this.errorCode = errorCode;
this.error = error;
}
public String getErrorCode() {
return errorCode;
}
public String getError() {
return error;
}
}

View File

@@ -0,0 +1,170 @@
/*
* matrix-java-sdk - Matrix Client SDK for Java
* Copyright (C) 2017 Kamax Sarl
*
* https://www.kamax.io/
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package io.kamax.matrix;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class MatrixID implements _MatrixID {
public static class Builder {
private MatrixID mxId;
public Builder(String id) {
mxId = MatrixID.parse(id);
}
public MatrixID valid() {
if (!mxId.isValid()) {
throw new IllegalArgumentException(mxId + " is not a valid Matrix ID");
}
return mxId;
}
public MatrixID acceptable() {
if (!mxId.isAcceptable()) {
throw new IllegalArgumentException(mxId + " is not an acceptable Matrix ID");
}
return mxId;
}
}
public static final String ALLOWED_CHARS = "0-9a-z-.=_/";
public static final Pattern LAX_PATTERN = Pattern.compile("@(.*?):(.+)");
public static final Pattern STRICT_PATTERN = Pattern.compile("@([" + ALLOWED_CHARS + "]+):(.+)");
private String id;
private String localpart;
private String domain;
private static String buildRaw(String localpart, String domain) {
return "@" + localpart + ":" + domain;
}
private static MatrixID parse(String id) {
Matcher m = LAX_PATTERN.matcher(id);
if (!m.matches()) {
throw new IllegalArgumentException(id + " is not a Matrix ID");
}
MatrixID mxId = new MatrixID();
mxId.id = id;
mxId.localpart = m.group(1);
mxId.domain = m.group(2);
return mxId;
}
public static Builder from(String id) {
return new Builder(id);
}
public static Builder from(String local, String domain) {
return from(buildRaw(local, domain));
}
public static MatrixID asValid(String id) {
return new Builder(id).valid();
}
public static MatrixID asAcceptable(String local, String domain) {
return from(local, domain).acceptable();
}
public static MatrixID asAcceptable(String id) {
return from(id).acceptable();
}
private MatrixID() {
// not for public consumption
}
private MatrixID(MatrixID mxId) {
this.id = mxId.id;
this.localpart = mxId.localpart;
this.domain = mxId.domain;
}
@Deprecated
public MatrixID(String mxId) {
this(parse(mxId));
}
@Deprecated
public MatrixID(String localpart, String domain) {
this(parse(buildRaw(localpart, domain)));
}
@Override
public String getId() {
return id;
}
@Override
public String getLocalPart() {
return localpart;
}
@Override
public String getDomain() {
return domain;
}
@Override
public MatrixID canonicalize() {
return parse(getId().toLowerCase());
}
@Override
public boolean isValid() {
return isAcceptable() && STRICT_PATTERN.matcher(id).matches();
}
@Override
public boolean isAcceptable() {
// TODO properly implement
return id.length() <= 255;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof MatrixID)) return false;
MatrixID matrixID = (MatrixID) o;
return id.equals(matrixID.id);
}
@Override
public int hashCode() {
return id.hashCode();
}
@Override
public String toString() {
return getId();
}
}

View File

@@ -0,0 +1,93 @@
/*
* matrix-java-sdk - Matrix Client SDK for Java
* Copyright (C) 2018 Kamax Sarl
*
* https://www.kamax.io/
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package io.kamax.matrix;
import org.apache.commons.codec.DecoderException;
import org.apache.commons.codec.binary.Hex;
import java.nio.charset.StandardCharsets;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import static io.kamax.matrix.MatrixID.ALLOWED_CHARS;
public class MatrixIdCodec {
public static final String DELIMITER = "=";
public static final String ENCODE_REGEX = "[^" + ALLOWED_CHARS + "]+";
public static final Pattern ENCODE_PATTERN = Pattern.compile(ENCODE_REGEX);
public static final Pattern DECODE_PATTERN = Pattern.compile("(=[0-9a-f]{2})+");
private MatrixIdCodec() {
// not for public consumption
}
public static String encode(String decoded) {
decoded = decoded.toLowerCase();
StringBuilder builder = new StringBuilder();
for (Character c : decoded.toCharArray()) {
String s = c.toString();
Matcher lp = ENCODE_PATTERN.matcher(s);
if (!lp.find()) {
builder.append(s);
} else {
for (byte b : c.toString().getBytes(StandardCharsets.UTF_8)) {
builder.append(DELIMITER);
builder.append(Hex.encodeHexString(new byte[] { b }));
}
}
}
return builder.toString();
}
public static String decode(String encoded) {
StringBuilder builder = new StringBuilder();
Matcher m = DECODE_PATTERN.matcher(encoded);
int prevEnd = 0;
while (m.find()) {
try {
int start = m.start();
int end = m.end();
String sub = encoded.substring(start, end).replaceAll(DELIMITER, "");
String decoded = new String(Hex.decodeHex(sub.toCharArray()), StandardCharsets.UTF_8);
builder.append(encoded, prevEnd, start);
builder.append(decoded);
prevEnd = end - 1;
} catch (DecoderException e) {
e.printStackTrace();
}
}
prevEnd++;
if (prevEnd < encoded.length()) {
builder.append(encoded, prevEnd, encoded.length());
}
if (builder.length() == 0) {
return encoded;
} else {
return builder.toString();
}
}
}

View File

@@ -0,0 +1,104 @@
/*
* matrix-java-sdk - Matrix Client SDK for Java
* Copyright (C) 2018 Kamax Sàrl
*
* https://www.kamax.io/
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package io.kamax.matrix;
import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
public class MatrixPath {
public static String encode(String element) {
try {
return URLEncoder.encode(element, StandardCharsets.UTF_8.name());
} catch (UnsupportedEncodingException e) {
// This would be madness if it happened, but we need to handle it still
throw new RuntimeException(e);
}
}
private static MatrixPath with(String base) {
return new MatrixPath().add(base);
}
public static MatrixPath root() {
return with("");
}
public static MatrixPath base() {
return root().add("_matrix");
}
public static MatrixPath client() {
return base().add("client");
}
public static MatrixPath clientR0() {
return client().add("v3");
}
private StringBuilder path = new StringBuilder();
/**
* Add the raw element to this path
*
* @param element
* The raw element to be added as is to the path, without encoding or path separator
* @return The MatrixPath
*/
public MatrixPath put(String element) {
path.append(element);
return this;
}
/**
* URL encode and add a new path element
*
* This method handle path separators
*
* @param element
* The element to be encoded and added.
* @return The MatrixPath
*/
public MatrixPath add(String element) {
// We add a path separator if this is the first character or if the last character is not a path separator
// already
if (path.length() == 0 || path.lastIndexOf("/", 0) < path.length() - 1) {
put("/");
}
put(encode(element));
return this;
}
public String get() {
return path.toString();
}
public String toString() {
return get();
}
public URI toURI() {
return URI.create(toString());
}
}

View File

@@ -0,0 +1,61 @@
/*
* matrix-java-sdk - Matrix Client SDK for Java
* Copyright (C) 2017 Kamax Sarl
*
* https://www.kamax.io/
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package io.kamax.matrix;
public class ThreePid implements _ThreePid {
private String medium;
private String address;
public ThreePid(String medium, String address) {
this.medium = medium;
this.address = address.toLowerCase();
}
@Override
public String getMedium() {
return medium;
}
@Override
public String getAddress() {
return address;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
ThreePid threePid = (ThreePid) o;
if (!medium.equals(threePid.medium)) return false;
return address.equals(threePid.address);
}
@Override
public int hashCode() {
int result = medium.hashCode();
result = 31 * result + address.hashCode();
return result;
}
}

View File

@@ -0,0 +1,61 @@
/*
* matrix-java-sdk - Matrix Client SDK for Java
* Copyright (C) 2017 Kamax Sarl
*
* https://www.kamax.io/
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package io.kamax.matrix;
public class ThreePidMapping implements _ThreePidMapping {
private _ThreePid threePid;
private _MatrixID mxId;
public ThreePidMapping(_ThreePid threePid, _MatrixID mxId) {
this.threePid = threePid;
this.mxId = mxId;
}
@Override
public _ThreePid getThreePid() {
return threePid;
}
@Override
public _MatrixID getMatrixId() {
return mxId;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
ThreePidMapping that = (ThreePidMapping) o;
if (!threePid.equals(that.threePid)) return false;
return mxId.equals(that.mxId);
}
@Override
public int hashCode() {
int result = threePid.hashCode();
result = 31 * result + mxId.hashCode();
return result;
}
}

View File

@@ -0,0 +1,46 @@
/*
* matrix-java-sdk - Matrix Client SDK for Java
* Copyright (C) 2017 Kamax Sarl
*
* https://www.kamax.io/
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package io.kamax.matrix;
public enum ThreePidMedium {
Email("email"),
PhoneNumber("msisdn");
private String id;
ThreePidMedium(String id) {
this.id = id;
}
public String getId() {
return id;
}
public String toString() {
return getId();
}
public boolean is(String s) {
return getId().contentEquals(s);
}
}

View File

@@ -0,0 +1,41 @@
/*
* matrix-java-sdk - Matrix Client SDK for Java
* Copyright (C) 2017 Kamax Sarl
*
* https://www.kamax.io/
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package io.kamax.matrix;
import java.net.URI;
import java.net.URL;
import java.util.Optional;
public interface _MatrixContent {
URI getAddress();
URL getPermaLink();
boolean isValid();
Optional<String> getType();
byte[] getData();
Optional<String> getFilename();
}

View File

@@ -0,0 +1,55 @@
/*
* matrix-java-sdk - Matrix Client SDK for Java
* Copyright (C) 2017 Kamax Sarl
*
* https://www.kamax.io/
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package io.kamax.matrix;
public interface _MatrixID {
String getId();
String getLocalPart();
String getDomain();
/**
* Render this Matrix ID strictly valid. In technical term, transform this ID so
* <code>isValid()</code> returns true.
*
* @return A canonical Matrix ID
*/
_MatrixID canonicalize();
/**
* If the Matrix ID is strictly valid in the protocol as per
* http://matrix.org/docs/spec/intro.html#user-identifiers
*
* @return true if strictly valid, false if not
*/
boolean isValid();
/**
* If the Matrix ID is acceptable in the protocol as per
* http://matrix.org/docs/spec/intro.html#historical-user-ids
*
* @return
*/
boolean isAcceptable();
}

View File

@@ -0,0 +1,31 @@
/*
* matrix-java-sdk - Matrix Client SDK for Java
* Copyright (C) 2017 Kamax Sarl
*
* https://www.kamax.io/
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package io.kamax.matrix;
import io.kamax.matrix.client._Presence;
import java.util.Optional;
public interface _MatrixUser extends _MatrixUserProfile {
Optional<_Presence> getPresence();
}

View File

@@ -0,0 +1,42 @@
/*
* matrix-java-sdk - Matrix SDK for Java
* Copyright (C) 2018 Kamax Sarl
*
* https://www.kamax.io/
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package io.kamax.matrix;
import java.net.URI;
import java.util.Optional;
public interface _MatrixUserProfile {
_MatrixID getId();
Optional<String> getName();
void setName(String name);
Optional<String> getAvatarUrl();
void setAvatar(String avatarRef);
void setAvatar(URI avatarUri);
Optional<_MatrixContent> getAvatar();
}

View File

@@ -0,0 +1,29 @@
/*
* matrix-java-sdk - Matrix Client SDK for Java
* Copyright (C) 2017 Kamax Sarl
*
* https://www.kamax.io/
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package io.kamax.matrix;
public interface _ThreePid {
String getMedium();
String getAddress();
}

View File

@@ -0,0 +1,29 @@
/*
* matrix-java-sdk - Matrix Client SDK for Java
* Copyright (C) 2017 Kamax Sarl
*
* https://www.kamax.io/
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package io.kamax.matrix;
public interface _ThreePidMapping {
_ThreePid getThreePid();
_MatrixID getMatrixId();
}

View File

@@ -0,0 +1,409 @@
/*
* matrix-java-sdk - Matrix Client SDK for Java
* Copyright (C) 2017 Kamax Sarl
*
* https://www.kamax.io/
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package io.kamax.matrix.client;
import com.google.gson.Gson;
import com.google.gson.JsonParser;
import com.google.gson.JsonSyntaxException;
import io.kamax.matrix.MatrixErrorInfo;
import io.kamax.matrix._MatrixID;
import io.kamax.matrix.hs._MatrixHomeserver;
import io.kamax.matrix.json.GsonUtil;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.net.URL;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.Objects;
import java.util.Optional;
import okhttp3.*;
public abstract class AMatrixHttpClient implements _MatrixClientRaw {
private Logger log = LoggerFactory.getLogger(AMatrixHttpClient.class);
protected MatrixClientContext context;
protected Gson gson = GsonUtil.get();
protected JsonParser jsonParser = new JsonParser();
private OkHttpClient client;
public AMatrixHttpClient(String domain) {
this(new MatrixClientContext().setDomain(domain));
}
public AMatrixHttpClient(URL hsBaseUrl) {
this(new MatrixClientContext().setHsBaseUrl(hsBaseUrl));
}
protected AMatrixHttpClient(MatrixClientContext context) {
this(context, new OkHttpClient.Builder(), new MatrixClientDefaults());
}
protected AMatrixHttpClient(MatrixClientContext context, OkHttpClient.Builder client) {
this(context, client, new MatrixClientDefaults());
}
protected AMatrixHttpClient(MatrixClientContext context, OkHttpClient.Builder client,
MatrixClientDefaults defaults) {
this(context, client.connectTimeout(defaults.getConnectTimeout(), TimeUnit.MILLISECONDS)
.readTimeout(5, TimeUnit.MINUTES).followRedirects(false).build());
}
protected AMatrixHttpClient(MatrixClientContext context, OkHttpClient client) {
this.context = context;
this.client = client;
}
@Override
public Optional<_AutoDiscoverySettings> discoverSettings() {
if (StringUtils.isBlank(context.getDomain())) {
throw new IllegalStateException("A non-empty Matrix domain must be set to discover the client settings");
}
String hostname = context.getDomain().split(":")[0];
log.info("Performing .well-known auto-discovery for {}", hostname);
URL url = new HttpUrl.Builder().scheme("https").host(hostname).addPathSegments(".well-known/matrix/client")
.build().url();
String body = execute(new MatrixHttpRequest(new Request.Builder().get().url(url)).addIgnoredErrorCode(404));
if (StringUtils.isBlank(body)) {
if (Objects.isNull(context.getHsBaseUrl())) {
throw new IllegalStateException("No valid Homeserver base URL was found");
}
// No .well-known data found
// FIXME improve SDK so we can differentiate between not found and empty.
// not found = skip
// empty = failure
return Optional.empty();
}
log.info("Found body: {}", body);
WellKnownAutoDiscoverySettings settings = new WellKnownAutoDiscoverySettings(body);
log.info("Found .well-known data");
// TODO reconsider if and where we should check for an already present HS url in the context
if (settings.getHsBaseUrls().isEmpty()) {
throw new IllegalStateException("No valid Homeserver base URL was found");
}
for (URL baseUrlCandidate : settings.getHsBaseUrls()) {
context.setHsBaseUrl(baseUrlCandidate);
try {
if (!getHomeApiVersions().isEmpty()) {
log.info("Found a valid HS at {}", getContext().getHsBaseUrl().toString());
break;
}
} catch (MatrixClientRequestException e) {
log.warn("Error when trying to fetch {}: {}", baseUrlCandidate, e.getMessage());
}
}
for (URL baseUrlCandidate : settings.getIsBaseUrls()) {
context.setIsBaseUrl(baseUrlCandidate);
try {
if (validateIsBaseUrl()) {
log.info("Found a valid IS at {}", getContext().getIsBaseUrl().toString());
break;
}
} catch (MatrixClientRequestException e) {
log.warn("Error when trying to fetch {}: {}", baseUrlCandidate, e.getMessage());
}
}
return Optional.of(settings);
}
@Override
public MatrixClientContext getContext() {
return context;
}
@Override
public _MatrixHomeserver getHomeserver() {
return context.getHomeserver();
}
@Override
public Optional<String> getAccessToken() {
return Optional.ofNullable(context.getToken());
}
public String getAccessTokenOrThrow() {
return getAccessToken()
.orElseThrow(() -> new IllegalStateException("This method can only be used with a valid token."));
}
@Override
public List<String> getHomeApiVersions() {
String body = execute(new Request.Builder().get().url(getPath("client", "", "versions")));
return GsonUtil.asList(GsonUtil.parseObj(body), "versions", String.class);
}
@Override
public boolean validateIsBaseUrl() {
String body = execute(new Request.Builder().get().url(getIdentityPath("identity", "api", "v1")));
return "{}".equals(body);
}
protected String getUserId() {
return getUser().orElseThrow(IllegalStateException::new).getId();
}
@Override
public Optional<_MatrixID> getUser() {
return context.getUser();
}
protected Request.Builder addAuthHeader(Request.Builder builder, String token) {
builder.addHeader("Authorization", "Bearer " + token);
return builder;
}
protected Request.Builder addAuthHeader(Request.Builder builder) {
return addAuthHeader(builder, getAccessTokenOrThrow());
}
protected String executeAuthenticated(Request.Builder builder, String token) {
return execute(addAuthHeader(builder, token));
}
protected String executeAuthenticated(Request.Builder builder) {
return execute(addAuthHeader(builder));
}
protected String executeAuthenticated(MatrixHttpRequest matrixRequest) {
addAuthHeader(matrixRequest.getHttpRequest());
return execute(matrixRequest);
}
protected String execute(Request.Builder builder) {
return execute(new MatrixHttpRequest(builder));
}
protected String execute(MatrixHttpRequest matrixRequest) {
log(matrixRequest.getHttpRequest());
try (Response response = client.newCall(matrixRequest.getHttpRequest().build()).execute()) {
String body = response.body().string();
int responseStatus = response.code();
if (responseStatus == 200) {
log.debug("Request successfully executed.");
} else if (matrixRequest.getIgnoredErrorCodes().contains(responseStatus)) {
log.debug("Error code ignored: " + responseStatus);
return "";
} else {
MatrixErrorInfo info = createErrorInfo(body, responseStatus);
body = handleError(matrixRequest, responseStatus, info);
}
return body;
} catch (IOException e) {
throw new MatrixClientRequestException(e);
}
}
protected MatrixHttpContentResult executeContentRequest(MatrixHttpRequest matrixRequest) {
log(matrixRequest.getHttpRequest());
try (Response response = client.newCall(matrixRequest.getHttpRequest().build()).execute()) {
int responseStatus = response.code();
MatrixHttpContentResult result;
if (responseStatus == 200 || matrixRequest.getIgnoredErrorCodes().contains(responseStatus)) {
log.debug("Request successfully executed.");
result = new MatrixHttpContentResult(response);
} else {
String body = response.body().string();
MatrixErrorInfo info = createErrorInfo(body, responseStatus);
result = handleErrorContentRequest(matrixRequest, responseStatus, info);
}
return result;
} catch (IOException e) {
throw new MatrixClientRequestException(e);
}
}
/**
* Default handling of errors. Can be overwritten by a custom implementation in inherited classes.
*
* @param matrixRequest
* @param responseStatus
* @param info
* @return body of the response of a repeated call of the request, else this methods throws a
* MatrixClientRequestException
*/
protected String handleError(MatrixHttpRequest matrixRequest, int responseStatus, MatrixErrorInfo info) {
String message = String.format("Request failed: %s", responseStatus);
if (Objects.nonNull(info)) {
message = String.format("%s - %s - %s", message, info.getErrcode(), info.getError());
}
if (responseStatus == 429) {
return handleRateLimited(matrixRequest, info);
}
throw new MatrixClientRequestException(info, message);
}
/**
* Default handling of rate limited calls. Can be overwritten by a custom implementation in inherited classes.
*
* @param matrixRequest
* @param info
* @return body of the response of a repeated call of the request, else this methods throws a
* MatrixClientRequestException
*/
protected String handleRateLimited(MatrixHttpRequest matrixRequest, MatrixErrorInfo info) {
throw new MatrixClientRequestException(info, "Request was rate limited.");
// TODO Add default handling of rate limited call, i.e. repeated call after given time interval.
// 1. Wait for timeout
// 2. return execute(request)
}
protected MatrixHttpContentResult handleErrorContentRequest(MatrixHttpRequest matrixRequest, int responseStatus,
MatrixErrorInfo info) {
String message = String.format("Request failed with status code: %s", responseStatus);
if (responseStatus == 429) {
return handleRateLimitedContentRequest(matrixRequest, info);
}
throw new MatrixClientRequestException(info, message);
}
protected MatrixHttpContentResult handleRateLimitedContentRequest(MatrixHttpRequest matrixRequest,
MatrixErrorInfo info) {
throw new MatrixClientRequestRateLimitedException(info, "Request was rate limited.");
// TODO Add default handling of rate limited call, i.e. repeated call after given time interval.
// 1. Wait for timeout
// 2. return execute(request)
}
protected Optional<String> extractAsStringFromBody(String body, String jsonObjectName) {
if (StringUtils.isEmpty(body)) {
return Optional.empty();
}
return GsonUtil.findString(jsonParser.parse(body).getAsJsonObject(), jsonObjectName);
}
private MatrixErrorInfo createErrorInfo(String body, int responseStatus) {
MatrixErrorInfo info = null;
try {
info = gson.fromJson(body, MatrixErrorInfo.class);
if (Objects.nonNull(info)) {
log.debug("Request returned with an error. Status code: {}, errcode: {}, error: {}", responseStatus,
info.getErrcode(), info.getError());
}
} catch (JsonSyntaxException e) {
log.debug("Unable to parse Matrix error info. Content was:\n{}", body);
}
return info;
}
private void log(Request.Builder req) {
log.debug("Doing {} {}", req, req.toString());
}
protected HttpUrl.Builder getHsBaseUrl() {
return HttpUrl.get(context.getHsBaseUrl()).newBuilder();
}
protected HttpUrl.Builder getIsBaseUrl() {
return HttpUrl.get(context.getIsBaseUrl()).newBuilder();
}
protected HttpUrl.Builder getPathBuilder(HttpUrl.Builder base, String... segments) {
base.addPathSegment("_matrix");
for (String segment : segments) {
base.addPathSegment(segment);
}
if (context.isVirtual()) {
context.getUser().ifPresent(user -> base.addQueryParameter("user_id", user.getId()));
}
return base;
}
protected HttpUrl.Builder getPathBuilder(String... segments) {
return getPathBuilder(getHsBaseUrl(), segments);
}
protected HttpUrl.Builder getIdentityPathBuilder(String... segments) {
return getPathBuilder(getIsBaseUrl(), segments);
}
protected URL getPath(String... segments) {
return getPathBuilder(segments).build().url();
}
protected URL getIdentityPath(String... segments) {
return getIdentityPathBuilder(segments).build().url();
}
protected HttpUrl.Builder getClientPathBuilder(String... segments) {
String[] base = { "client", "v3" };
segments = ArrayUtils.addAll(base, segments);
return getPathBuilder(segments);
}
protected HttpUrl.Builder getMediaPathBuilder(String... segments) {
String[] base = { "media", "v3" };
segments = ArrayUtils.addAll(base, segments);
return getPathBuilder(segments);
}
protected URL getClientPath(String... segments) {
return getClientPathBuilder(segments).build().url();
}
protected URL getMediaPath(String... segments) {
return getMediaPathBuilder(segments).build().url();
}
protected RequestBody getJsonBody(Object o) {
return RequestBody.create(MediaType.parse("application/json"), GsonUtil.get().toJson(o));
}
protected Request.Builder request(URL url) {
return new Request.Builder().url(url);
}
protected Request.Builder getRequest(URL url) {
return request(url).get();
}
}

View File

@@ -0,0 +1,154 @@
/*
* matrix-java-sdk - Matrix Client SDK for Java
* Copyright (C) 2017 Kamax Sarl
*
* https://www.kamax.io/
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package io.kamax.matrix.client;
import io.kamax.matrix.MatrixID;
import io.kamax.matrix._MatrixID;
import io.kamax.matrix.hs.MatrixHomeserver;
import io.kamax.matrix.hs._MatrixHomeserver;
import java.net.URL;
import java.util.Objects;
import java.util.Optional;
public class MatrixClientContext {
private String domain;
private URL hsBaseUrl;
private URL isBaseUrl;
private _MatrixID user;
private String token;
private boolean isVirtual;
private String deviceId;
private String initialDeviceName;
public MatrixClientContext() {
// stub
}
public MatrixClientContext(MatrixClientContext other) {
this.domain = other.domain;
this.hsBaseUrl = other.hsBaseUrl;
this.isBaseUrl = other.isBaseUrl;
this.user = other.user;
this.token = other.token;
this.isVirtual = other.isVirtual;
this.deviceId = other.deviceId;
this.initialDeviceName = other.initialDeviceName;
}
public MatrixClientContext(_MatrixHomeserver hs) {
setDomain(hs.getDomain());
setHsBaseUrl(hs.getBaseEndpoint());
}
public MatrixClientContext(_MatrixHomeserver hs, _MatrixID user, String token) {
this(hs);
setUser(user);
setToken(token);
}
public _MatrixHomeserver getHomeserver() {
if (Objects.isNull(hsBaseUrl)) {
throw new IllegalStateException("Homeserver Base URL is not set");
}
return new MatrixHomeserver(domain, hsBaseUrl.toString());
}
public String getDomain() {
return domain;
}
public MatrixClientContext setDomain(String domain) {
this.domain = domain;
return this;
}
public URL getHsBaseUrl() {
return hsBaseUrl;
}
public MatrixClientContext setHsBaseUrl(URL hsBaseUrl) {
this.hsBaseUrl = hsBaseUrl;
return this;
}
public URL getIsBaseUrl() {
return isBaseUrl;
}
public MatrixClientContext setIsBaseUrl(URL isBaseUrl) {
this.isBaseUrl = isBaseUrl;
return this;
}
public Optional<_MatrixID> getUser() {
return Optional.ofNullable(user);
}
public MatrixClientContext setUser(_MatrixID user) {
this.user = user;
return this;
}
public MatrixClientContext setUserWithLocalpart(String localpart) {
setUser(MatrixID.asAcceptable(localpart, getDomain()));
return this;
}
public String getToken() {
return token;
}
public MatrixClientContext setToken(String token) {
this.token = token;
return this;
}
public boolean isVirtual() {
return isVirtual;
}
public MatrixClientContext setVirtual(boolean virtual) {
isVirtual = virtual;
return this;
}
public String getDeviceId() {
return deviceId;
}
public MatrixClientContext setDeviceId(String deviceId) {
this.deviceId = deviceId;
return this;
}
public String getInitialDeviceName() {
return initialDeviceName;
}
public MatrixClientContext setInitialDeviceName(String initialDeviceName) {
this.initialDeviceName = initialDeviceName;
return this;
}
}

View File

@@ -0,0 +1,59 @@
/*
* matrix-java-sdk - Matrix Client SDK for Java
* Copyright (C) 2018 Kamax Sarl
*
* https://www.kamax.io/
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package io.kamax.matrix.client;
public class MatrixClientDefaults {
private int connectTimeout = 30 * 1000; // 30 sec
private int requestTimeout = 5 * 60 * 1000; // 5 min
private int socketTimeout = requestTimeout;
public int getConnectTimeout() {
return connectTimeout;
}
public MatrixClientDefaults setConnectTimeout(int connectTimeout) {
this.connectTimeout = connectTimeout;
return this;
}
public int getRequestTimeout() {
return requestTimeout;
}
public MatrixClientDefaults setRequestTimeout(int requestTimeout) {
this.requestTimeout = requestTimeout;
return this;
}
public int getSocketTimeout() {
return socketTimeout;
}
public MatrixClientDefaults setSocketTimeout(int socketTimeout) {
this.socketTimeout = socketTimeout;
return this;
}
}

View File

@@ -0,0 +1,46 @@
/*
* matrix-java-sdk - Matrix Client SDK for Java
* Copyright (C) 2017 Kamax Sarl
*
* https://www.kamax.io/
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package io.kamax.matrix.client;
import io.kamax.matrix.MatrixErrorInfo;
import java.io.IOException;
import java.util.Optional;
public class MatrixClientRequestException extends RuntimeException {
private MatrixErrorInfo errorInfo;
public MatrixClientRequestException(IOException e) {
super(e);
}
public MatrixClientRequestException(MatrixErrorInfo errorInfo, String message) {
super(message);
this.errorInfo = errorInfo;
}
public Optional<MatrixErrorInfo> getError() {
return Optional.ofNullable(errorInfo);
}
}

View File

@@ -0,0 +1,31 @@
/*
* matrix-java-sdk - Matrix Client SDK for Java
* Copyright (C) 2018 Kamax Sarl
*
* https://www.kamax.io/
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package io.kamax.matrix.client;
import io.kamax.matrix.MatrixErrorInfo;
public class MatrixClientRequestRateLimitedException extends MatrixClientRequestException {
public MatrixClientRequestRateLimitedException(MatrixErrorInfo errorInfo, String message) {
super(errorInfo, message);
}
}

View File

@@ -0,0 +1,133 @@
/*
* matrix-java-sdk - Matrix Client SDK for Java
* Copyright (C) 2017 Kamax Sarl
*
* https://www.kamax.io/
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package io.kamax.matrix.client;
import io.kamax.matrix._MatrixContent;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.net.URI;
import java.net.URL;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.Optional;
import okhttp3.Request;
public class MatrixHttpContent extends AMatrixHttpClient implements _MatrixContent {
private Logger log = LoggerFactory.getLogger(MatrixHttpContent.class);
private final Pattern filenamePattern = Pattern.compile("filename=\"?([^\";]+)");
private URI address;
private MatrixHttpContentResult result;
private boolean loaded = false;
private boolean valid = false;
public MatrixHttpContent(MatrixClientContext context, URI address) {
super(context);
this.address = address;
}
// TODO switch a HTTP HEAD to fetch initial data, instead of loading in memory directly
private synchronized void load() {
if (loaded) {
return;
}
try {
if (!StringUtils.equalsIgnoreCase("mxc", address.getScheme())) {
log.debug("{} is not a supported protocol for avatars, ignoring", address.getScheme());
} else {
MatrixHttpRequest request = new MatrixHttpRequest(new Request.Builder().url(getPermaLink()));
result = executeContentRequest(request);
valid = result.isValid();
}
} catch (MatrixClientRequestException e) {
valid = false;
}
loaded = true;
}
@Override
public URI getAddress() {
return address;
}
@Override
public URL getPermaLink() {
return getMediaPathBuilder("download", address.getHost()).addEncodedPathSegments(address.getPath().substring(1))
.build().url();
}
@Override
public boolean isValid() {
load();
return valid;
}
@Override
public Optional<String> getType() {
load();
if (!isValid()) {
throw new IllegalStateException("This method should only be called, if valid is true.");
}
return result.getContentType();
}
@Override
public byte[] getData() {
load();
if (!isValid()) {
throw new IllegalStateException("This method should only be called, if valid is true.");
}
return result.getData();
}
@Override
public Optional<String> getFilename() {
load();
if (!isValid()) {
throw new IllegalStateException("This method should only be called, if valid is true.");
}
return result.getHeader("Content-Disposition").filter(l -> !l.isEmpty()).flatMap(l -> {
for (String v : l) {
Matcher m = filenamePattern.matcher(v);
if (m.find()) {
return Optional.of(m.group(1));
}
}
return Optional.empty();
});
}
}

View File

@@ -0,0 +1,71 @@
/*
* matrix-java-sdk - Matrix Client SDK for Java
* Copyright (C) 2017 Kamax Sarl
*
* https://www.kamax.io/
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package io.kamax.matrix.client;
import java.io.IOException;
import java.util.*;
import java.util.Optional;
import okhttp3.MediaType;
import okhttp3.Response;
import okhttp3.ResponseBody;
public class MatrixHttpContentResult {
private final boolean valid;
private final Map<String, List<String>> headers;
private final Optional<String> contentType;
private final byte[] data;
public MatrixHttpContentResult(Response response) throws IOException {
try (ResponseBody body = response.body()) {
boolean hasBody = Objects.nonNull(body);
valid = hasBody && response.code() == 200;
headers = response.headers().toMultimap();
if (hasBody) {
contentType = Optional.ofNullable(body.contentType()).map(MediaType::toString);
data = body.bytes();
} else {
contentType = Optional.empty();
data = new byte[0];
}
}
}
public boolean isValid() {
return valid;
}
public Optional<List<String>> getHeader(String name) {
return Optional.ofNullable(headers.get(name));
}
public Optional<String> getContentType() {
return contentType;
}
public byte[] getData() {
return data;
}
}

View File

@@ -0,0 +1,93 @@
/*
* matrix-java-sdk - Matrix Client SDK for Java
* Copyright (C) 2018 Kamax Sarl
*
* https://www.kamax.io/
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package io.kamax.matrix.client;
import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
import io.kamax.matrix.json.GsonUtil;
import org.apache.commons.lang3.ArrayUtils;
import java.net.URL;
import java.util.List;
import javax.swing.*;
public class MatrixHttpPushRule extends AMatrixHttpClient implements _PushRule {
private static final String ActionKey = "actions";
private static final String EnabledKey = "enabled";
private final String[] baseSegments;
public MatrixHttpPushRule(MatrixClientContext context, String scope, String kind, String id) {
super(context);
baseSegments = new String[] { "pushrules", scope, kind, id };
}
private URL makeUrl() {
return getClientPath(baseSegments);
}
private URL makeUrl(String... segments) {
return getClientPath(ArrayUtils.addAll(baseSegments, segments));
}
@Override
public JsonObject getJson() {
return GsonUtil.parseObj(executeAuthenticated(getRequest(makeUrl())));
}
@Override
public void set(JsonObject data) {
executeAuthenticated(request(makeUrl()).put(getJsonBody(data)));
}
@Override
public void delete() {
executeAuthenticated(request(makeUrl()).delete());
}
@Override
public boolean isEnabled() {
JsonObject response = GsonUtil.parseObj(executeAuthenticated(getRequest(makeUrl(EnabledKey))));
return GsonUtil.getPrimitive(response, EnabledKey).getAsBoolean();
}
@Override
public void setEnabled(boolean enabled) {
executeAuthenticated(request(makeUrl(EnabledKey)).put(getJsonBody(GsonUtil.makeObj(EnabledKey, enabled))));
}
@Override
public List<String> getActions() {
JsonObject response = GsonUtil.parseObj(executeAuthenticated(getRequest(makeUrl(ActionKey))));
return GsonUtil.asList(GsonUtil.findArray(response, ActionKey).orElseGet(JsonArray::new), String.class);
}
@Override
public void setActions(List<String> data) {
executeAuthenticated(
request(makeUrl(ActionKey)).put(getJsonBody(GsonUtil.makeObj(ActionKey, GsonUtil.asArray(data)))));
}
}

View File

@@ -0,0 +1,50 @@
/*
* matrix-java-sdk - Matrix Client SDK for Java
* Copyright (C) 2017 Kamax Sarl
*
* https://www.kamax.io/
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package io.kamax.matrix.client;
import java.util.ArrayList;
import java.util.List;
import okhttp3.Request;
public class MatrixHttpRequest {
private final Request.Builder httpRequest;
private List<Integer> ignoredErrorCodes = new ArrayList<>();
public MatrixHttpRequest(Request.Builder request) {
this.httpRequest = request;
}
public MatrixHttpRequest addIgnoredErrorCode(int errcode) {
ignoredErrorCodes.add(errcode);
return this;
}
public Request.Builder getHttpRequest() {
return httpRequest;
}
public List<Integer> getIgnoredErrorCodes() {
return ignoredErrorCodes;
}
}

View File

@@ -0,0 +1,440 @@
/*
* matrix-java-sdk - Matrix Client SDK for Java
* Copyright (C) 2017 Kamax Sarl
*
* https://www.kamax.io/
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package io.kamax.matrix.client;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import io.kamax.matrix.MatrixErrorInfo;
import io.kamax.matrix.MatrixID;
import io.kamax.matrix._MatrixContent;
import io.kamax.matrix._MatrixID;
import io.kamax.matrix._MatrixUserProfile;
import io.kamax.matrix.hs._MatrixRoom;
import io.kamax.matrix.json.GsonUtil;
import io.kamax.matrix.json.RoomMessageChunkResponseJson;
import io.kamax.matrix.json.RoomMessageFormattedTextPutBody;
import io.kamax.matrix.json.RoomMessageTextPutBody;
import io.kamax.matrix.json.RoomTagSetBody;
import io.kamax.matrix.json.event.MatrixJsonPersistentEvent;
import io.kamax.matrix.room.*;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
import okhttp3.HttpUrl;
import okhttp3.Request;
public class MatrixHttpRoom extends AMatrixHttpClient implements _MatrixRoom {
private Logger log = LoggerFactory.getLogger(MatrixHttpRoom.class);
private String roomId;
public MatrixHttpRoom(MatrixClientContext context, String roomId) {
super(context);
this.roomId = roomId;
}
@Override
public String getAddress() {
return roomId;
}
@Override
public Optional<String> getName() {
return getState("m.room.name").flatMap(obj -> GsonUtil.findString(obj, "name"));
}
@Override
public Optional<String> getTopic() {
return getState("m.room.topic").flatMap(obj -> GsonUtil.findString(obj, "topic"));
}
@Override
public Optional<String> getAvatarUrl() {
return getState("m.room.avatar").flatMap(obj -> GsonUtil.findString(obj, "url"));
}
@Override
public Optional<_MatrixContent> getAvatar() {
return getAvatarUrl().flatMap(url -> {
try {
return Optional.of(new MatrixHttpContent(context, new URI(url)));
} catch (URISyntaxException e) {
log.debug("{} is not a valid URI for avatar, returning empty", url);
return Optional.empty();
}
});
}
@Override
public String getId() {
return roomId;
}
@Override
public Optional<JsonObject> getState(String type) {
URL path = getClientPath("rooms", getAddress(), "state", type);
MatrixHttpRequest request = new MatrixHttpRequest(new Request.Builder().get().url(path));
request.addIgnoredErrorCode(404);
String body = executeAuthenticated(request);
if (StringUtils.isBlank(body)) {
return Optional.empty();
}
return Optional.of(GsonUtil.parseObj(body));
}
@Override
public Optional<JsonObject> getState(String type, String key) {
URL path = getClientPath("rooms", roomId, "state", type, key);
MatrixHttpRequest request = new MatrixHttpRequest(new Request.Builder().get().url(path));
request.addIgnoredErrorCode(404);
String body = executeAuthenticated(request);
if (StringUtils.isBlank(body)) {
return Optional.empty();
}
return Optional.of(GsonUtil.parseObj(body));
}
@Override
public void join() {
join(Collections.emptyList());
}
@Override
public void join(List<String> servers) {
HttpUrl.Builder b = getClientPathBuilder("rooms", roomId, "join");
servers.forEach(server -> b.addQueryParameter("server_name", server));
executeAuthenticated(new Request.Builder().post(getJsonBody(new JsonObject())).url(b.build()));
}
@Override
public Optional<MatrixErrorInfo> tryJoin() {
return tryJoin(Collections.emptyList());
}
@Override
public Optional<MatrixErrorInfo> tryJoin(List<String> servers) {
try {
join(servers);
return Optional.empty();
} catch (MatrixClientRequestException e) {
return e.getError();
}
}
@Override
public void leave() {
URL path = getClientPath("rooms", roomId, "leave");
MatrixHttpRequest request = new MatrixHttpRequest(
new Request.Builder().post(getJsonBody(new JsonObject())).url(path));
// TODO Find a better way to handle room objects for unknown rooms
// Maybe throw exception?
// TODO implement method to check room existence - isValid() ?
// if (res.getStatusLine().getStatusCode() == 404) {
// log.warn("Room {} is not joined, ignoring call", roomId);
// return;
// }
request.addIgnoredErrorCode(404);
executeAuthenticated(request);
}
@Override
public Optional<MatrixErrorInfo> tryLeave() {
try {
leave();
return Optional.empty();
} catch (MatrixClientRequestException e) {
return e.getError();
}
}
@Override
public void kick(_MatrixID user) {
kick(user, null);
}
@Override
public void kick(_MatrixID user, String reason) {
JsonObject body = new JsonObject();
body.addProperty("user_id", user.getId());
body.addProperty("reason", reason);
URL path = getClientPath("rooms", roomId, "kick");
MatrixHttpRequest request = new MatrixHttpRequest(new Request.Builder().post(getJsonBody(body)).url(path));
executeAuthenticated(request);
}
@Override
public Optional<MatrixErrorInfo> tryKick(_MatrixID user) {
return tryKick(user, null);
}
@Override
public Optional<MatrixErrorInfo> tryKick(_MatrixID user, String reason) {
try {
kick(user, reason);
return Optional.empty();
} catch (MatrixClientRequestException e) {
return e.getError();
}
}
@Override
public String sendEvent(String type, JsonObject content) {
// FIXME URL encoding
URL path = getClientPath("rooms", roomId, "send", type, Long.toString(System.currentTimeMillis()));
String body = executeAuthenticated(new Request.Builder().put(getJsonBody(content)).url(path));
return GsonUtil.getStringOrThrow(GsonUtil.parseObj(body), "event_id");
}
private String sendMessage(RoomMessageTextPutBody content) {
return sendEvent("m.room.message", GsonUtil.makeObj(content));
}
@Override
public String sendText(String message) {
return sendMessage(new RoomMessageTextPutBody(message));
}
@Override
public String sendFormattedText(String formatted, String rawFallback) {
// TODO sanitize input
return sendMessage(new RoomMessageFormattedTextPutBody(rawFallback, formatted));
}
@Override
public String sendNotice(String message) {
return sendMessage(new RoomMessageTextPutBody("m.notice", message));
}
@Override
public String sendNotice(String formatted, String plain) {
// TODO sanitize input
return sendMessage(new RoomMessageFormattedTextPutBody("m.notice", plain, formatted));
}
@Override
public void sendReceipt(String type, String eventId) {
URL path = getClientPath("rooms", roomId, "receipt", type, eventId);
executeAuthenticated(new Request.Builder().post(getJsonBody(new JsonObject())).url(path));
}
@Override
public void sendReceipt(ReceiptType type, String eventId) {
sendReceipt(type.getId(), eventId);
}
@Override
public void sendReadReceipt(String eventId) {
sendReceipt(ReceiptType.Read, eventId);
}
@Override
public void invite(_MatrixID mxId) {
URL path = getClientPath("rooms", roomId, "invite");
executeAuthenticated(
new Request.Builder().post(getJsonBody(GsonUtil.makeObj("user_id", mxId.getId()))).url(path));
}
@Override
public List<_MatrixUserProfile> getJoinedUsers() {
URL path = getClientPath("rooms", roomId, "joined_members");
String body = executeAuthenticated(new Request.Builder().get().url(path));
List<_MatrixUserProfile> ids = new ArrayList<>();
if (StringUtils.isNotEmpty(body)) {
JsonObject joinedUsers = jsonParser.parse(body).getAsJsonObject().get("joined").getAsJsonObject();
ids = joinedUsers.entrySet().stream().filter(e -> e.getValue().isJsonObject()).map(entry -> {
JsonObject obj = entry.getValue().getAsJsonObject();
return new MatrixHttpUser(getContext(), MatrixID.asAcceptable(entry.getKey())) {
@Override
public Optional<String> getName() {
return GsonUtil.findString(obj, "display_name");
}
@Override
public Optional<_MatrixContent> getAvatar() {
return GsonUtil.findString(obj, "avatar_url").flatMap(s -> {
try {
return Optional.of(new URI(s));
} catch (URISyntaxException e) {
return Optional.empty();
}
}).map(uri -> new MatrixHttpContent(getContext(), uri));
}
};
}).collect(Collectors.toList());
}
return ids;
}
@Override
public _MatrixRoomMessageChunk getMessages(_MatrixRoomMessageChunkOptions options) {
HttpUrl.Builder builder = getClientPathBuilder("rooms", roomId, "messages");
builder.addQueryParameter("from", options.getFromToken());
builder.addQueryParameter("dir", options.getDirection());
options.getToToken().ifPresent(token -> builder.addQueryParameter("to", token));
options.getLimit().ifPresent(limit -> builder.addQueryParameter("limit", limit.toString()));
String bodyRaw = executeAuthenticated(new Request.Builder().get().url(builder.build().url()));
RoomMessageChunkResponseJson body = GsonUtil.get().fromJson(bodyRaw, RoomMessageChunkResponseJson.class);
return new MatrixRoomMessageChunk(body.getStart(), body.getEnd(),
body.getChunk().stream().map(MatrixJsonPersistentEvent::new).collect(Collectors.toList()));
}
@Override
public List<Tag> getUserTags() {
return getAllTags().stream().filter(tag -> "u".equals(tag.getNamespace()))
.collect(Collectors.toList());
}
@Override
public List<Tag> getAllTags() {
URL path = getClientPath("user", getUserId(), "rooms", getAddress(), "tags");
String body = executeAuthenticated(new Request.Builder().get().url(path));
JsonObject jsonTags = GsonUtil.parseObj(body).getAsJsonObject("tags").getAsJsonObject();
List<Tag> tags = jsonTags.entrySet().stream().map(entry -> {
String completeName = entry.getKey();
String name = "";
String namespace = "";
if (completeName.startsWith("m.")) {
name = completeName.substring(2);
namespace = "m";
} else if (completeName.startsWith("u.")) {
name = completeName.substring(2);
namespace = "u";
} else {
name = completeName;
}
JsonElement jsonOrder = entry.getValue().getAsJsonObject().get("order");
Double order = null;
if (jsonOrder != null) {
order = jsonOrder.getAsDouble();
}
return new Tag(namespace, name, order);
}).collect(Collectors.toList());
return tags;
}
@Override
public void addUserTag(String tag) {
addTag("u." + tag, null);
}
@Override
public void addUserTag(String tag, double order) {
addTag("u." + tag, order);
}
@Override
public void deleteUserTag(String tag) {
deleteTag("u." + tag);
}
@Override
public void addFavouriteTag() {
addTag("m.favourite", null);
}
@Override
public void addFavouriteTag(double order) {
addTag("m.favourite", order);
}
@Override
public Optional<Tag> getFavouriteTag() {
return getAllTags().stream()
.filter(tag -> "m".equals(tag.getNamespace()) && "favourite".equals(tag.getName())).findFirst();
}
@Override
public void deleteFavouriteTag() {
deleteTag("m.favourite");
}
@Override
public void addLowpriorityTag() {
addTag("m.lowpriority", null);
}
@Override
public void addLowpriorityTag(double order) {
addTag("m.lowpriority", order);
}
@Override
public Optional<Tag> getLowpriorityTag() {
return getAllTags().stream()
.filter(tag -> "m".equals(tag.getNamespace()) && "lowpriority".equals(tag.getName())).findFirst();
}
@Override
public void deleteLowpriorityTag() {
deleteTag("m.lowpriority");
}
private void addTag(String tag, Double order) {
// TODO check name size
if (order != null && (order < 0 || order > 1)) {
throw new IllegalArgumentException("Order out of range!");
}
URL path = getClientPath("user", getUserId(), "rooms", getAddress(), "tags", tag);
Request.Builder request = new Request.Builder().url(path);
if (order != null) {
request.put(getJsonBody(new RoomTagSetBody(order)));
} else {
request.put(getJsonBody(new JsonObject()));
}
executeAuthenticated(request);
}
private void deleteTag(String tag) {
URL path = getClientPath("user", getUserId(), "rooms", getAddress(), "tags", tag);
executeAuthenticated(new Request.Builder().url(path).delete());
}
}

View File

@@ -0,0 +1,125 @@
/*
* matrix-java-sdk - Matrix Client SDK for Java
* Copyright (C) 2017 Kamax Sarl
*
* https://www.kamax.io/
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package io.kamax.matrix.client;
import com.google.gson.JsonObject;
import io.kamax.matrix._MatrixContent;
import io.kamax.matrix._MatrixID;
import io.kamax.matrix._MatrixUser;
import io.kamax.matrix.client.regular.Presence;
import io.kamax.matrix.json.GsonUtil;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.Optional;
import okhttp3.Request;
public class MatrixHttpUser extends AMatrixHttpClient implements _MatrixUser {
private Logger log = LoggerFactory.getLogger(MatrixHttpUser.class);
private _MatrixID mxId;
public MatrixHttpUser(MatrixClientContext context, _MatrixID mxId) {
super(context);
this.mxId = mxId;
}
@Override
public _MatrixID getId() {
return mxId;
}
@Override
public Optional<String> getName() {
URL path = getClientPath("profile", mxId.getId(), "displayname");
MatrixHttpRequest request = new MatrixHttpRequest(new Request.Builder().get().url(path));
request.addIgnoredErrorCode(404);
String body = executeAuthenticated(request);
return extractAsStringFromBody(body, "displayname");
}
@Override
public void setName(String name) {
URL path = getClientPath("profile", mxId.getId(), "displayname");
JsonObject body = GsonUtil.makeObj("displayname", name);
executeAuthenticated(new Request.Builder().put(getJsonBody(body)).url(path));
}
@Override
public Optional<String> getAvatarUrl() {
URL path = getClientPath("profile", mxId.getId(), "avatar_url");
MatrixHttpRequest request = new MatrixHttpRequest(new Request.Builder().get().url(path));
request.addIgnoredErrorCode(404);
String body = executeAuthenticated(request);
return extractAsStringFromBody(body, "avatar_url");
}
@Override
public void setAvatar(String avatarRef) {
URL path = getClientPath("profile", mxId.getId(), "avatar_url");
JsonObject body = GsonUtil.makeObj("avatar_url", avatarRef);
executeAuthenticated(new Request.Builder().put(getJsonBody(body)).url(path));
}
@Override
public void setAvatar(URI avatarUri) {
setAvatar(avatarUri.toString());
}
@Override
public Optional<_MatrixContent> getAvatar() {
return getAvatarUrl().flatMap(uri -> {
try {
return Optional.of(new MatrixHttpContent(getContext(), new URI(uri)));
} catch (URISyntaxException e) {
log.debug("{} is not a valid URI for avatar, returning empty", uri);
return Optional.empty();
}
});
}
@Override
public Optional<_Presence> getPresence() {
URL path = getClientPath("presence", mxId.getId(), "status");
MatrixHttpRequest request = new MatrixHttpRequest(new Request.Builder().get().url(path));
request.addIgnoredErrorCode(404);
String body = execute(request);
if (StringUtils.isBlank(body)) {
return Optional.empty();
}
return Optional.of(new Presence(GsonUtil.parseObj(body)));
}
}

View File

@@ -0,0 +1,39 @@
/*
* matrix-java-sdk - Matrix Client SDK for Java
* Copyright (C) 2017 Kamax Sarl
*
* https://www.kamax.io/
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package io.kamax.matrix.client;
public class MatrixPasswordCredentials {
private final String localPart;
private final String password;
public MatrixPasswordCredentials(String localPart, String password) {
this.localPart = localPart;
this.password = password;
}
public String getLocalPart() {
return localPart;
}
public String getPassword() {
return password;
}
}

View File

@@ -0,0 +1,45 @@
/*
* matrix-java-sdk - Matrix Client SDK for Java
* Copyright (C) 2018 Kamax Sàrl
*
* https://www.kamax.io/
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package io.kamax.matrix.client;
import org.apache.commons.lang3.StringUtils;
public enum PresenceStatus {
Online("online"),
Offline("offline"),
Unavailable("unavailable");
private String id;
PresenceStatus(String id) {
this.id = id;
}
public String getId() {
return id;
}
public boolean is(String status) {
return StringUtils.equals(id, status);
}
}

View File

@@ -0,0 +1,138 @@
/*
* matrix-java-sdk - Matrix Client SDK for Java
* Copyright (C) 2018 Kamax Sarl
*
* https://www.kamax.io/
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package io.kamax.matrix.client;
import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
import com.google.gson.JsonParseException;
import io.kamax.matrix.json.GsonUtil;
import io.kamax.matrix.json.InvalidJsonException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
public class WellKnownAutoDiscoverySettings implements _AutoDiscoverySettings {
private final Logger log = LoggerFactory.getLogger(WellKnownAutoDiscoverySettings.class);
private JsonObject raw;
private List<URL> hsBaseUrls = new ArrayList<>();
private List<URL> isBaseUrls = new ArrayList<>();
/**
* Build .well-known auto-discovery settings from a .well-known source.
*
* @param raw
* The raw JSON data
* @throws IllegalArgumentException
* if the data is invalid and couldn't be parsed.
*/
public WellKnownAutoDiscoverySettings(String raw) {
try {
setRaw(GsonUtil.parseObj(raw));
} catch (JsonParseException | InvalidJsonException e) {
throw new IllegalArgumentException("Invalid JSON data for .well-known string");
}
}
private void setRaw(JsonObject raw) {
this.raw = raw;
process();
}
private Optional<URL> getUrl(String url) {
try {
return Optional.of(new URL(url));
} catch (MalformedURLException e) {
log.warn("Ignoring invalid Base URL entry in well-known: {} - {}", url, e.getMessage());
return Optional.empty();
}
}
private List<URL> getUrls(JsonArray array) {
List<URL> urls = new ArrayList<>();
array.forEach(el -> {
if (!el.isJsonPrimitive()) {
log.warn("Ignoring invalid Base URL entry in well-known: {} - Not a string", GsonUtil.get().toJson(el));
return;
}
getUrl(el.getAsString()).ifPresent(urls::add);
});
return urls;
}
private List<URL> processUrls(JsonObject base, String key) {
List<URL> urls = new ArrayList<>();
GsonUtil.findObj(base, key).ifPresent(cfg -> {
log.info("Found data");
GsonUtil.findArray(cfg, "base_urls").ifPresent(arr -> {
log.info("Found base URL(s)");
urls.addAll(getUrls(arr));
});
if (urls.isEmpty()) {
GsonUtil.findString(cfg, "base_url").flatMap(this::getUrl).ifPresent(urls::add);
}
});
return urls;
}
private void process() {
log.info("Processing Homeserver Base URLs");
hsBaseUrls = processUrls(raw, "m.homeserver");
log.info("Found {} valid URL(s)", hsBaseUrls.size());
log.info("Processing Identity server Base URLs");
isBaseUrls = processUrls(raw, "m.identity_server");
log.info("Found {} valid URL(s)", isBaseUrls.size());
}
@Override
public JsonObject getRaw() {
return raw;
}
@Override
public List<URL> getHsBaseUrls() {
return Collections.unmodifiableList(hsBaseUrls);
}
@Override
public List<URL> getIsBaseUrls() {
return Collections.unmodifiableList(isBaseUrls);
}
}

View File

@@ -0,0 +1,36 @@
/*
* matrix-java-sdk - Matrix Client SDK for Java
* Copyright (C) 2018 Kamax Sarl
*
* https://www.kamax.io/
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package io.kamax.matrix.client;
import com.google.gson.JsonObject;
import java.net.URL;
import java.util.List;
public interface _AutoDiscoverySettings {
JsonObject getRaw();
List<URL> getHsBaseUrls();
List<URL> getIsBaseUrls();
}

View File

@@ -0,0 +1,39 @@
/*
* matrix-java-sdk - Matrix Client SDK for Java
* Copyright (C) 2018 Kamax Sarl
*
* https://www.kamax.io/
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package io.kamax.matrix.client;
import com.google.gson.JsonObject;
import java.util.List;
public interface _GlobalPushRulesSet {
List<JsonObject> getContent();
List<JsonObject> getOverride();
List<JsonObject> getRoom();
List<JsonObject> getSender();
List<JsonObject> getUnderride();
}

View File

@@ -0,0 +1,158 @@
/*
* matrix-java-sdk - Matrix Client SDK for Java
* Copyright (C) 2017 Kamax Sarl
*
* https://www.kamax.io/
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package io.kamax.matrix.client;
import com.google.gson.JsonObject;
import io.kamax.matrix._MatrixContent;
import io.kamax.matrix._MatrixID;
import io.kamax.matrix._MatrixUser;
import io.kamax.matrix.hs._MatrixRoom;
import io.kamax.matrix.room.RoomAlias;
import io.kamax.matrix.room._RoomAliasLookup;
import io.kamax.matrix.room._RoomCreationOptions;
import java.io.File;
import java.net.URI;
import java.util.List;
import java.util.Optional;
public interface _MatrixClient extends _MatrixClientRaw {
_MatrixID getWhoAmI();
void setDisplayName(String name);
_RoomAliasLookup lookup(RoomAlias alias);
_MatrixRoom createRoom(_RoomCreationOptions options);
_MatrixRoom getRoom(String roomId);
List<_MatrixRoom> getJoinedRooms();
_MatrixRoom joinRoom(String roomIdOrAlias);
_MatrixUser getUser(_MatrixID mxId);
Optional<String> getDeviceId();
/* Custom endpoint! */
// TODO refactor into custom synapse class?
void register(MatrixPasswordCredentials credentials, String sharedSecret, boolean admin);
/***
* Set the access token to use for any authenticated API calls.
*
* @param accessToken
* The access token provided by the server which must be valid
* @throws MatrixClientRequestException
* If an error occurred while checking for the identity behind the access token
*/
void setAccessToken(String accessToken) throws MatrixClientRequestException;
void login(MatrixPasswordCredentials credentials);
void logout();
_SyncData sync(_SyncOptions options);
/**
* Download content from the media repository
*
* @param mxUri
* The MXC URI for the content to download
* @return The content
* @throws IllegalArgumentException
* if the parameter is not a valid MXC URI
*/
_MatrixContent getMedia(String mxUri) throws IllegalArgumentException;
/**
* Download content from the media repository
*
* @param mxUri
* The MXC URI for the content to download
* @return The content
* @throws IllegalArgumentException
* if the parameter is not a valid MXC URI
*/
_MatrixContent getMedia(URI mxUri) throws IllegalArgumentException;
/**
* Upload content to the media repository
*
* @param data
* The data to send
* @param type
* The mime-type of the content upload
* @return The MXC URI for the uploaded content
*/
String putMedia(byte[] data, String type);
/**
* Upload content to the media repository
*
* @param data
* The data to send
* @param type
* The mime-type of the content upload
* @param filename
* A suggested filename for the content
* @return The MXC URI for the uploaded content
*/
String putMedia(byte[] data, String type, String filename);
/**
* Upload content to the media repository
*
* @param data
* The file to read the data from
* @param type
* The mime-type of the content upload
* @return The MXC URI for the uploaded content
*/
String putMedia(File data, String type);
/**
* Upload content to the media repository
*
* @param data
* The data to send
* @param type
* The mime-type of the content upload
* @param filename
* A suggested filename for the content
* @return The MXC URI for the uploaded content
*/
String putMedia(File data, String type, String filename);
List<JsonObject> getPushers();
void setPusher(JsonObject pusher);
void deletePusher(String pushKey);
_GlobalPushRulesSet getPushRules();
_PushRule getPushRule(String scope, String kind, String id);
}

View File

@@ -0,0 +1,51 @@
/*
* matrix-java-sdk - Matrix Client SDK for Java
* Copyright (C) 2017 Kamax Sarl
*
* https://www.kamax.io/
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package io.kamax.matrix.client;
import io.kamax.matrix._MatrixID;
import io.kamax.matrix.hs._MatrixHomeserver;
import java.util.List;
import java.util.Optional;
public interface _MatrixClientRaw {
MatrixClientContext getContext();
_MatrixHomeserver getHomeserver();
Optional<String> getAccessToken();
Optional<_MatrixID> getUser();
Optional<_AutoDiscoverySettings> discoverSettings();
// FIXME
// we should maybe have a dedicated object for HS related items and be merged into getHomeserver() which is only
// holding state at this point and is not functional
List<String> getHomeApiVersions();
// FIXME
// we should maybe have a dedicated object for IS related items. Will reconsider when implementing
// other part of the IS API
boolean validateIsBaseUrl();
}

View File

@@ -0,0 +1,29 @@
/*
* matrix-java-sdk - Matrix Client SDK for Java
* Copyright (C) 2018 Kamax Sàrl
*
* https://www.kamax.io/
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package io.kamax.matrix.client;
public interface _Presence {
String getStatus();
Long getLastActive();
}

View File

@@ -0,0 +1,43 @@
/*
* matrix-java-sdk - Matrix Client SDK for Java
* Copyright (C) 2018 Kamax Sarl
*
* https://www.kamax.io/
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package io.kamax.matrix.client;
import com.google.gson.JsonObject;
import java.util.List;
public interface _PushRule {
JsonObject getJson();
void set(JsonObject data);
void delete();
boolean isEnabled();
void setEnabled(boolean enabled);
List<String> getActions();
void setActions(List<String> data);
}

View File

@@ -0,0 +1,253 @@
/*
* matrix-java-sdk - Matrix Client SDK for Java
* Copyright (C) 2018 Kamax Sarl
*
* https://www.kamax.io/
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package io.kamax.matrix.client;
import com.google.gson.JsonObject;
import io.kamax.matrix.event._MatrixAccountDataEvent;
import io.kamax.matrix.event._MatrixEphemeralEvent;
import io.kamax.matrix.event._MatrixPersistentEvent;
import io.kamax.matrix.event._MatrixStateEvent;
import java.util.List;
import java.util.Set;
/**
* Representation of the data when performing a sync call on the Matrix Client API.
*/
public interface _SyncData {
interface State {
/**
* The state of the room.
*
* @return a list of state events.
*/
List<_MatrixStateEvent> getEvents();
}
interface Timeline {
/**
* Events that happened in the sync window.
*
* @return List of events.
*/
List<_MatrixPersistentEvent> getEvents();
/**
* If the number of events returned was limited by the sync filter.
*
* @return true if the number of events was limited, false if not.
*/
boolean isLimited();
/**
* Token that can be supplied to fetch previous events for the associated room.
*
* @return the token.
*/
String getPreviousBatchToken();
}
interface Ephemeral {
/**
* Events that happened in the sync window.
*
* @return List of events.
*/
List<_MatrixEphemeralEvent> getEvents();
}
interface AccountData {
/**
* Events that happened in the sync window.
*
* @return List of events.
*/
List<_MatrixAccountDataEvent> getEvents();
}
interface InvitedRoom {
/**
* The ID of the room the user was invited to.
*
* @return the room ID.
*/
String getId();
/**
* The state of the room at the invite event.
*
* @return a list of state events.
*/
State getState();
}
interface UnreadNotifications {
/**
* The number of unread notifications with the highlight flag set.
*
* @return the count.
*/
long getHighlightCount();
/**
* The total number of unread notifications.
*
* @return the count.
*/
long getNotificationCount();
}
interface JoinedRoom {
/**
* The ID of the room the user is joined to.
*
* @return the room id.
*/
String getId();
/**
* State changes prior the start of the timeline.
*
* @return a list of state events.
*/
State getState();
/**
* The room timeline for this sync batch.
*
* @return the timeline.
*/
Timeline getTimeline();
/**
* Ephemeral events of the room.
*
* @return a list of ephemeral events.
*/
Ephemeral getEphemeral();
/**
* Account events of the room.
*
* @return a list of account data events.
*/
AccountData getAccountData();
/**
* The Counts of unread notifications.
*
* @return unread notifications.
*/
UnreadNotifications getUnreadNotifications();
}
interface LeftRoom {
/**
* The ID of the room the user is joined to.
*
* @return the room id.
*/
String getId();
/**
* State changes prior the start of the timeline.
*
* @return a list of state events.
*/
State getState();
/**
* The room timeline up to the leave event.
*
* @return the timeline.
*/
Timeline getTimeline();
}
interface Rooms {
/**
* Rooms the user was invited to within this sync window.
*
* @return Set of InvitedRoom objects.
*/
Set<InvitedRoom> getInvited();
/**
* Rooms the user was joined in within this sync window.
*
* @return Set of JoinedRoom objects.
*/
Set<JoinedRoom> getJoined();
/**
* Rooms the user left from within this sync window.
*
* @return Set of LeftRoom objects.
*/
Set<LeftRoom> getLeft();
}
/**
* The batch token to supply in the next sync call.
*
* @return the batch token.
*/
String nextBatchToken();
/**
* The global private data created by this user.
*
* @return the account data.
*/
AccountData getAccountData();
/**
* Update to the rooms.
*
* @return rooms object.
*/
Rooms getRooms();
/**
* The raw JSON data for this object.
*
* @return the JSON data.
*/
JsonObject getJson();
}

View File

@@ -0,0 +1,65 @@
/*
* matrix-java-sdk - Matrix Client SDK for Java
* Copyright (C) 2018 Kamax Sarl
*
* https://www.kamax.io/
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package io.kamax.matrix.client;
import java.util.Optional;
/**
* Possible options that can be passed to the sync call.
*/
public interface _SyncOptions {
/**
* The point of time to continue the sync from.
*
* @return A token that was provided in a previous sync call, if set.
*/
Optional<String> getSince();
/**
* The filter to use for the sync.
*
* @return The ID or raw JSON filter, if set.
*/
Optional<String> getFilter();
/**
* If the full state should be included in the sync.
*
* @return The full state option, if set.
*/
Optional<Boolean> withFullState();
/**
* If the client should automatically be marked as online.
*
* @return The set presence option, if set.
*/
Optional<String> getSetPresence();
/**
* The maximum time to wait, in milliseconds, before ending the sync call.
*
* @return The timeout option, if set.
*/
Optional<Long> getTimeout();
}

View File

@@ -0,0 +1,87 @@
/*
* matrix-java-sdk - Matrix Client SDK for Java
* Copyright (C) 2017 Kamax Sarl
*
* https://www.kamax.io/
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package io.kamax.matrix.client.as;
import io.kamax.matrix.client.MatrixClientContext;
import io.kamax.matrix.client.MatrixClientDefaults;
import io.kamax.matrix.client._MatrixClient;
import io.kamax.matrix.client.regular.MatrixHttpClient;
import io.kamax.matrix.json.VirtualUserRegistrationBody;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.net.URL;
import okhttp3.OkHttpClient;
import okhttp3.Request;
public class MatrixApplicationServiceClient extends MatrixHttpClient implements _MatrixApplicationServiceClient {
private Logger log = LoggerFactory.getLogger(MatrixApplicationServiceClient.class);
public MatrixApplicationServiceClient(String domain) {
super(domain);
}
public MatrixApplicationServiceClient(URL hsBaseUrl) {
super(hsBaseUrl);
}
public MatrixApplicationServiceClient(MatrixClientContext context) {
super(context);
}
public MatrixApplicationServiceClient(MatrixClientContext context, OkHttpClient.Builder client) {
super(context, client);
}
public MatrixApplicationServiceClient(MatrixClientContext context, OkHttpClient.Builder client,
MatrixClientDefaults defaults) {
super(context, client, defaults);
}
public MatrixApplicationServiceClient(MatrixClientContext context, OkHttpClient client) {
super(context, client);
}
private MatrixHttpClient createClient(String localpart) {
MatrixClientContext context = new MatrixClientContext(getContext()).setUserWithLocalpart(localpart)
.setVirtual(true);
return new MatrixHttpClient(context);
}
@Override
public _MatrixClient createUser(String localpart) {
log.debug("Creating new user {}", localpart);
URL path = getClientPath("register");
executeAuthenticated(
new Request.Builder().post(getJsonBody(new VirtualUserRegistrationBody(localpart))).url(path));
return createClient(localpart);
}
@Override
public _MatrixClient getUser(String localpart) {
return createClient(localpart);
}
}

View File

@@ -0,0 +1,31 @@
/*
* matrix-java-sdk - Matrix Client SDK for Java
* Copyright (C) 2017 Kamax Sarl
*
* https://www.kamax.io/
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package io.kamax.matrix.client.as;
import io.kamax.matrix.client._MatrixClient;
public interface _MatrixApplicationServiceClient extends _MatrixClient {
_MatrixClient createUser(String localpart);
_MatrixClient getUser(String localpart);
}

View File

@@ -0,0 +1,68 @@
/*
* matrix-java-sdk - Matrix Client SDK for Java
* Copyright (C) 2018 Kamax Sarl
*
* https://www.kamax.io/
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package io.kamax.matrix.client.regular;
import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
import io.kamax.matrix.client._GlobalPushRulesSet;
import io.kamax.matrix.json.GsonUtil;
import java.util.List;
public class GlobalPushRulesSet implements _GlobalPushRulesSet {
private JsonObject data;
public GlobalPushRulesSet(JsonObject data) {
this.data = data;
}
private List<JsonObject> getForKey(String key) {
return GsonUtil.asList(GsonUtil.findArray(data, key).orElseGet(JsonArray::new), JsonObject.class);
}
@Override
public List<JsonObject> getContent() {
return getForKey("content");
}
@Override
public List<JsonObject> getOverride() {
return getForKey("override");
}
@Override
public List<JsonObject> getRoom() {
return getForKey("room");
}
@Override
public List<JsonObject> getSender() {
return getForKey("sender");
}
@Override
public List<JsonObject> getUnderride() {
return getForKey("underride");
}
}

View File

@@ -0,0 +1,292 @@
/*
* matrix-java-sdk - Matrix Client SDK for Java
* Copyright (C) 2017 Kamax Sarl
*
* https://www.kamax.io/
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package io.kamax.matrix.client.regular;
import com.google.gson.JsonNull;
import com.google.gson.JsonObject;
import io.kamax.matrix.MatrixID;
import io.kamax.matrix._MatrixContent;
import io.kamax.matrix._MatrixID;
import io.kamax.matrix._MatrixUser;
import io.kamax.matrix.client.*;
import io.kamax.matrix.hs._MatrixRoom;
import io.kamax.matrix.json.*;
import io.kamax.matrix.room.RoomAlias;
import io.kamax.matrix.room.RoomAliasLookup;
import io.kamax.matrix.room._RoomAliasLookup;
import io.kamax.matrix.room._RoomCreationOptions;
import org.apache.commons.codec.digest.HmacAlgorithms;
import org.apache.commons.codec.digest.HmacUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.File;
import java.net.URI;
import java.net.URL;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
import okhttp3.*;
public class MatrixHttpClient extends AMatrixHttpClient implements _MatrixClient {
private Logger log = LoggerFactory.getLogger(MatrixHttpClient.class);
public MatrixHttpClient(String domain) {
super(domain);
}
public MatrixHttpClient(URL hsBaseUrl) {
super(hsBaseUrl);
}
public MatrixHttpClient(MatrixClientContext context) {
super(context);
}
public MatrixHttpClient(MatrixClientContext context, OkHttpClient.Builder client) {
super(context, client);
}
public MatrixHttpClient(MatrixClientContext context, OkHttpClient.Builder client, MatrixClientDefaults defaults) {
super(context, client, defaults);
}
public MatrixHttpClient(MatrixClientContext context, OkHttpClient client) {
super(context, client);
}
protected _MatrixID getIdentity(String token) {
URL path = getClientPath("account", "whoami");
String body = executeAuthenticated(new Request.Builder().get().url(path), token);
return MatrixID.from(GsonUtil.getStringOrThrow(GsonUtil.parseObj(body), "user_id")).acceptable();
}
@Override
public _MatrixID getWhoAmI() {
URL path = getClientPath("account", "whoami");
String body = executeAuthenticated(new Request.Builder().get().url(path));
return MatrixID.from(GsonUtil.getStringOrThrow(GsonUtil.parseObj(body), "user_id")).acceptable();
}
@Override
public void setDisplayName(String name) {
URL path = getClientPath("profile", getUserId(), "displayname");
execute(new Request.Builder().put(getJsonBody(new UserDisplaynameSetBody(name))).url(path));
}
@Override
public _RoomAliasLookup lookup(RoomAlias alias) {
URL path = getClientPath("directory", "room", alias.getId());
String resBody = execute(new Request.Builder().get().url(path));
RoomAliasLookupJson lookup = GsonUtil.get().fromJson(resBody, RoomAliasLookupJson.class);
return new RoomAliasLookup(lookup.getRoomId(), alias.getId(), lookup.getServers());
}
@Override
public _MatrixRoom createRoom(_RoomCreationOptions options) {
URL path = getClientPath("createRoom");
String resBody = executeAuthenticated(
new Request.Builder().post(getJsonBody(new RoomCreationRequestJson(options))).url(path));
String roomId = GsonUtil.get().fromJson(resBody, RoomCreationResponseJson.class).getRoomId();
return getRoom(roomId);
}
@Override
public _MatrixRoom getRoom(String roomId) {
return new MatrixHttpRoom(getContext(), roomId);
}
@Override
public List<_MatrixRoom> getJoinedRooms() {
URL path = getClientPath("joined_rooms");
JsonObject resBody = GsonUtil.parseObj(executeAuthenticated(new Request.Builder().get().url(path)));
return GsonUtil.asList(resBody, "joined_rooms", String.class).stream().map(this::getRoom)
.collect(Collectors.toList());
}
@Override
public _MatrixRoom joinRoom(String roomIdOrAlias) {
URL path = getClientPath("join", roomIdOrAlias);
String resBody = executeAuthenticated(new Request.Builder().post(getJsonBody(new JsonObject())).url(path));
String roomId = GsonUtil.get().fromJson(resBody, RoomCreationResponseJson.class).getRoomId();
return getRoom(roomId);
}
@Override
public _MatrixUser getUser(_MatrixID mxId) {
return new MatrixHttpUser(getContext(), mxId);
}
@Override
public Optional<String> getDeviceId() {
return Optional.ofNullable(context.getDeviceId());
}
protected void updateContext(String resBody) {
LoginResponse response = gson.fromJson(resBody, LoginResponse.class);
context.setToken(response.getAccessToken());
context.setDeviceId(response.getDeviceId());
context.setUser(MatrixID.asAcceptable(response.getUserId()));
}
@Override
public void register(MatrixPasswordCredentials credentials, String sharedSecret, boolean admin) {
// As per synapse registration script:
// https://github.com/matrix-org/synapse/blob/master/scripts/register_new_matrix_user#L28
String value = credentials.getLocalPart() + "\0" + credentials.getPassword() + "\0"
+ (admin ? "admin" : "notadmin");
String mac = new HmacUtils(HmacAlgorithms.HMAC_SHA_1, sharedSecret).hmacHex(value);
JsonObject body = new JsonObject();
body.addProperty("user", credentials.getLocalPart());
body.addProperty("password", credentials.getPassword());
body.addProperty("mac", mac);
body.addProperty("type", "org.matrix.login.shared_secret");
body.addProperty("admin", false);
URL url = getPath("client", "api", "v1", "register");
updateContext(execute(new Request.Builder().post(getJsonBody(body)).url(url)));
}
@Override
public void setAccessToken(String accessToken) {
context.setUser(getIdentity(accessToken));
context.setToken(accessToken);
}
@Override
public void login(MatrixPasswordCredentials credentials) {
URL url = getClientPath("login");
LoginPostBody data = new LoginPostBody(credentials.getLocalPart(), credentials.getPassword());
getDeviceId().ifPresent(data::setDeviceId);
Optional.ofNullable(context.getInitialDeviceName()).ifPresent(data::setInitialDeviceDisplayName);
updateContext(execute(new Request.Builder().post(getJsonBody(data)).url(url)));
}
@Override
public void logout() {
URL path = getClientPath("logout");
executeAuthenticated(new Request.Builder().post(getJsonBody(new JsonObject())).url(path));
context.setToken(null);
context.setUser(null);
context.setDeviceId(null);
}
@Override
public _SyncData sync(_SyncOptions options) {
long start = System.currentTimeMillis();
HttpUrl.Builder path = getClientPathBuilder("sync");
path.addQueryParameter("timeout", options.getTimeout().map(Long::intValue).orElse(30000).toString());
options.getSince().ifPresent(since -> path.addQueryParameter("since", since));
options.getFilter().ifPresent(filter -> path.addQueryParameter("filter", filter));
options.withFullState().ifPresent(state -> path.addQueryParameter("full_state", state ? "true" : "false"));
options.getSetPresence().ifPresent(presence -> path.addQueryParameter("presence", presence));
String body = executeAuthenticated(new Request.Builder().get().url(path.build().url()));
long request = System.currentTimeMillis();
log.info("Sync: network request took {} ms", (request - start));
SyncDataJson data = new SyncDataJson(GsonUtil.parseObj(body));
long parsing = System.currentTimeMillis();
log.info("Sync: parsing took {} ms", (parsing - request));
return data;
}
@Override
public _MatrixContent getMedia(String mxUri) throws IllegalArgumentException {
return getMedia(URI.create(mxUri));
}
@Override
public _MatrixContent getMedia(URI mxUri) throws IllegalArgumentException {
return new MatrixHttpContent(context, mxUri);
}
private String putMedia(Request.Builder builder, String filename) {
HttpUrl.Builder b = getMediaPathBuilder("upload");
if (StringUtils.isNotEmpty(filename)) b.addQueryParameter("filename", filename);
String body = executeAuthenticated(builder.url(b.build()));
return GsonUtil.getStringOrThrow(GsonUtil.parseObj(body), "content_uri");
}
@Override
public String putMedia(byte[] data, String type) {
return putMedia(data, type, null);
}
@Override
public String putMedia(byte[] data, String type, String filename) {
return putMedia(new Request.Builder().post(RequestBody.create(MediaType.parse(type), data)), filename);
}
@Override
public String putMedia(File data, String type) {
return putMedia(data, type, null);
}
@Override
public String putMedia(File data, String type, String filename) {
return putMedia(new Request.Builder().post(RequestBody.create(MediaType.parse(type), data)), filename);
}
@Override
public List<JsonObject> getPushers() {
URL url = getClientPath("pushers");
JsonObject response = GsonUtil.parseObj(executeAuthenticated(new Request.Builder().get().url(url)));
return GsonUtil.findArray(response, "pushers").map(array -> GsonUtil.asList(array, JsonObject.class))
.orElse(Collections.emptyList());
}
@Override
public void setPusher(JsonObject pusher) {
URL url = getClientPath("pushers", "set");
executeAuthenticated(new Request.Builder().url(url).post(getJsonBody(pusher)));
}
@Override
public void deletePusher(String pushKey) {
JsonObject pusher = new JsonObject();
pusher.add("kind", JsonNull.INSTANCE);
pusher.addProperty("pushkey", pushKey);
setPusher(pusher);
}
@Override
public _GlobalPushRulesSet getPushRules() {
URL url = getClientPath("pushrules", "global", "");
JsonObject response = GsonUtil.parseObj(executeAuthenticated(new Request.Builder().url(url).get()));
return new GlobalPushRulesSet(response);
}
@Override
public _PushRule getPushRule(String scope, String kind, String id) {
return new MatrixHttpPushRule(context, scope, kind, id);
}
}

View File

@@ -0,0 +1,48 @@
/*
* matrix-java-sdk - Matrix Client SDK for Java
* Copyright (C) 2018 Kamax Sàrl
*
* https://www.kamax.io/
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package io.kamax.matrix.client.regular;
import com.google.gson.JsonObject;
import io.kamax.matrix.client._Presence;
import io.kamax.matrix.json.GsonUtil;
public class Presence implements _Presence {
private String status;
private Long lastActive;
public Presence(JsonObject json) {
this.status = GsonUtil.getStringOrThrow(json, "presence");
this.lastActive = GsonUtil.getLong(json, "last_active_ago");
}
@Override
public String getStatus() {
return status;
}
@Override
public Long getLastActive() {
return lastActive;
}
}

View File

@@ -0,0 +1,390 @@
/*
* matrix-java-sdk - Matrix Client SDK for Java
* Copyright (C) 2018 Kamax Sarl
*
* https://www.kamax.io/
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package io.kamax.matrix.client.regular;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import io.kamax.matrix.MatrixID;
import io.kamax.matrix._MatrixID;
import io.kamax.matrix.client._SyncData;
import io.kamax.matrix.event.EventKey;
import io.kamax.matrix.event._MatrixAccountDataEvent;
import io.kamax.matrix.event._MatrixEphemeralEvent;
import io.kamax.matrix.event._MatrixPersistentEvent;
import io.kamax.matrix.event._MatrixStateEvent;
import io.kamax.matrix.json.MatrixJsonObject;
import java.util.*;
public class SyncDataJson extends MatrixJsonObject implements _SyncData {
public class MatrixPersistentEventJson extends MatrixJsonObject implements _MatrixPersistentEvent {
public MatrixPersistentEventJson(JsonObject obj) {
super(obj);
}
@Override
public String getId() {
return findString(EventKey.Id.get()).orElse(""); // FIXME refactor event structure
}
@Override
public String getType() {
return getString(EventKey.Type.get());
}
@Override
public Long getTime() {
return getLong(EventKey.Timestamp.get());
}
@Override
public _MatrixID getSender() {
return MatrixID.from(getString(EventKey.Sender.get())).acceptable();
}
}
public class MatrixEphemeralEventJson extends MatrixJsonObject implements _MatrixEphemeralEvent {
public MatrixEphemeralEventJson(JsonObject obj) {
super(obj);
}
@Override
public String getType() {
return getString(EventKey.Type.get());
}
}
public class MatrixAccountDataEventJson extends MatrixJsonObject implements _MatrixAccountDataEvent {
public MatrixAccountDataEventJson(JsonObject obj) {
super(obj);
}
@Override
public String getType() {
return getString(EventKey.Type.get());
}
}
public class MatrixStateEventJson extends MatrixPersistentEventJson implements _MatrixStateEvent {
public MatrixStateEventJson(JsonObject obj) {
super(obj);
}
@Override
public String getStateKey() {
return getString(EventKey.StateKey.get());
}
}
public class StateJson extends MatrixJsonObject implements _SyncData.State {
private List<_MatrixStateEvent> events = new ArrayList<>();
public StateJson(JsonObject obj) {
super(obj);
findArray("events").ifPresent(array -> {
for (JsonElement el : array) {
events.add(new MatrixStateEventJson(asObj(el)));
}
});
}
@Override
public List<_MatrixStateEvent> getEvents() {
return events;
}
}
public class TimelineJson extends MatrixJsonObject implements _SyncData.Timeline {
private List<_MatrixPersistentEvent> events = new ArrayList<>();
public TimelineJson(JsonObject obj) {
super(obj);
findArray("events").ifPresent(array -> {
for (JsonElement el : array) {
events.add(new MatrixPersistentEventJson(asObj(el)));
}
});
}
@Override
public List<_MatrixPersistentEvent> getEvents() {
return events;
}
@Override
public boolean isLimited() {
return findString("limited").map("true"::equals).orElse(false);
}
@Override
public String getPreviousBatchToken() {
return getString("prev_batch");
}
}
public class EphemeralJson extends MatrixJsonObject implements _SyncData.Ephemeral {
private List<_MatrixEphemeralEvent> events = new ArrayList<>();
public EphemeralJson(JsonObject obj) {
super(obj);
findArray("events").ifPresent(array -> {
for (JsonElement el : array) {
events.add(new MatrixEphemeralEventJson(asObj(el)));
}
});
}
@Override
public List<_MatrixEphemeralEvent> getEvents() {
return events;
}
}
public class AccountDataJson extends MatrixJsonObject implements _SyncData.AccountData {
private List<_MatrixAccountDataEvent> events = new ArrayList<>();
public AccountDataJson(JsonObject obj) {
super(obj);
findArray("events").ifPresent(array -> {
for (JsonElement el : array) {
events.add(new MatrixAccountDataEventJson(asObj(el)));
}
});
}
@Override
public List<_MatrixAccountDataEvent> getEvents() {
return events;
}
}
public class InvitedRoomJson extends MatrixJsonObject implements _SyncData.InvitedRoom {
private String id;
private State state;
public InvitedRoomJson(String id, JsonObject data) {
super(data);
this.id = id;
this.state = new StateJson(findObj("invite_state").orElseGet(JsonObject::new));
}
@Override
public String getId() {
return id;
}
@Override
public State getState() {
return state;
}
}
public class UnreadNotificationsJson extends MatrixJsonObject implements _SyncData.UnreadNotifications {
private long highlights;
private long global;
public UnreadNotificationsJson(JsonObject data) {
super(data);
this.highlights = findLong("highlight_count").orElse(0L);
this.global = findLong("notification_count").orElse(0L);
}
@Override
public long getHighlightCount() {
return highlights;
}
@Override
public long getNotificationCount() {
return global;
}
}
public class JoinedRoomJson extends MatrixJsonObject implements _SyncData.JoinedRoom {
private String id;
private State state;
private Timeline timeline;
private UnreadNotifications unreadNotifications;
private Ephemeral ephemeral;
private AccountData accountData;
public JoinedRoomJson(String id, JsonObject data) {
super(data);
this.id = id;
this.state = new StateJson(findObj("state").orElseGet(JsonObject::new));
this.timeline = new TimelineJson(findObj("timeline").orElseGet(JsonObject::new));
this.unreadNotifications = new UnreadNotificationsJson(computeObj("unread_notifications"));
this.ephemeral = new EphemeralJson(findObj("ephemeral").orElseGet(JsonObject::new));
this.accountData = new AccountDataJson(findObj("account_data").orElseGet(JsonObject::new));
}
@Override
public String getId() {
return id;
}
@Override
public State getState() {
return state;
}
@Override
public Timeline getTimeline() {
return timeline;
}
@Override
public Ephemeral getEphemeral() {
return ephemeral;
}
@Override
public AccountData getAccountData() {
return accountData;
}
@Override
public UnreadNotifications getUnreadNotifications() {
return unreadNotifications;
}
}
public class LeftRoomJson extends MatrixPersistentEventJson implements _SyncData.LeftRoom {
private String id;
private State state;
private Timeline timeline;
public LeftRoomJson(String id, JsonObject data) {
super(data);
this.id = id;
this.state = new StateJson(findObj("state").orElseGet(JsonObject::new));
this.timeline = new TimelineJson(findObj("timeline").orElseGet(JsonObject::new));
}
@Override
public String getId() {
return id;
}
@Override
public State getState() {
return state;
}
@Override
public Timeline getTimeline() {
return timeline;
}
}
public class RoomsJson extends MatrixJsonObject implements _SyncData.Rooms {
private Set<InvitedRoom> invited = new HashSet<>();
private Set<JoinedRoom> joined = new HashSet<>();
private Set<LeftRoom> left = new HashSet<>();
public RoomsJson(JsonObject obj) {
super(obj);
findObj("invite").ifPresent(o -> {
for (Map.Entry<String, JsonElement> entry : o.entrySet()) {
invited.add(new InvitedRoomJson(entry.getKey(), asObj(entry.getValue())));
}
});
findObj("join").ifPresent(o -> {
for (Map.Entry<String, JsonElement> entry : o.entrySet()) {
joined.add(new JoinedRoomJson(entry.getKey(), asObj(entry.getValue())));
}
});
findObj("leave").ifPresent(o -> {
for (Map.Entry<String, JsonElement> entry : o.entrySet()) {
left.add(new LeftRoomJson(entry.getKey(), asObj(entry.getValue())));
}
});
}
@Override
public Set<InvitedRoom> getInvited() {
return invited;
}
@Override
public Set<JoinedRoom> getJoined() {
return joined;
}
@Override
public Set<LeftRoom> getLeft() {
return left;
}
}
private String nextBatch;
private AccountDataJson accountData;
private RoomsJson rooms;
public SyncDataJson(JsonObject data) {
super(data);
nextBatch = getString("next_batch");
accountData = new AccountDataJson(findObj("account_data").orElseGet(JsonObject::new));
rooms = new RoomsJson(findObj("rooms").orElseGet(JsonObject::new));
}
@Override
public String nextBatchToken() {
return nextBatch;
}
@Override
public AccountData getAccountData() {
return accountData;
}
@Override
public Rooms getRooms() {
return rooms;
}
}

View File

@@ -0,0 +1,103 @@
/*
* matrix-java-sdk - Matrix Client SDK for Java
* Copyright (C) 2018 Kamax Sarl
*
* https://www.kamax.io/
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package io.kamax.matrix.client.regular;
import io.kamax.matrix.client._SyncOptions;
import java.util.Optional;
public class SyncOptions implements _SyncOptions {
public static class Builder {
private final SyncOptions obj;
public Builder() {
this.obj = new SyncOptions();
}
public SyncOptions get() {
return obj;
}
public Builder setSince(String since) {
obj.since = since;
return this;
}
public Builder setFilter(String filter) {
obj.filter = filter;
return this;
}
public Builder setWithFullState(boolean withFullState) {
obj.fullState = withFullState;
return this;
}
public Builder setPresence(boolean setPresence) {
obj.setPresence = setPresence ? null : "offline";
return this;
}
public Builder setTimeout(long timeout) {
obj.timeout = timeout;
return this;
}
}
public static Builder build() {
return new Builder();
}
private String since;
private String filter;
private Boolean fullState;
private String setPresence;
private Long timeout;
@Override
public Optional<String> getSince() {
return Optional.ofNullable(since);
}
@Override
public Optional<String> getFilter() {
return Optional.ofNullable(filter);
}
@Override
public Optional<Boolean> withFullState() {
return Optional.ofNullable(fullState);
}
@Override
public Optional<String> getSetPresence() {
return Optional.ofNullable(setPresence);
}
@Override
public Optional<Long> getTimeout() {
return Optional.ofNullable(timeout);
}
}

View File

@@ -0,0 +1,36 @@
/*
* matrix-java-sdk - Matrix Client SDK for Java
* Copyright (C) 2017 Kamax Sarl
*
* https://www.kamax.io/
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package io.kamax.matrix.codec;
import java.nio.charset.StandardCharsets;
import java.util.Base64;
public class MxBase64 {
public static String encode(byte[] data) {
return Base64.getEncoder().withoutPadding().encodeToString(data);
}
public static String encode(String data) {
return encode(data.getBytes(StandardCharsets.UTF_8));
}
}

View File

@@ -0,0 +1,80 @@
/*
* matrix-java-sdk - Matrix Client SDK for Java
* Copyright (C) 2017 Kamax Sarl
*
* https://www.kamax.io/
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package io.kamax.matrix.crypto;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringUtils;
import java.io.File;
import java.io.IOException;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
public class KeyFileStore implements _KeyStore {
private final Charset charset = StandardCharsets.UTF_8;
private File file;
public KeyFileStore(String path) {
File file = new File(path);
if (!file.exists()) {
throw new IllegalArgumentException("Signing key file storage " + path + " does not exist");
}
if (file.isDirectory()) {
throw new IllegalArgumentException("Signing key file storage " + path + " is a directory");
}
if (!file.isFile()) {
throw new IllegalArgumentException("Signing key file storage " + path + " is not a regular file");
}
if (!file.canRead()) {
throw new IllegalArgumentException("Signing key file storage " + path + " is not readable");
}
this.file = file;
}
@Override
public Optional<String> load() {
try {
List<String> keys = FileUtils.readLines(file, charset);
return keys.stream().filter(StringUtils::isNotBlank).findFirst();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
@Override
public void store(String key) {
try {
FileUtils.writeLines(file, charset.name(), Collections.singletonList(key), false);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}

View File

@@ -0,0 +1,100 @@
/*
* matrix-java-sdk - Matrix Client SDK for Java
* Copyright (C) 2017 Kamax Sarl
*
* https://www.kamax.io/
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package io.kamax.matrix.crypto;
import io.kamax.matrix.codec.MxBase64;
import java.security.KeyPair;
import java.util.ArrayList;
import java.util.Base64;
import java.util.List;
import net.i2p.crypto.eddsa.EdDSAPrivateKey;
import net.i2p.crypto.eddsa.EdDSAPublicKey;
import net.i2p.crypto.eddsa.KeyPairGenerator;
import net.i2p.crypto.eddsa.spec.EdDSANamedCurveTable;
import net.i2p.crypto.eddsa.spec.EdDSAParameterSpec;
import net.i2p.crypto.eddsa.spec.EdDSAPrivateKeySpec;
import net.i2p.crypto.eddsa.spec.EdDSAPublicKeySpec;
public class KeyManager {
public static KeyManager fromFile(String path) {
return new KeyManager(new KeyFileStore(path));
}
public static KeyManager fromMemory() {
return new KeyManager(new KeyMemoryStore());
}
private EdDSAParameterSpec keySpecs;
private List<KeyPair> keys;
public KeyManager(_KeyStore store) {
keySpecs = EdDSANamedCurveTable.getByName(EdDSANamedCurveTable.ED_25519);
keys = new ArrayList<>();
String seedBase64 = store.load().orElseGet(() -> {
KeyPair pair = (new KeyPairGenerator()).generateKeyPair();
String keyEncoded = getPrivateKeyBase64((EdDSAPrivateKey) pair.getPrivate());
store.store(keyEncoded);
return keyEncoded;
});
byte[] seed = Base64.getDecoder().decode(seedBase64);
EdDSAPrivateKeySpec privKeySpec = new EdDSAPrivateKeySpec(seed, keySpecs);
EdDSAPublicKeySpec pubKeySpec = new EdDSAPublicKeySpec(privKeySpec.getA(), keySpecs);
keys.add(new KeyPair(new EdDSAPublicKey(pubKeySpec), new EdDSAPrivateKey(privKeySpec)));
}
public int getCurrentIndex() {
return 0;
}
public KeyPair getKeys(int index) {
return keys.get(index);
}
public EdDSAPrivateKey getPrivateKey(int index) {
return (EdDSAPrivateKey) getKeys(index).getPrivate();
}
protected String getPrivateKeyBase64(EdDSAPrivateKey key) {
return MxBase64.encode(key.getSeed());
}
public String getPrivateKeyBase64(int index) {
return getPrivateKeyBase64(getPrivateKey(index));
}
public EdDSAPublicKey getPublicKey(int index) {
return (EdDSAPublicKey) getKeys(index).getPublic();
}
public EdDSAParameterSpec getSpecs() {
return keySpecs;
}
public String getPublicKeyBase64(int index) {
return MxBase64.encode(getPublicKey(index).getAbyte());
}
}

View File

@@ -0,0 +1,46 @@
/*
* matrix-java-sdk - Matrix Client SDK for Java
* Copyright (C) 2017 Kamax Sarl
*
* https://www.kamax.io/
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package io.kamax.matrix.crypto;
import java.util.Optional;
public class KeyMemoryStore implements _KeyStore {
private String data;
public KeyMemoryStore() {
}
public KeyMemoryStore(String data) {
this.data = data;
}
@Override
public Optional<String> load() {
return Optional.ofNullable(data);
}
@Override
public void store(String key) {
data = key;
}
}

View File

@@ -0,0 +1,80 @@
/*
* matrix-java-sdk - Matrix Client SDK for Java
* Copyright (C) 2017 Kamax Sarl
*
* https://www.kamax.io/
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package io.kamax.matrix.crypto;
import com.google.gson.JsonObject;
import io.kamax.matrix.codec.MxBase64;
import io.kamax.matrix.json.MatrixJson;
import java.security.InvalidKeyException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.SignatureException;
import net.i2p.crypto.eddsa.EdDSAEngine;
public class SignatureManager {
private KeyManager keyMgr;
private String domain;
private EdDSAEngine signEngine;
public SignatureManager(KeyManager keyMgr, String domain) {
this.keyMgr = keyMgr;
this.domain = domain;
try {
signEngine = new EdDSAEngine(MessageDigest.getInstance(keyMgr.getSpecs().getHashAlgorithm()));
signEngine.initSign(keyMgr.getPrivateKey(keyMgr.getCurrentIndex()));
} catch (NoSuchAlgorithmException | InvalidKeyException e) {
throw new RuntimeException(e);
}
}
public String sign(JsonObject obj) {
return sign(MatrixJson.encodeCanonical(obj));
}
public String sign(String message) {
try {
byte[] signRaw = signEngine.signOneShot(message.getBytes());
return MxBase64.encode(signRaw);
} catch (SignatureException e) {
throw new RuntimeException(e);
}
}
public JsonObject signMessageGson(String message) {
String sign = sign(message);
JsonObject keySignature = new JsonObject();
// FIXME should create a signing key object what would give this ed and index values
keySignature.addProperty("ed25519:" + keyMgr.getCurrentIndex(), sign);
JsonObject signature = new JsonObject();
signature.add(domain, keySignature);
return signature;
}
}

View File

@@ -0,0 +1,31 @@
/*
* matrix-java-sdk - Matrix Client SDK for Java
* Copyright (C) 2017 Kamax Sarl
*
* https://www.kamax.io/
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package io.kamax.matrix.crypto;
import java.util.Optional;
public interface _KeyStore {
Optional<String> load();
void store(String key);
}

Some files were not shown because too many files have changed in this diff Show More