Compare commits
	
		
			137 Commits
		
	
	
		
			v1.3.0-rc.
			...
			2.2.0-rc1
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|  | 494c9e3941 | ||
|  | 0786a6520f | ||
|  | 430136c391 | ||
|  | eda4404335 | ||
|  | c52034b18a | ||
|  | 8d346037b7 | ||
|  | 14ad4435bc | ||
|  | 94441d0446 | ||
|  | b4776b50e2 | ||
|  | 2458b38b75 | ||
|  | 249e28a8b5 | ||
|  | 8ba8756871 | ||
|  | ba9e2d6121 | ||
|  | f042b82a50 | ||
|  | 59071177ad | ||
|  | 6450cd1f20 | ||
|  | 90bc244f3e | ||
|  | 6e52a509db | ||
|  | 5ca666981a | ||
|  | 43fe8b1aec | ||
|  | a0270c7d01 | ||
|  | 703044d06a | ||
|  | add6ed8fd9 | ||
|  | baed894ff8 | ||
|  | 14e095a147 | ||
|  | bc8795e940 | ||
|  | 5521c0c338 | ||
|  | 614b3440e2 | ||
|  | d0fd9fb9b0 | ||
|  | 1232e9ce79 | ||
|  | a47a983c10 | ||
|  | fbb0d7c7ba | ||
|  | f1dd309551 | ||
|  | 36f22e5ca6 | ||
|  | a112a5e57c | ||
|  | dbc764fe65 | ||
|  | d5680b2dfe | ||
|  | 5aad4fb81e | ||
|  | a1f64f5159 | ||
|  | a96920f533 | ||
|  | 9ca2ebdad0 | ||
|  | 7f284ac71e | ||
|  | 4d488a3fc8 | ||
|  | 7ee3e19de4 | ||
|  | 608938c084 | ||
|  | e6fec9199d | ||
|  | c3262a9f25 | ||
|  | 136563c61a | ||
|  | 3043cd4e61 | ||
|  | 21d9d0fda1 | ||
|  | a964b073bf | ||
|  | f85345bc97 | ||
|  | 29603682e5 | ||
|  | d54f1dcb88 | ||
|  | 92f10347d1 | ||
|  | 0298f66212 | ||
|  | 0ddd086bda | ||
|  | 544f8e59f0 | ||
|  | 917f87bf8c | ||
|  | 774795c203 | ||
|  | 27b2976e42 | ||
|  | f16f184253 | ||
|  | cd890d114a | ||
|  | 321ba1e325 | ||
|  | c3ce0a17f6 | ||
|  | 0fcc0d9bb2 | ||
|  | ce7f900543 | ||
|  | c7c009f9af | ||
|  | 3b01663245 | ||
|  | 9cc601d582 | ||
|  | e6272b1827 | ||
|  | 8243354f39 | ||
|  | 25968e0737 | ||
|  | 44a80461a0 | ||
|  | 85d9f9e704 | ||
|  | 6278301672 | ||
|  | 5ed0c66cfd | ||
|  | ea58b6985a | ||
|  | a44f781495 | ||
|  | 0d42ee695a | ||
|  | f331af0941 | ||
|  | e2c8a56135 | ||
|  | a67c5d7ae1 | ||
|  | 80352070f1 | ||
|  | 39447b8b8b | ||
|  | 9d4680f55a | ||
|  | d1ea0fbf0f | ||
|  | ee21f051fb | ||
|  | 6cc17abf2c | ||
|  | a7b5accd75 | ||
|  | 6bb0c93f57 | ||
|  | 9abdcc15ba | ||
|  | eb903bf226 | ||
|  | 1cbb0a135b | ||
|  | 1587103c0a | ||
|  | 838d79ae15 | ||
|  | 96c47ecf76 | ||
|  | c5cea933a4 | ||
|  | 57c7e4a91d | ||
|  | 1dce59a02e | ||
|  | de840b9d00 | ||
|  | 53c85d2248 | ||
|  | 254dc5684f | ||
|  | de92e98f7d | ||
|  | d5f9137056 | ||
|  | 1307e3aa43 | ||
|  | dfedde0df6 | ||
|  | 93bd7354c2 | ||
|  | c302789898 | ||
|  | 96155c1876 | ||
|  | 95ee328281 | ||
|  | 72a1794cc3 | ||
|  | 37ddd0e588 | ||
|  | 4d63bba251 | ||
|  | aadfae2965 | ||
|  | 2f7e5e4025 | ||
|  | 77dc75d383 | ||
|  | f3b528d1ba | ||
|  | 91e5e08e70 | ||
|  | acd8c7d7c5 | ||
|  | 249cc0ea92 | ||
|  | 99697d7c75 | ||
|  | e133e120d7 | ||
|  | e39d6bfa10 | ||
|  | 217bc423ed | ||
|  | 8f0654c34e | ||
|  | 8afdb3ed83 | ||
|  | bd4ccbc5e5 | ||
|  | 6d1c6ed109 | ||
|  | 1619f5311c | ||
|  | 6fa36ea092 | ||
|  | 471e06536b | ||
|  | 3a6b75996c | ||
|  | 566e4f3137 | ||
|  | a4c18dee5d | ||
|  | 8d6850d346 | ||
|  | 67bc18af7d | 
							
								
								
									
										4
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							| @@ -7,8 +7,8 @@ out/ | |||||||
| .idea/ | .idea/ | ||||||
|  |  | ||||||
| # Local dev config | # Local dev config | ||||||
| /mxisd.yaml | /ma1sd.yaml | ||||||
| /application.yaml | /application.yaml | ||||||
|  |  | ||||||
| # Local dev storage | # Local dev storage | ||||||
| /mxisd.db | /ma1sd.db | ||||||
|   | |||||||
							
								
								
									
										14
									
								
								Dockerfile
									
									
									
									
									
								
							
							
						
						
									
										14
									
								
								Dockerfile
									
									
									
									
									
								
							| @@ -2,17 +2,17 @@ FROM openjdk:8-jre-alpine | |||||||
|  |  | ||||||
| RUN apk update && apk add bash && rm -rf /var/lib/apk/* /var/cache/apk/* | RUN apk update && apk add bash && rm -rf /var/lib/apk/* /var/cache/apk/* | ||||||
|  |  | ||||||
| VOLUME /etc/mxisd | VOLUME /etc/ma1sd | ||||||
| VOLUME /var/mxisd | VOLUME /var/ma1sd | ||||||
| EXPOSE 8090 | EXPOSE 8090 | ||||||
|  |  | ||||||
| ENV JAVA_OPTS="" | ENV JAVA_OPTS="" | ||||||
| ENV CONF_FILE_PATH="/etc/mxisd/mxisd.yaml" | ENV CONF_FILE_PATH="/etc/ma1sd/ma1sd.yaml" | ||||||
| ENV SIGN_KEY_PATH="/var/mxisd/sign.key" | ENV SIGN_KEY_PATH="/var/ma1sd/sign.key" | ||||||
| ENV SQLITE_DATABASE_PATH="/var/mxisd/mxisd.db" | ENV SQLITE_DATABASE_PATH="/var/ma1sd/ma1sd.db" | ||||||
|  |  | ||||||
| CMD [ "/start.sh" ] | CMD [ "/start.sh" ] | ||||||
|  |  | ||||||
| ADD src/docker/start.sh /start.sh | ADD src/docker/start.sh /start.sh | ||||||
| ADD src/script/mxisd /app/mxisd | ADD src/script/ma1sd /app/ma1sd | ||||||
| ADD build/libs/mxisd.jar /app/mxisd.jar | ADD build/libs/ma1sd.jar /app/ma1sd.jar | ||||||
|   | |||||||
							
								
								
									
										80
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										80
									
								
								README.md
									
									
									
									
									
								
							| @@ -1,6 +1,6 @@ | |||||||
| mxisd - Federated Matrix Identity Server | ma1sd - Federated Matrix Identity Server | ||||||
| ---------------------------------------- | ---------------------------------------- | ||||||
|    |    | ||||||
|  |  | ||||||
| - [Overview](#overview) | - [Overview](#overview) | ||||||
| - [Features](#features) | - [Features](#features) | ||||||
| @@ -8,21 +8,30 @@ mxisd - Federated Matrix Identity Server | |||||||
| - [Getting Started](#getting-started) | - [Getting Started](#getting-started) | ||||||
| - [Support](#support) | - [Support](#support) | ||||||
| - [Contribute](#contribute) | - [Contribute](#contribute) | ||||||
| - [Powered by mxisd](#powered-by-mxisd) | - [Powered by ma1sd](#powered-by-ma1sd) | ||||||
| - [FAQ](#faq) | - [FAQ](#faq) | ||||||
|  | - [Migration from mxisd](#migration-from-mxisd) | ||||||
| - [Contact](#contact) | - [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 | # Overview | ||||||
| mxisd is a Federated Matrix Identity server for self-hosted Matrix infrastructures with [enhanced features](#features). | ma1sd is a Federated Matrix Identity server for self-hosted Matrix infrastructures with [enhanced features](#features). | ||||||
| As an enhanced Identity service, it implements the [Matrix Identity service API](https://kamax.io/matrix/api/identity_service/unstable.html) | 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. | 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 | It is the one stop shop for anything regarding Authentication, Directory and Identity management in Matrix built in a | ||||||
| single coherent product. | 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. |  | ||||||
|  |  | ||||||
| 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: | users. 3PIDs can be anything that uniquely and globally identify a user, like: | ||||||
| - Email address | - Email address | ||||||
| - Phone number | - Phone number | ||||||
| @@ -30,18 +39,18 @@ users. 3PIDs can be anything that uniquely and globally identify a user, like: | |||||||
| - Twitter handle | - Twitter handle | ||||||
| - Facebook ID | - Facebook ID | ||||||
|  |  | ||||||
| If you are unfamiliar with the Identity vocabulary and concepts in Matrix, **please read this [introduction](docs/concepts.md)**. | If you are unfamiliar with the Identity vocabulary and concepts in Matrix, **please read this [introduction](docs/concepts.md)**.   | ||||||
|  |  | ||||||
| # Features | # Features | ||||||
| [Identity](docs/features/identity.md): As a [regular Matrix Identity service](https://kamax.io/matrix/api/identity_service/unstable.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 | - Search for people by 3PID using its own Identity stores | ||||||
|   ([Spec](https://kamax.io/matrix/api/identity_service/unstable.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.) | - Invite people to rooms by 3PID using its own Identity stores, with notifications to the invitee (Email, SMS, etc.) | ||||||
|   ([Spec](https://kamax.io/matrix/api/identity_service/unstable.html#post-matrix-identity-api-v1-store-invite)) |   ([Spec](https://matrix.org/docs/spec/identity_service/r0.2.0.html#invitation-storage)) | ||||||
| - Allow users to add 3PIDs to their settings/profile | - Allow users to add/remove 3PIDs to their settings/profile via 3PID sessions | ||||||
|   ([Spec](https://kamax.io/matrix/api/identity_service/unstable.html#establishing-associations)) |   ([Spec](https://matrix.org/docs/spec/identity_service/r0.2.0.html#establishing-associations)) | ||||||
| - Register accounts on your Homeserver with 3PIDs | - Register accounts on your Homeserver with 3PIDs | ||||||
|   ([Spec](https://kamax.io/matrix/api/identity_service/unstable.html#establishing-associations)) |   ([Spec](https://matrix.org/docs/spec/identity_service/r0.2.0.html#establishing-associations)) | ||||||
|  |  | ||||||
| As an enhanced Identity service: | As an enhanced Identity service: | ||||||
| - [Federation](docs/features/federation.md): Use a recursive lookup mechanism when searching and inviting people by 3PID, | - [Federation](docs/features/federation.md): Use a recursive lookup mechanism when searching and inviting people by 3PID, | ||||||
| @@ -52,6 +61,7 @@ As an enhanced Identity service: | |||||||
|   - Central Matrix Identity servers |   - Central Matrix Identity servers | ||||||
| - [Session Control](docs/threepids/session/session.md): Extensive control of where 3PIDs are transmitted so they are not | - [Session Control](docs/threepids/session/session.md): Extensive control of where 3PIDs are transmitted so they are not | ||||||
|   leaked publicly by users |   leaked publicly by users | ||||||
|  | - [Registration control](docs/features/registration.md): Control and restrict user registration based on 3PID patterns or criterias, like a pending invite | ||||||
| - [Authentication](docs/features/authentication.md): Use your Identity stores to perform authentication in [synapse](https://github.com/matrix-org/synapse) | - [Authentication](docs/features/authentication.md): Use your Identity stores to perform authentication in [synapse](https://github.com/matrix-org/synapse) | ||||||
|   via the [REST password provider](https://github.com/kamax-io/matrix-synapse-rest-auth) |   via the [REST password provider](https://github.com/kamax-io/matrix-synapse-rest-auth) | ||||||
| - [Directory search](docs/features/directory.md) which allows you to search for users within your organisation, | - [Directory search](docs/features/directory.md) which allows you to search for users within your organisation, | ||||||
| @@ -67,45 +77,43 @@ As an enhanced Identity service: | |||||||
| - Users can directly find each other using whatever attribute is relevant within your Identity store | - 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 | - 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-ma1sd-really-designed-for) to know if ma1sd is a good fit for you. | ||||||
|  |  | ||||||
| # Getting started | # Getting started | ||||||
| See the [dedicated document](docs/getting-started.md) | See the [dedicated document](docs/getting-started.md) | ||||||
|  |  | ||||||
| # Support | # Support | ||||||
| ## Community | ## Troubleshooting | ||||||
| Over Matrix: [#mxisd:kamax.io](https://matrix.to/#/#mxisd:kamax.io) ([Preview](https://view.matrix.org/room/!NPRUEisLjcaMtHIzDr:kamax.io/)) | A basic troubleshooting guide is available [here](docs/troubleshooting.md). | ||||||
|  |  | ||||||
| For more high-level discussion about the Identity Server architecture/API, go to  [#matrix-identity:kamax.io](https://matrix.to/#/#matrix-identity:kamax.io) | ## Community | ||||||
|  | Over Matrix: [#ma1sd:ru-matrix.org](https://matrix.to/#/#ma1sd:ru-matrix.org) ([Preview](https://view.matrix.org/room/!CxwBdgAlaphCARnKTA:ru-matrix.org/)) | ||||||
|  |  | ||||||
| ## Commercial | ## Commercial | ||||||
| If you would prefer professional support/custom development for mxisd and/or for Matrix in general, including other open | Sorry, I cannot provide commercial support (at least now). But always try to help you. | ||||||
| source technologies/products: |  | ||||||
| - Visit our [website](https://www.kamax.io/) to get in touch with us and get a quote. | Don't hesitate to ask about project and feel free to create issues at https://github.com/ma1uta/ma1sd | ||||||
| - Come in our general Matrix room: [#kamax-matrix:kamax.io](https://matrix.to/#/#kamax-matrix:kamax.io) |  | ||||||
|  |  | ||||||
| # Contribute  | # Contribute  | ||||||
| You can contribute as a community member by: | 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! | - 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. mxisd should feel natural, let us know if it does not! | - 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 | - 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. | changes you feel improve the doc. | ||||||
| - Contribute code directly: we love contributors! All your contributions will be licensed under AGPLv3. | - 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: | # Powered by ma1sd | ||||||
| - Get a [support contract](#commercial). This is the best way you can help us as it ensures mxisd is | The following projects can use ma1sd under the hood for some or all their features. Check them out! | ||||||
| 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! |  | ||||||
| - [matrix-docker-ansible-deploy](https://github.com/spantaleev/matrix-docker-ansible-deploy) | - [matrix-docker-ansible-deploy](https://github.com/spantaleev/matrix-docker-ansible-deploy) | ||||||
| - [matrix-register-bot](https://github.com/krombel/matrix-register-bot) | - [matrix-register-bot](https://github.com/krombel/matrix-register-bot) | ||||||
|  |  | ||||||
| # FAQ | # FAQ | ||||||
| See the [dedicated document](docs/faq.md) | See the [dedicated document](docs/faq.md) | ||||||
|  |  | ||||||
|  | # Migration from mxisd | ||||||
|  |  | ||||||
|  | See the [migration guide](docs/migration-from-mxisd.md) | ||||||
|  |  | ||||||
| # Contact | # Contact | ||||||
| Get in touch via: | Get in touch via: | ||||||
| - Matrix: [#mxisd:kamax.io](https://matrix.to/#/#mxisd:kamax.io) | - Matrix: [#ma1sd:ru-matrix.org](https://matrix.to/#/#ma1sd:ru-matrix.org) | ||||||
| - Email: see our website: [Kamax.io](https://www.kamax.io) |  | ||||||
|   | |||||||
							
								
								
									
										105
									
								
								build.gradle
									
									
									
									
									
								
							
							
						
						
									
										105
									
								
								build.gradle
									
									
									
									
									
								
							| @@ -1,5 +1,5 @@ | |||||||
| /* | /* | ||||||
|  * mxisd - Matrix Identity Server Daemon |  * ma1sd - Matrix Identity Server Daemon | ||||||
|  * Copyright (C) 2017 Kamax Sarl |  * Copyright (C) 2017 Kamax Sarl | ||||||
|  * |  * | ||||||
|  * https://www.kamax.io/ |  * https://www.kamax.io/ | ||||||
| @@ -24,17 +24,18 @@ apply plugin: 'java' | |||||||
| apply plugin: 'application' | apply plugin: 'application' | ||||||
| apply plugin: 'com.github.johnrengelman.shadow' | apply plugin: 'com.github.johnrengelman.shadow' | ||||||
| apply plugin: 'idea' | apply plugin: 'idea' | ||||||
|  | apply plugin: 'com.github.ben-manes.versions' | ||||||
|  |  | ||||||
| def confFileName = "mxisd.example.yaml" | def confFileName = "ma1sd.example.yaml" | ||||||
| def distDir = "${project.buildDir}/dist" | def distDir = "${project.buildDir}/dist" | ||||||
|  |  | ||||||
| def debBinPath = "/usr/lib/mxisd" | def debBinPath = "/usr/lib/ma1sd" | ||||||
| def debConfPath = "/etc/mxisd" | def debConfPath = "/etc/ma1sd" | ||||||
| def debDataPath = "/var/lib/mxisd" | def debDataPath = "/var/lib/ma1sd" | ||||||
| def debSystemdPath = "/etc/systemd/system" | def debSystemdPath = "/etc/systemd/system" | ||||||
|  |  | ||||||
| def debConfFileName = confFileName | def debConfFileName = confFileName | ||||||
| def debStartScriptFilename = "mxisd" | def debStartScriptFilename = "ma1sd" | ||||||
|  |  | ||||||
| def debBuildBasePath = "${project.buildDir}/tmp/debian" | def debBuildBasePath = "${project.buildDir}/tmp/debian" | ||||||
| def debBuildDebianPath = "${debBuildBasePath}/DEBIAN" | def debBuildDebianPath = "${debBuildBasePath}/DEBIAN" | ||||||
| @@ -43,16 +44,18 @@ def debBuildConfPath = "${debBuildBasePath}${debConfPath}" | |||||||
| def debBuildDataPath = "${debBuildBasePath}${debDataPath}" | def debBuildDataPath = "${debBuildBasePath}${debDataPath}" | ||||||
| def debBuildSystemdPath = "${debBuildBasePath}${debSystemdPath}" | def debBuildSystemdPath = "${debBuildBasePath}${debSystemdPath}" | ||||||
|  |  | ||||||
| def dockerImageName = "kamax/mxisd" | def dockerImageName = "ma1uta/ma1sd" | ||||||
| def dockerImageTag = "${dockerImageName}:${mxisdVersion()}" | def dockerImageTag = "${dockerImageName}:${ma1sdVersion()}" | ||||||
|  |  | ||||||
| group = 'io.kamax' | group = 'io.kamax' | ||||||
| mainClassName = 'io.kamax.mxisd.MxisdStandaloneExec' | mainClassName = 'io.kamax.mxisd.MxisdStandaloneExec' | ||||||
|  | sourceCompatibility = '1.8' | ||||||
|  | targetCompatibility = '1.8' | ||||||
|  |  | ||||||
| String mxisdVersion() { | String ma1sdVersion() { | ||||||
|     def versionPattern = Pattern.compile("v(\\d+\\.)?(\\d+\\.)?(\\d+)(-.*)?") |     def versionPattern = Pattern.compile("v(\\d+\\.)?(\\d+\\.)?(\\d+)(-.*)?") | ||||||
|  |  | ||||||
|     String version = System.getenv('MXISD_BUILD_VERSION') |     String version = System.getenv('MA1SD_BUILD_VERSION') | ||||||
|     if (version == null || version.size() == 0) { |     if (version == null || version.size() == 0) { | ||||||
|         version = gitVersion() |         version = gitVersion() | ||||||
|     } |     } | ||||||
| @@ -74,46 +77,47 @@ buildscript { | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     dependencies { |     dependencies { | ||||||
|         classpath 'com.github.jengelman.gradle.plugins:shadow:4.0.3' |         classpath 'com.github.jengelman.gradle.plugins:shadow:5.1.0' | ||||||
|  |         classpath 'com.github.ben-manes:gradle-versions-plugin:0.27.0' | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
| repositories { | repositories { | ||||||
|     jcenter() |     jcenter() | ||||||
|     maven { url "https://kamax.io/maven/releases/" } |  | ||||||
|     maven { url "https://kamax.io/maven/snapshots/" } |  | ||||||
| } | } | ||||||
|  |  | ||||||
| dependencies { | dependencies { | ||||||
|     // Logging |     // Logging | ||||||
|     compile 'org.slf4j:slf4j-simple:1.7.25' |     compile 'org.slf4j:slf4j-simple:1.7.25' | ||||||
|      |  | ||||||
|     // Easy file management |  | ||||||
|     compile 'commons-io:commons-io:2.5' |  | ||||||
|      |  | ||||||
|     // Config management |  | ||||||
|     compile 'org.yaml:snakeyaml:1.23' |  | ||||||
|  |  | ||||||
|     // Matrix Java SDK |     // Easy file management | ||||||
|     compile 'io.kamax:matrix-java-sdk:0.0.14-8-g0e57ec6' |     compile 'commons-io:commons-io:2.6' | ||||||
|  |  | ||||||
|  |     // Config management | ||||||
|  |     compile 'org.yaml:snakeyaml:1.25' | ||||||
|  |  | ||||||
|  |     // Dependencies from old Matrix-java-sdk | ||||||
|  |     compile 'org.apache.commons:commons-lang3:3.9' | ||||||
|  |     compile 'com.squareup.okhttp3:okhttp:4.2.2' | ||||||
|  |     compile 'commons-codec:commons-codec:1.13' | ||||||
|  |  | ||||||
|     // ORMLite |     // ORMLite | ||||||
|     compile 'com.j256.ormlite:ormlite-jdbc:5.0' |     compile 'com.j256.ormlite:ormlite-jdbc:5.1' | ||||||
|  |  | ||||||
|     // ed25519 handling |     // ed25519 handling | ||||||
|     compile 'net.i2p.crypto:eddsa:0.1.0' |     compile 'net.i2p.crypto:eddsa:0.3.0' | ||||||
|  |  | ||||||
|     // LDAP connector |     // LDAP connector | ||||||
|     compile 'org.apache.directory.api:api-all:1.0.0' |     compile 'org.apache.directory.api:api-all:1.0.0' | ||||||
|  |  | ||||||
|     // DNS lookups |     // DNS lookups | ||||||
|     compile 'dnsjava:dnsjava:2.1.8' |     compile 'dnsjava:dnsjava:2.1.9' | ||||||
|  |  | ||||||
|     // HTTP connections |     // HTTP connections | ||||||
|     compile 'org.apache.httpcomponents:httpclient:4.5.3' |     compile 'org.apache.httpcomponents:httpclient:4.5.10' | ||||||
|  |  | ||||||
|     // Phone numbers validation |     // Phone numbers validation | ||||||
|     compile 'com.googlecode.libphonenumber:libphonenumber:8.7.1' |     compile 'com.googlecode.libphonenumber:libphonenumber:8.10.22' | ||||||
|  |  | ||||||
|     // E-mail sending |     // E-mail sending | ||||||
|     compile 'javax.mail:javax.mail-api:1.6.2' |     compile 'javax.mail:javax.mail-api:1.6.2' | ||||||
| @@ -123,33 +127,44 @@ dependencies { | |||||||
|     compile 'com.google.firebase:firebase-admin:5.3.0' |     compile 'com.google.firebase:firebase-admin:5.3.0' | ||||||
|  |  | ||||||
|     // Connection Pool |     // Connection Pool | ||||||
|     compile 'com.mchange:c3p0:0.9.5.2' |     compile 'com.mchange:c3p0:0.9.5.4' | ||||||
|  |  | ||||||
|     // SQLite |     // SQLite | ||||||
|     compile 'org.xerial:sqlite-jdbc:3.20.0' |     compile 'org.xerial:sqlite-jdbc:3.28.0' | ||||||
|  |  | ||||||
|     // PostgreSQL |     // PostgreSQL | ||||||
|     compile 'org.postgresql:postgresql:42.2.5' |     compile 'org.postgresql:postgresql:42.2.8' | ||||||
|  |  | ||||||
|     // MariaDB/MySQL |     // MariaDB/MySQL | ||||||
|     compile 'org.mariadb.jdbc:mariadb-java-client:2.1.2' |     compile 'org.mariadb.jdbc:mariadb-java-client:2.5.1' | ||||||
|  |  | ||||||
|     // Twilio SDK for SMS |     // Twilio SDK for SMS | ||||||
|     compile 'com.twilio.sdk:twilio:7.14.5' |     compile 'com.twilio.sdk:twilio:7.45.0' | ||||||
|  |  | ||||||
|     // SendGrid SDK to send emails from GCE |     // SendGrid SDK to send emails from GCE | ||||||
|     compile 'com.sendgrid:sendgrid-java:2.2.2' |     compile 'com.sendgrid:sendgrid-java:2.2.2' | ||||||
|  |  | ||||||
|     // ZT-Exec for exec identity store |     // ZT-Exec for exec identity store | ||||||
|     compile 'org.zeroturnaround:zt-exec:1.10' |     compile 'org.zeroturnaround:zt-exec:1.11' | ||||||
|  |  | ||||||
|     // HTTP server |     // HTTP server | ||||||
|     compile 'io.undertow:undertow-core:2.0.16.Final' |     compile 'io.undertow:undertow-core:2.0.27.Final' | ||||||
|  |  | ||||||
|     testCompile 'junit:junit:4.12' |     // Command parser for AS interface | ||||||
|     testCompile 'com.github.tomakehurst:wiremock:2.8.0' |     implementation 'commons-cli:commons-cli:1.4' | ||||||
|     testCompile 'com.unboundid:unboundid-ldapsdk:4.0.9' |  | ||||||
|     testCompile 'com.icegreen:greenmail:1.5.9' |     testCompile 'junit:junit:4.13-rc-1' | ||||||
|  |     testCompile 'com.github.tomakehurst:wiremock:2.25.1' | ||||||
|  |     testCompile 'com.unboundid:unboundid-ldapsdk:4.0.12' | ||||||
|  |     testCompile 'com.icegreen:greenmail:1.5.11' | ||||||
|  | } | ||||||
|  |  | ||||||
|  | jar { | ||||||
|  |     manifest { | ||||||
|  |         attributes( | ||||||
|  |                 'Implementation-Version': ma1sdVersion() | ||||||
|  |         ) | ||||||
|  |     } | ||||||
| } | } | ||||||
|  |  | ||||||
| shadowJar { | shadowJar { | ||||||
| @@ -160,7 +175,7 @@ shadowJar { | |||||||
|  |  | ||||||
| task debBuild(dependsOn: shadowJar) { | task debBuild(dependsOn: shadowJar) { | ||||||
|     doLast { |     doLast { | ||||||
|         String debVersion = mxisdVersion() |         String debVersion = ma1sdVersion() | ||||||
|         println "Version for package: ${debVersion}" |         println "Version for package: ${debVersion}" | ||||||
|         mkdir distDir |         mkdir distDir | ||||||
|         mkdir debBuildBasePath |         mkdir debBuildBasePath | ||||||
| @@ -171,7 +186,7 @@ task debBuild(dependsOn: shadowJar) { | |||||||
|         mkdir debBuildSystemdPath |         mkdir debBuildSystemdPath | ||||||
|  |  | ||||||
|         copy { |         copy { | ||||||
|             from "${project.buildDir}/libs/mxisd.jar" |             from "${project.buildDir}/libs/ma1sd.jar" | ||||||
|             into debBuildBinPath |             into debBuildBinPath | ||||||
|         } |         } | ||||||
|  |  | ||||||
| @@ -190,13 +205,13 @@ task debBuild(dependsOn: shadowJar) { | |||||||
|         ant.replaceregexp( // FIXME adapt to new config format |         ant.replaceregexp( // FIXME adapt to new config format | ||||||
|                 file: "${debBuildConfPath}/${debConfFileName}", |                 file: "${debBuildConfPath}/${debConfFileName}", | ||||||
|                 match: "key:\\R  path:(.*)", |                 match: "key:\\R  path:(.*)", | ||||||
|                 replace: "key:\n  path: '${debDataPath}/signing.key'" |                 replace: "key:\n  path: '${debDataPath}/keys'" | ||||||
|         ) |         ) | ||||||
|  |  | ||||||
|         ant.replaceregexp( // FIXME adapt to new config format |         ant.replaceregexp( // FIXME adapt to new config format | ||||||
|                 file: "${debBuildConfPath}/${debConfFileName}", |                 file: "${debBuildConfPath}/${debConfFileName}", | ||||||
|                 match: "storage:\\R  provider:\\R    sqlite:\\R      database:(.*)", |                 match: "storage:\\R  provider:\\R    sqlite:\\R      database:(.*)", | ||||||
|                 replace: "storage:\n  provider:\n    sqlite:\n      database: '${debDataPath}/mxisd.db'" |                 replace: "storage:\n  provider:\n    sqlite:\n      database: '${debDataPath}/store.db'" | ||||||
|         ) |         ) | ||||||
|  |  | ||||||
|         copy { |         copy { | ||||||
| @@ -216,6 +231,12 @@ task debBuild(dependsOn: shadowJar) { | |||||||
|                 value: debDataPath |                 value: debDataPath | ||||||
|         ) |         ) | ||||||
|  |  | ||||||
|  |         ant.replace( | ||||||
|  |                 file: "${debBuildDebianPath}/postinst", | ||||||
|  |                 token: '%DEB_CONF_FILE%', | ||||||
|  |                 value: "${debConfPath}/ma1sd.yaml" | ||||||
|  |         ) | ||||||
|  |  | ||||||
|         ant.chmod( |         ant.chmod( | ||||||
|                 file: "${debBuildDebianPath}/postinst", |                 file: "${debBuildDebianPath}/postinst", | ||||||
|                 perm: 'a+x' |                 perm: 'a+x' | ||||||
| @@ -227,7 +248,7 @@ task debBuild(dependsOn: shadowJar) { | |||||||
|         ) |         ) | ||||||
|  |  | ||||||
|         copy { |         copy { | ||||||
|             from "${project.file('src/systemd/mxisd.service')}" |             from "${project.file('src/systemd/ma1sd.service')}" | ||||||
|             into debBuildSystemdPath |             into debBuildSystemdPath | ||||||
|         } |         } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -16,7 +16,7 @@ TCP 443 | |||||||
|           +<---------------------------------<+ |           +<---------------------------------<+ | ||||||
|           | |           | | ||||||
|           |   +-------------------+ |           |   +-------------------+ | ||||||
|  TCP 8090 +-> | mxisd             | |  TCP 8090 +-> | ma1sd             | | ||||||
|               |                   | |               |                   | | ||||||
|               | - Profile's 3PIDs | |               | - Profile's 3PIDs | | ||||||
|               | - 3PID Invites    | |               | - 3PID Invites    | | ||||||
| @@ -25,7 +25,7 @@ TCP 443 | |||||||
|              TCP 443 |              TCP 443 | ||||||
|                 |  +------------------------+ |                 |  +------------------------+ | ||||||
|                 |  | Remote Federated       | |                 |  | Remote Federated       | | ||||||
|                 |  | mxisd servers          | |                 |  | ma1sd servers          | | ||||||
|                 |  |                        | |                 |  |                        | | ||||||
|                 +--> - 3PID Invites         | |                 +--> - 3PID Invites         | | ||||||
|                    +------------------------+ |                    +------------------------+ | ||||||
|   | |||||||
| @@ -12,17 +12,17 @@ | |||||||
|  |  | ||||||
| ### Build | ### Build | ||||||
| ```bash | ```bash | ||||||
| git clone https://github.com/kamax-matrix/mxisd.git | git clone https://github.com/ma1uta/ma1sd.git | ||||||
| cd mxisd | cd ma1sd | ||||||
| ./gradlew build | ./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 `ma1sd.example.yaml` to `ma1sd.yaml` and edit to your needs.   | ||||||
| For advanced configuration, see the [Configure section](configure.md). | For advanced configuration, see the [Configure section](configure.md). | ||||||
|  |  | ||||||
| Start the server in foreground to validate the build and configuration: | Start the server in foreground to validate the build and configuration: | ||||||
| ```bash | ```bash | ||||||
| java -jar build/libs/mxisd.jar | java -jar build/libs/ma1sd.jar | ||||||
| ``` | ``` | ||||||
|  |  | ||||||
| Ensure the signing key is available: | Ensure the signing key is available: | ||||||
| @@ -34,9 +34,9 @@ $ curl 'http://localhost:8090/_matrix/identity/api/v1/pubkey/ed25519:0' | |||||||
|  |  | ||||||
| Test basic recursive lookup (requires Internet connection with access to TCP 443): | Test basic recursive lookup (requires Internet connection with access to TCP 443): | ||||||
| ```bash | ```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 | If you enabled LDAP, you can also validate your config with a similar request after replacing the `address` value with | ||||||
| @@ -56,7 +56,7 @@ Requirements: | |||||||
| - fakeroot | - fakeroot | ||||||
| - dpkg-deb | - dpkg-deb | ||||||
|  |  | ||||||
| [Build mxisd](#build) then: | [Build ma1sd](#build) then: | ||||||
| ```bash | ```bash | ||||||
| ./gradlew debBuild | ./gradlew debBuild | ||||||
| ``` | ``` | ||||||
| @@ -64,7 +64,7 @@ You will find the debian package in `build/dist`. | |||||||
| Then follow the instruction in the [Debian package](install/debian.md) document. | Then follow the instruction in the [Debian package](install/debian.md) document. | ||||||
|  |  | ||||||
| ## Docker image | ## Docker image | ||||||
| [Build mxisd](#build) then: | [Build ma1sd](#build) then: | ||||||
| ```bash | ```bash | ||||||
| ./gradlew dockerBuild | ./gradlew dockerBuild | ||||||
| ``` | ``` | ||||||
|   | |||||||
| @@ -1,6 +1,6 @@ | |||||||
| # Concepts | # Concepts | ||||||
| - [Matrix](#matrix) | - [Matrix](#matrix) | ||||||
| - [mxisd](#mxisd) | - [ma1sd](#ma1sd) | ||||||
|  |  | ||||||
| ## Matrix | ## Matrix | ||||||
| The following concepts are part of the Matrix ecosystem and specification. | 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.) | - Medium, which describes what network it belongs to (Email, Phone, Twitter, Discord, etc.) | ||||||
| - Address, the actual value people typically use on a daily basis. | - 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 | ### Homeserver | ||||||
| Where a user **account and data** are stored. | Where a user **account and data** are stored. | ||||||
| @@ -34,10 +34,10 @@ An Identity server: | |||||||
| ### 3PID session | ### 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. | The fact to validate a 3PID (email, phone number, etc.) via the introduction of a token which was sent to the 3PID address. | ||||||
|  |  | ||||||
| ## mxisd | ## ma1sd | ||||||
| The following concepts are specific to mxisd. | The following concepts are specific to ma1sd. | ||||||
|  |  | ||||||
| ### Identity store | ### Identity store | ||||||
| Where your user accounts and 3PID mappings are stored. | 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. | ||||||
|   | |||||||
| @@ -41,10 +41,18 @@ matrix: | |||||||
| Create a list under the label `myOtherServers` containing two Identity servers: `https://other1.example.org` and `https://other2.example.org`. | Create a list under the label `myOtherServers` containing two Identity servers: `https://other1.example.org` and `https://other2.example.org`. | ||||||
|  |  | ||||||
| ## Server | ## 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.port`: HTTP port to listen on (unencrypted) | ||||||
| - `server.publicUrl`: Defaults to `https://{server.name}` | - `server.publicUrl`: Defaults to `https://{server.name}` | ||||||
|  |  | ||||||
|  | ## Unbind (MSC1915) | ||||||
|  | - `session.policy.unbind.enabled`: Enable or disable unbind functionality (MSC1915). (Defaults to true). | ||||||
|  |  | ||||||
|  | *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 | ## Storage | ||||||
| ### SQLite | ### SQLite | ||||||
| `storage.provider.sqlite.database`: Absolute location of the SQLite database | `storage.provider.sqlite.database`: Absolute location of the SQLite database | ||||||
| @@ -68,7 +76,7 @@ notification: | |||||||
|     msisdn: 'raw' |     msisdn: 'raw' | ||||||
| ``` | ``` | ||||||
| - Emails notifications would use the `sendgrid` handler, which define its own configuration under `notification.handlers.sendgrid` | - 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 | ### Handlers | ||||||
| - `notification.handers.<handler ID>`: Handler-specific configuration for the given handler ID. Repeatable. | - `notification.handers.<handler ID>`: Handler-specific configuration for the given handler ID. Repeatable. | ||||||
|   | |||||||
							
								
								
									
										60
									
								
								docs/faq.md
									
									
									
									
									
								
							
							
						
						
									
										60
									
								
								docs/faq.md
									
									
									
									
									
								
							| @@ -10,23 +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. | - [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. | - [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. | 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. | started and answer questions you might have. | ||||||
|  |  | ||||||
| ### Do I need to use mxisd if I run a Homeserver? | ### 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 ma1sd for.  | ||||||
|  |  | ||||||
|  | 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 ma1sd if I run a Homeserver? | ||||||
| No, but it is strongly recommended, even if you don't use any Identity store or integration. | 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 | 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. | least the same information as if you were not running it. | ||||||
|  |  | ||||||
| It will also give your users a choice to make their 3PIDs available publicly, ensuring they are made aware of the | So ma1sd is like your gatekeeper and guardian angel. It does not change what you already know, just adds some nice | ||||||
| privacy consequences, which is not the case with the central Matrix.org servers. |  | ||||||
|  |  | ||||||
| So mxisd 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. | simple features on top of it. | ||||||
|  |  | ||||||
| ### I'm not sure I understand what an "Identity server" is supposed to be or do... | ### I'm not sure I understand what an "Identity server" is supposed to be or do... | ||||||
| @@ -35,27 +44,28 @@ 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". | 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 | 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. | 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. | No. | ||||||
|  |  | ||||||
| Accounts cannot currently migrate/move from one server to another.   | 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? | ### 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) is not longer maintained and | The [synapse LDAP3 auth provider](https://github.com/matrix-org/matrix-synapse-ldap3) is not longer maintained despite | ||||||
| only handles on specific flow: validate credentials at login. | saying so and only handles on specific flow: validate credentials at login. | ||||||
|  |  | ||||||
| It does not: | It does not: | ||||||
| - Auto-provision user profiles | - Auto-provision user profiles | ||||||
| - Integrate with Identity management | - Integrate with Identity management | ||||||
| - Integrate with Directory searches | - 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. | does not. | ||||||
|  |  | ||||||
| ### Sydent is the official Identity server implementation of the Matrix team. Why not use that? | ### Sydent is the official Identity server implementation of the Matrix team. Why not use that? | ||||||
| @@ -66,22 +76,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 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 | - 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. | 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. | data and those of people you might know. | ||||||
|  |  | ||||||
| mxisd [can be configured](features/identity.md#lookups) to talk to the central Identity servers if you wish. | [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! | ### So ma1sd 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.   | 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, mxisd will follow, remaining 100% compatible with the ecosystem. | 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. | No. | ||||||
|  |  | ||||||
| It is possible, but it is not supported and the scope of features will be extremely limited. | 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. | ||||||
|   | |||||||
| @@ -3,7 +3,7 @@ | |||||||
| - [Basic](#basic) | - [Basic](#basic) | ||||||
|   - [Overview](#overview) |   - [Overview](#overview) | ||||||
|   - [synapse](#synapse) |   - [synapse](#synapse) | ||||||
|   - [mxisd](#mxisd) |   - [ma1sd](#ma1sd) | ||||||
|   - [Validate](#validate) |   - [Validate](#validate) | ||||||
|   - [Next steps](#next-steps) |   - [Next steps](#next-steps) | ||||||
|     - [Profile auto-fil](#profile-auto-fill) |     - [Profile auto-fil](#profile-auto-fill) | ||||||
| @@ -16,15 +16,15 @@ | |||||||
|     - [DNS Overwrite](#dns-overwrite) |     - [DNS Overwrite](#dns-overwrite) | ||||||
|  |  | ||||||
| ## Description | ## Description | ||||||
| Authentication is an enhanced feature of mxisd to ensure coherent and centralized identity management.   | Authentication is an enhanced feature of ma1sd to ensure coherent and centralized identity management.   | ||||||
| It allows to use Identity stores configured in mxisd to authenticate users on your Homeserver. | It allows to use Identity stores configured in ma1sd to authenticate users on your Homeserver. | ||||||
|  |  | ||||||
| Authentication is divided into two parts: | Authentication is divided into two parts: | ||||||
| - [Basic](#basic): authenticate with a regular username. | - [Basic](#basic): authenticate with a regular username. | ||||||
| - [Advanced](#advanced): same as basic with extra ability to authenticate using a 3PID. | - [Advanced](#advanced): same as basic with extra abilities like authenticate using a 3PID or do username rewrite. | ||||||
|  |  | ||||||
| ## Basic | ## 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. | known as password provider. | ||||||
|  |  | ||||||
| ### Overview | ### Overview | ||||||
| @@ -33,7 +33,7 @@ An overview of the Basic Authentication process: | |||||||
|                                                                                     Identity stores |                                                                                     Identity stores | ||||||
|  Client                                                                             +------+ |  Client                                                                             +------+ | ||||||
|    |                                            +-------------------------+    +--> | LDAP | |    |                                            +-------------------------+    +--> | LDAP | | ||||||
|    |   +---------------+  /_matrix/identity     | mxisd                   |    |    +------+ |    |   +---------------+  /_matrix/identity     | ma1sd                   |    |    +------+ | ||||||
|    +-> | Reverse proxy | >------------------+   |                         |    | |    +-> | Reverse proxy | >------------------+   |                         |    | | ||||||
|        +--|------------+                    |   |                         |    |    +--------+ |        +--|------------+                    |   |                         |    |    +--------+ | ||||||
|           |                                 +-----> Check ID stores     >------+--> | SQL DB | |           |                                 +-----> 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) |               |   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 | ### 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: | - Edit your **synapse** configuration: | ||||||
|   - As described by the auth module documentation |   - As described by the auth module documentation | ||||||
|   - Set `endpoint` to `http://mxisdAddress:8090` - Replace `mxisdAddress` by an IP/host name that provides a direct |   - Set `endpoint` to `http://ma1sdAddress:8090` - Replace `ma1sdAddress` by an IP/host name that provides a direct | ||||||
|   connection to mxisd.   |   connection to ma1sd.   | ||||||
|   This **MUST NOT** be a public address, and SHOULD NOT go through a reverse proxy. |   This **MUST NOT** be a public address, and SHOULD NOT go through a reverse proxy. | ||||||
| - Restart synapse | - Restart synapse | ||||||
|  |  | ||||||
| ### mxisd | ### ma1sd | ||||||
| - Configure and enable at least one [Identity store](../stores/README.md) | - Configure and enable at least one [Identity store](../stores/README.md) | ||||||
| - Restart mxisd | - Restart ma1sd | ||||||
|  |  | ||||||
| ### Validate | ### Validate | ||||||
| Login on the Homeserver using credentials present in one of your Identity stores. | 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 |             |                            |     Step 1    +---------------------------+     Step 2 | ||||||
|             |                            |               |                           | |             |                            |               |                           | | ||||||
| Client+---->| /_matrix/client/r0/login +---------------->|                           | Look up address  +---------+ | Client+---->| /_matrix/client/r0/login +---------------->|                           | Look up address  +---------+ | ||||||
|             |                      ^     |               |  mxisd - Identity server  +----------------->| Backend | |             |                      ^     |               |  ma1sd - Identity server  +----------------->| Backend | | ||||||
|             |                      |     |               |                           |                  +---------+ |             |                      |     |               |                           |                  +---------+ | ||||||
|             | /_matrix/* +--+      +---------------------+                           | |             | /_matrix/* +--+      +---------------------+                           | | ||||||
|             |               |            |               +---------------+-----------+ |             |               |            |               +---------------+-----------+ | ||||||
| @@ -110,7 +110,7 @@ Client+---->| /_matrix/client/r0/login +---------------->| | |||||||
| ``` | ``` | ||||||
|  |  | ||||||
| Steps of user authentication using a 3PID: | 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. | 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. | 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. |    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 | ```apache | ||||||
| ProxyPass /_matrix/client/r0/login http://localhost:8090/_matrix/client/r0/login | 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: | Your VirtualHost should now look similar to: | ||||||
| ```apache | ```apache | ||||||
| @@ -145,11 +145,53 @@ Your VirtualHost should now look similar to: | |||||||
| </VirtualHost> | </VirtualHost> | ||||||
| ``` | ``` | ||||||
|  |  | ||||||
|  | ##### nginx | ||||||
|  |  | ||||||
|  | The specific configuration to add under the relevant `server`: | ||||||
|  |  | ||||||
|  | ```nginx | ||||||
|  | location /_matrix/client/r0/login { | ||||||
|  |     proxy_pass http://localhost:8090; | ||||||
|  |     proxy_set_header Host $host; | ||||||
|  |     proxy_set_header X-Forwarded-For $remote_addr; | ||||||
|  | } | ||||||
|  | ``` | ||||||
|  |  | ||||||
|  | Your `server` section should now look similar to: | ||||||
|  |  | ||||||
|  | ```nginx | ||||||
|  | server { | ||||||
|  |     listen 443 ssl; | ||||||
|  |     server_name matrix.example.org; | ||||||
|  |      | ||||||
|  |     # ... | ||||||
|  |      | ||||||
|  |     location /_matrix/client/r0/login { | ||||||
|  |         proxy_pass http://localhost:8090; | ||||||
|  |         proxy_set_header Host $host; | ||||||
|  |         proxy_set_header X-Forwarded-For $remote_addr; | ||||||
|  |     } | ||||||
|  |      | ||||||
|  |     location /_matrix/identity { | ||||||
|  |         proxy_pass http://localhost:8090/_matrix/identity; | ||||||
|  |         proxy_set_header Host $host; | ||||||
|  |         proxy_set_header X-Forwarded-For $remote_addr; | ||||||
|  |     } | ||||||
|  |      | ||||||
|  |     location /_matrix { | ||||||
|  |         proxy_pass http://localhost:8008/_matrix; | ||||||
|  |         proxy_set_header Host $host; | ||||||
|  |         proxy_set_header X-Forwarded-For $remote_addr; | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | ``` | ||||||
|  |  | ||||||
| #### DNS Overwrite | #### 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. | 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 | ```yaml | ||||||
| dns: | dns: | ||||||
|   overwrite: |   overwrite: | ||||||
| @@ -165,8 +207,14 @@ In case the hostname is the same as your Matrix domain and `server.name` is not | |||||||
|  |  | ||||||
| `value` is the base internal URL of the Homeserver, without any `/_matrix/..` or trailing `/`. | `value` is the base internal URL of the Homeserver, without any `/_matrix/..` or trailing `/`. | ||||||
|  |  | ||||||
|  | ### Optional features | ||||||
|  |  | ||||||
|  | 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 | #### Username rewrite | ||||||
| In mxisd config: | In ma1sd config: | ||||||
| ```yaml | ```yaml | ||||||
| auth: | auth: | ||||||
|   rewrite: |   rewrite: | ||||||
|   | |||||||
| @@ -1,11 +1,11 @@ | |||||||
| # Bridge Integration | # 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. | 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. | 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.   | **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. | of working configuration. | ||||||
|  |  | ||||||
| ## Configuration | ## Configuration | ||||||
|   | |||||||
| @@ -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 | - 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) | internally, so users can just find themselves **prior** to having any common room(s) | ||||||
| - Add extra attributes of your backend to extend the search | - 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 | ## Overview | ||||||
| This is performed by intercepting the Homeserver endpoint `/_matrix/client/r0/user_directory/search` like so: | 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 | Client --> | Reverse proxy                                                                         Step 2 | ||||||
|            |                                              Step 1    +-------------------------+ |            |                                              Step 1    +-------------------------+ | ||||||
|            |   /_matrix/client/r0/user_directory/search ----------> |                         |  Search in   +---------+ |            |   /_matrix/client/r0/user_directory/search ----------> |                         |  Search in   +---------+ | ||||||
|            |                        /\                              | mxisd - Identity server | -----------> | Backend | |            |                        /\                              | ma1sd - Identity server | -----------> | Backend | | ||||||
|            |   /_matrix/*            \----------------------------- |                         |  all users   +---------+ |            |   /_matrix/*            \----------------------------- |                         |  all users   +---------+ | ||||||
|            |        |            Step 4: Send back merged results   +-------------------------+ |            |        |            Step 4: Send back merged results   +-------------------------+ | ||||||
|            +        |                                                            | |            +        |                                                            | | ||||||
| @@ -44,7 +44,7 @@ Client --> | Reverse proxy | |||||||
|                          +------------+   /_matrix/client/r0/user_directory/search |                          +------------+   /_matrix/client/r0/user_directory/search | ||||||
| ``` | ``` | ||||||
| Steps: | 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. | 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. | 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. |    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. | which directly answered the request. | ||||||
|  |  | ||||||
| ## Requirements | ## 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 | - At least one compatible [Identity store](../stores/README.md) enabled | ||||||
|    |    | ||||||
| ## Configuration | ## Configuration | ||||||
| @@ -62,7 +62,7 @@ The specific configuration to put under the relevant `VirtualHost`: | |||||||
| ```apache | ```apache | ||||||
| ProxyPass /_matrix/client/r0/user_directory/ http://0.0.0.0:8090/_matrix/client/r0/user_directory/ | 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. | results. | ||||||
|  |  | ||||||
| Your `VirtualHost` should now look like this: | Your `VirtualHost` should now look like this: | ||||||
| @@ -118,7 +118,7 @@ server { | |||||||
| ``` | ``` | ||||||
|  |  | ||||||
| ### DNS Overwrite | ### 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. | 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: | To do so, use the following configuration: | ||||||
| @@ -136,7 +136,7 @@ dns: | |||||||
| ## Next steps | ## Next steps | ||||||
| ### Homeserver results | ### Homeserver results | ||||||
| You can configure if the Homeserver should be queried at all when doing a directory search.   | 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 | ```yaml | ||||||
| directory: | directory: | ||||||
|   exclude: |   exclude: | ||||||
|   | |||||||
| @@ -1,72 +1,122 @@ | |||||||
| # Integration as an Application Service | # Application Service | ||||||
| **WARNING:** These features are currently highly experimental. They can be removed or modified without notice.   | **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. | All the features requires a Homeserver capable of connecting [Application Services](https://matrix.org/docs/spec/application_service/r0.1.1.html). | ||||||
|  |  | ||||||
| ## Email notification for Room invites by Matrix ID | The following capabilities are provided in this feature: | ||||||
|  | - [Admin commands](#admin-commands) | ||||||
|  | - [Email Notification about room invites by Matrix IDs](#email-notification-about-room-invites-by-matrix-ids) | ||||||
|  | - [Auto-reject of expired 3PID invites](#auto-reject-of-expired-3pid-invites) | ||||||
|  |  | ||||||
|  | ## Setup | ||||||
|  | > **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 ma1sd configuration to allow integration. | ||||||
|  | 2. Integrate with the homeserver. | ||||||
|  | 3. Configure the specific capabilities, if applicable. | ||||||
|  |  | ||||||
|  | ### Configuration | ||||||
|  | #### Variables | ||||||
|  | Under the `appsvc` namespace: | ||||||
|  |  | ||||||
|  | | Key                   | Type    | Required | Default | Purpose                                                        | | ||||||
|  | |-----------------------|---------|----------|---------|----------------------------------------------------------------| | ||||||
|  | | `enabled`             | boolean | No       | `false` | Globally enable/disable the feature                            | | ||||||
|  | | `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 ma1sd from the Homeserver                          | | ||||||
|  | | `endpoint.toAS.token` | string  | Yes      | *None*  | Token for the Homeserver to use when sending requests to ma1sd | | ||||||
|  |  | ||||||
|  | #### Example | ||||||
|  | ```yaml | ||||||
|  | appsvc: | ||||||
|  |   enabled: true | ||||||
|  |   endpoint: | ||||||
|  |     toHS: | ||||||
|  |       url: 'http://localhost:8008' | ||||||
|  |       token: 'ExampleTokenToHS-ChangeMe!' | ||||||
|  |     toAS: | ||||||
|  |       url: 'http://localhost:8090' | ||||||
|  |       token: 'ExampleTokenToAS-ChangeMe!' | ||||||
|  | ``` | ||||||
|  | ### Integration | ||||||
|  | #### Synapse | ||||||
|  | Under the `appsvc.registration.synapse` namespace: | ||||||
|  |  | ||||||
|  | | Key    | Type   | Required | Default            | Purpose                                                                  | | ||||||
|  | |--------|--------|----------|--------------------|--------------------------------------------------------------------------| | ||||||
|  | | `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  | ||||||
|  | ```yaml | ||||||
|  | appsvc: | ||||||
|  |   registration: | ||||||
|  |     synapse: | ||||||
|  |       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/ma1sd-appservice-registration.yaml' | ||||||
|  |   - ... | ||||||
|  | ``` | ||||||
|  |  | ||||||
|  | Restart synapse when done to register ma1sd. | ||||||
|  |  | ||||||
|  | #### Others | ||||||
|  | See your Homeserver documentation on how to integrate. | ||||||
|  |  | ||||||
|  | ## Capabilities | ||||||
|  | ### Admin commands | ||||||
|  | #### Setup | ||||||
|  | Min config: | ||||||
|  | ```yaml | ||||||
|  | appsvc: | ||||||
|  |   feature: | ||||||
|  |     admin: | ||||||
|  |       allowedRoles: | ||||||
|  |         - '+aMatrixCommunity:example.org' | ||||||
|  |         - 'SomeLdapGroup' | ||||||
|  |         - 'AnyOtherArbitraryRoleFromIdentityStores' | ||||||
|  | ``` | ||||||
|  |  | ||||||
|  | #### Use | ||||||
|  | The following steps assume: | ||||||
|  | - `matrix.domain` set to `example.org` | ||||||
|  | - `appsvc.user.main` set to `ma1sd` or not set | ||||||
|  |  | ||||||
|  | 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 | ||||||
| This feature allows for users found in Identity stores to be instantly notified about Room Invites, regardless if their | This feature allows for users found in Identity stores to be instantly notified about Room Invites, regardless if their | ||||||
| account was already provisioned on the Homeserver. | account was already provisioned on the Homeserver. | ||||||
|  |  | ||||||
| ### Requirements | #### Requirements | ||||||
| - [Identity store(s)](../../stores/README.md) supporting the Profile feature | - [Identity store(s)](../../stores/README.md) supporting the Profile feature | ||||||
| - At least one email entry in the identity store for each user that could be invited. | - At least one email entry in the identity store for each user that could be invited. | ||||||
|  |  | ||||||
| ### Configuration | #### Configuration | ||||||
| In your mxisd config file: | In your ma1sd config file: | ||||||
| ```yaml | ```yaml | ||||||
| matrix: |  | ||||||
|   listener: |  | ||||||
|     url:  '<URL TO THE CS API OF THE HOMESERVER>' |  | ||||||
|     localpart: 'appservice-mxisd' |  | ||||||
|     token: |  | ||||||
|       hs: 'HS_TOKEN_CHANGE_ME' |  | ||||||
|  |  | ||||||
| synapseSql: | synapseSql: | ||||||
|   enabled: false ## Do not use this line if Synapse is used as an Identity Store |   enabled: false ## Do not use this line if Synapse is used as an Identity Store | ||||||
|   type: '<DB TYPE>' |   type: '<DB TYPE>' | ||||||
|   connection: '<DB CONNECTION URL>' |   connection: '<DB CONNECTION URL>' | ||||||
| ``` | ``` | ||||||
|  |  | ||||||
| The `synapseSql` section is used to retrieve display names which are not directly accessible in this mode. | The `synapseSql` section is optional. It is used to retrieve display names which are not directly accessible in this mode. | ||||||
| For details about `type` and `connection`, see the [relevant documentation](../../stores/synapse.md). | For details about `type` and `connection`, see the [relevant documentation](../../stores/synapse.md). | ||||||
| If you do not configure it, some placeholders will not be available in the notification, like the Room name. | If you do not configure it, some placeholders will not be available in the notification, like the Room name. | ||||||
|  |  | ||||||
| You can also change the default template of the notification using the `generic.matrixId` template option.   | You can also change the default template of the notification using the `generic.matrixId` template option.   | ||||||
| See [the Template generator documentation](../../threepids/notification/template-generator.md) for more info. | See [the Template generator documentation](../../threepids/notification/template-generator.md) for more info. | ||||||
|  |  | ||||||
| ### Homeserver integration | #### Test | ||||||
| #### Synapse |  | ||||||
| Create a new appservice registration file. Futher config will assume it is in `/etc/matrix-synapse/appservice-mxisd.yaml` |  | ||||||
| ```yaml |  | ||||||
| id: "appservice-mxisd" |  | ||||||
| url: "http://127.0.0.1:8090" |  | ||||||
| as_token: "AS_TOKEN_CHANGE_ME" |  | ||||||
| hs_token: "HS_TOKEN_CHANGE_ME" |  | ||||||
| sender_localpart: "appservice-mxisd" |  | ||||||
| namespaces: |  | ||||||
|   users: |  | ||||||
|     - regex: "@*" |  | ||||||
|       exclusive: false |  | ||||||
|   aliases: [] |  | ||||||
|   rooms: [] |  | ||||||
| ``` |  | ||||||
| `id`: An arbitrary unique string to identify the AS.   |  | ||||||
| `url`: mxisd to reach mxisd. This ideally should be HTTP and not going through any reverse proxy.   |  | ||||||
| `as_token`: Arbitrary value used by mxisd when talking to the HS. Not currently used.   |  | ||||||
| `hs_token`: Arbitrary value used by synapse when talking to mxisd. Must match `token.hs` in mxisd config. |  | ||||||
| `sender_localpart`: Username for the mxisd itself on the HS. Default configuration should be kept.   |  | ||||||
| `namespaces`: To be kept as is.   |  | ||||||
|  |  | ||||||
| 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/appservice-mxisd.yaml' |  | ||||||
|   - ... |  | ||||||
| ``` |  | ||||||
|  |  | ||||||
| Restart synapse when done to register mxisd. |  | ||||||
|  |  | ||||||
| #### Others |  | ||||||
| See your Homeserver documentation on how to integrate. |  | ||||||
|  |  | ||||||
| ### Test |  | ||||||
| Invite a user which is part of your domain while an appropriate Identity store is used. | Invite a user which is part of your domain while an appropriate Identity store is used. | ||||||
|  |  | ||||||
|  | ### Auto-reject of expired 3PID invites | ||||||
|  | *TBC* | ||||||
|   | |||||||
| @@ -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.   | 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. | 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. | 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. | 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 | ## Overview | ||||||
| ``` | ``` | ||||||
|               +-------------------+   +-------------> +----------+ |               +-------------------+   +-------------> +----------+ | ||||||
|               | mxisd             |   |               | Backends | |               | ma1sd             |   |               | Backends | | ||||||
|               |                   |   |      +------> +----------+ |               |                   |   |      +------> +----------+ | ||||||
|               |                   |   |      | |               |                   |   |      | | ||||||
|               | Invites / Lookups |   |      | |               | Invites / Lookups |   |      | | ||||||
| @@ -23,7 +23,7 @@ Outbound federation is enabled by default while inbound federation is opt-in and | |||||||
|               |                   |          | |               |                   |          | | ||||||
|               | +--------+        |          |        +-------------------+ |               | +--------+        |          |        +-------------------+ | ||||||
|  Homeserver --->| Local  |>------------------+------> | Remote Federated  | |  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. | _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 | ## Outbound | ||||||
| If you would like to disable outbound federation and isolate your identity server from the rest of the Matrix network, | 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 | ```yaml | ||||||
| lookup: | lookup: | ||||||
|   recursive: |   recursive: | ||||||
| @@ -46,15 +46,6 @@ lookup: | |||||||
| invite: | invite: | ||||||
|   resolution: |   resolution: | ||||||
|     recursive: false |     recursive: false | ||||||
| session: |  | ||||||
|   policy: |  | ||||||
|     validation: |  | ||||||
|       forLocal: |  | ||||||
|         toRemote: |  | ||||||
|           enabled: false |  | ||||||
|       forRemote: |  | ||||||
|         toRemote: |  | ||||||
|           enabled: false |  | ||||||
| ```  | ```  | ||||||
|  |  | ||||||
| There is currently no way to selectively disable federation towards specific servers, but this feature is planned. | There is currently no way to selectively disable federation towards specific servers, but this feature is planned. | ||||||
|   | |||||||
| @@ -1,7 +1,12 @@ | |||||||
| # Identity | # Identity | ||||||
| **WARNING**: This document is incomplete and can be misleading. | Implementation of the [Identity Service API r0.2.0](https://matrix.org/docs/spec/identity_service/r0.2.0.html). | ||||||
|  |  | ||||||
| Implementation of the [Unofficial Matrix Identity Service API](https://kamax.io/matrix/api/identity_service/unstable.html). | - [Lookups](#lookups) | ||||||
|  | - [Invitations](#invitations) | ||||||
|  |   - [Expiration](#expiration) | ||||||
|  |   - [Policies](#policies) | ||||||
|  |   - [Resolution](#resolution) | ||||||
|  | - [3PIDs Management](#3pids-management) | ||||||
|  |  | ||||||
| ## Lookups | ## Lookups | ||||||
| If you would like to use the central matrix.org Identity server to ensure maximum discovery at the cost of potentially | If you would like to use the central matrix.org Identity server to ensure maximum discovery at the cost of potentially | ||||||
| @@ -12,10 +17,80 @@ forward: | |||||||
|     - 'matrix-org' |     - 'matrix-org' | ||||||
| ``` | ``` | ||||||
| **NOTE:** You should carefully consider enabling this option, which is discouraged.   | **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). | ||||||
|  |  | ||||||
| ## Room Invitations | ## Invitations | ||||||
| Resolution can be customized using the following configuration: | ### Expiration | ||||||
|  | #### Overview | ||||||
|  | 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, 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 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 | ||||||
|  | ```yaml | ||||||
|  | invite: | ||||||
|  |   expiration: | ||||||
|  |     enabled: true/false | ||||||
|  |     after: 5 | ||||||
|  |     resolveTo: '@john.doe:example.org' | ||||||
|  | ``` | ||||||
|  | `enabled` | ||||||
|  | - Purpose: Enable or disable the invite expiration feature. | ||||||
|  | - Default: `true` | ||||||
|  |  | ||||||
|  | `after`  | ||||||
|  | - Purpose: Amount of minutes before an invitation expires. | ||||||
|  | - Default: `10080` (7 days) | ||||||
|  |  | ||||||
|  | `resolveTo` | ||||||
|  | - Purpose: Matrix User ID to resolve the expired invitations to. | ||||||
|  | - Default: Computed from `appsvc.user.inviteExpired` and `matrix.domain` | ||||||
|  |  | ||||||
|  | ### Policies | ||||||
|  | 3PID invite policies are the companion feature of [Registration](registration.md). While the Registration feature acts on | ||||||
|  | requirements for the invitee/register, this feature acts on requirement for the one(s) performing 3PID invites, ensuring | ||||||
|  | a coherent system. | ||||||
|  |  | ||||||
|  | It relies on only allowing people with specific [Roles](profile.md) to perform 3PID invites. This would typically allow | ||||||
|  | a tight-control on a server setup with is "invite-only" or semi-open (relying on trusted people to invite new members). | ||||||
|  |  | ||||||
|  | It's a middle ground between a closed server, where every user must be created or already exists in an Identity store, | ||||||
|  | and an open server, where anyone can register. | ||||||
|  |   | ||||||
|  | #### Integration | ||||||
|  | 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 | ||||||
|  | ###### nginx | ||||||
|  | **IMPORTANT**: Must be placed before your global `/_matrix` entry: | ||||||
|  | ```nginx | ||||||
|  | location ~* ^/_matrix/client/r0/rooms/([^/]+)/invite$ { | ||||||
|  |     proxy_pass		    http://127.0.0.1:8090; | ||||||
|  |     proxy_set_header	Host $host; | ||||||
|  |     proxy_set_header	X-Forwarded-For $remote_addr; | ||||||
|  | } | ||||||
|  | ``` | ||||||
|  |  | ||||||
|  | #### Configuration | ||||||
|  | The only policy currently available is to restrict 3PID invite to users having a specific (set of) role(s), like so: | ||||||
|  |  | ||||||
|  | ```yaml | ||||||
|  | invite: | ||||||
|  |   policy: | ||||||
|  |     ifSender: | ||||||
|  |       hasRole: | ||||||
|  |         - '<THIS_ROLE>' | ||||||
|  |         - '<OR_THIS_ROLE>' | ||||||
|  | ``` | ||||||
|  |  | ||||||
|  | ### Resolution | ||||||
|  | Resolution of 3PID invitations can be customized using the following configuration: | ||||||
|  |  | ||||||
| `invite.resolution.recursive`   | `invite.resolution.recursive`   | ||||||
| - Default value: `true`   | - Default value: `true`   | ||||||
| @@ -26,7 +101,7 @@ Resolution can be customized using the following configuration: | |||||||
|  |  | ||||||
| `invite.resolution.timer`   | `invite.resolution.timer`   | ||||||
| - Default value: `1`   | - 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. | ||||||
|  |  | ||||||
| ## 3PID addition to user profile | ## 3PIDs Management | ||||||
| See the [3PID session documents](../threepids/session) | See the [3PID session documents](../threepids/session) | ||||||
|   | |||||||
							
								
								
									
										111
									
								
								docs/features/registration.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										111
									
								
								docs/features/registration.md
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,111 @@ | |||||||
|  | # Registration | ||||||
|  | - [Overview](#overview) | ||||||
|  | - [Integration](#integration) | ||||||
|  |   - [Reverse Proxy](#reverse-proxy) | ||||||
|  |     - [nginx](#nginx) | ||||||
|  |     - [Apache2](#apache2) | ||||||
|  |   - [Homeserver](#homeserver) | ||||||
|  |     - [synapse](#synapse) | ||||||
|  | - [Configuration](#configuration) | ||||||
|  |   - [Example](#example) | ||||||
|  | - [Usage](#usage) | ||||||
|  |  | ||||||
|  | ## 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 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 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. | ||||||
|  |  | ||||||
|  | **IMPORTANT:** This feature does not control registration in general. It only acts on endpoints related to 3PIDs during | ||||||
|  | the registration process.   | ||||||
|  | As such, it relies on the homeserver to require 3PIDs with the registration flows. | ||||||
|  |  | ||||||
|  | This feature is not part of the Matrix Identity Server spec. | ||||||
|  |  | ||||||
|  | ## Integration | ||||||
|  | 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 | ||||||
|  |  | ||||||
|  | Later version(s) of this feature may directly control registration itself to create a coherent experience | ||||||
|  | ### Reverse Proxy | ||||||
|  | #### nginx | ||||||
|  | ```nginx | ||||||
|  | location ~* ^/_matrix/client/r0/register/[^/]+/requestToken$ { | ||||||
|  | 	proxy_pass		http://localhost:8090; | ||||||
|  | 	proxy_set_header	Host $host; | ||||||
|  | 	proxy_set_header	X-Forwarded-For $remote_addr; | ||||||
|  | } | ||||||
|  | ``` | ||||||
|  |  | ||||||
|  | #### Apache2 | ||||||
|  | > TBC | ||||||
|  |  | ||||||
|  | ### Homeserver | ||||||
|  | #### Synapse | ||||||
|  | ```yaml | ||||||
|  | enable_registration: true | ||||||
|  | registrations_require_3pid: | ||||||
|  |   - email | ||||||
|  | ``` | ||||||
|  |  | ||||||
|  | ## Configuration | ||||||
|  | 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. | ||||||
|  |  | ||||||
|  | ### For invites | ||||||
|  | `register.invite`, taking a boolean, controls if registration can be made using a 3PID which matches a pending 3PID invite.   | ||||||
|  | `true` is the default value. | ||||||
|  |  | ||||||
|  | ### 3PID-specific | ||||||
|  | At this time, only `email` is supported with 3PID specific configuration with this feature. | ||||||
|  |  | ||||||
|  | #### Email | ||||||
|  | **Base key**: `register.threepid.email` | ||||||
|  |  | ||||||
|  | ##### Domain whitelist/blacklist | ||||||
|  | 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` | ||||||
|  |  | ||||||
|  | The value format is an hybrid between glob patterns and postfix configuration files with the following syntax: | ||||||
|  | - `*<domain>` will match the domain and any sub-domain(s) | ||||||
|  | - `.<domain>` will only match sub-domain(s) | ||||||
|  | - `<domain>` will only match the exact domain | ||||||
|  |  | ||||||
|  | The following table illustrates pattern and matching status against example values: | ||||||
|  |  | ||||||
|  | | Config value   | Matches `example.org` | Matches `sub.example.org` | | ||||||
|  | |--------------- |-----------------------|---------------------------| | ||||||
|  | | `*example.org` | Yes                   | Yes                       | | ||||||
|  | | `.example.org` | No                    | Yes                       | | ||||||
|  | | `example.org`  | Yes                   | No                        | | ||||||
|  |  | ||||||
|  | ### Example | ||||||
|  | For the following example configuration: | ||||||
|  | ```yaml | ||||||
|  | register: | ||||||
|  |   policy: | ||||||
|  |     threepid: | ||||||
|  |       email: | ||||||
|  |         domain: | ||||||
|  |           whitelist: | ||||||
|  |             - '*example.org' | ||||||
|  |             - '.example.net' | ||||||
|  |             - 'example.com' | ||||||
|  | ``` | ||||||
|  | - Users can register using 3PIDs of pending invites, being allowed by default. | ||||||
|  | - Users can register using an email from `example.org` and any sub-domain, only sub-domains of `example.net` and `example.com` but not its sub-domains. | ||||||
|  | - Otherwise, user registration will be denied. | ||||||
|  |  | ||||||
|  | ## Usage | ||||||
|  | Nothing special is needed. Register using a regular Matrix client. | ||||||
| @@ -6,15 +6,14 @@ | |||||||
| 5. [Validate](#validate) | 5. [Validate](#validate) | ||||||
| 6. [Next steps](#next-steps) | 6. [Next steps](#next-steps) | ||||||
|  |  | ||||||
| Following these quick start instructions, you will have a basic setup that can perform recursive/federated lookups and | Following these quick start instructions, you will have a basic setup that can perform recursive/federated lookups.   | ||||||
| talk to the central Matrix.org Identity server.   |  | ||||||
| This will be a good ground work for further integration with features and your existing Identity stores. | This will be a good ground work for further integration with features and your existing Identity stores. | ||||||
|  |  | ||||||
| --- | --- | ||||||
|  |  | ||||||
| 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) | 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.   | 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 mxisd version is always supported. | 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 | 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). | directly go to the [Next steps](#next-steps). | ||||||
| @@ -22,17 +21,21 @@ directly go to the [Next steps](#next-steps). | |||||||
| ## Preparation | ## Preparation | ||||||
| You will need: | You will need: | ||||||
| - Working Homeserver, ideally with working federation | - 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 | ||||||
|  |  | ||||||
| As synapse requires an HTTPS connection when talking to an Identity service, **a reverse proxy is required** as mxisd does | If you use synapse: | ||||||
| not support HTTPS listener at this time. | - 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 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 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 | ||||||
| hostname. | 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 | If you would like a high-level view of the infrastructure and how each feature is integrated, see the | ||||||
| [dedicated document](architecture.md) | [dedicated document](architecture.md) | ||||||
|  |  | ||||||
| @@ -44,37 +47,30 @@ Install via: | |||||||
| - [NixOS](install/nixos.md) | - [NixOS](install/nixos.md) | ||||||
| - [Sources](build.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 | ## Configure | ||||||
| > **NOTE**: Please view the install instruction for your platform, as this step might be optional or already handled for you. | > **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) | > **NOTE**: Details about configuration syntax and format are described [here](configure.md) | ||||||
|  |  | ||||||
| Create/edit a minimal configuration (see installer doc for the location): | If you haven't created a configuration file yet, copy `ma1sd.example.yaml` to where the configuration file is stored given | ||||||
| ```yaml | your installation method and edit to your needs. | ||||||
| matrix: |  | ||||||
|   domain: 'example.org' | The following items must be at least configured: | ||||||
| key: |  | ||||||
|   path: '/path/to/signing.key.file' |  | ||||||
| storage: |  | ||||||
|   provider: |  | ||||||
|     sqlite: |  | ||||||
|       database: '/path/to/mxisd.db' |  | ||||||
| ```   |  | ||||||
| - `matrix.domain` should be set to your Homeserver domain (`server_name` in synapse configuration) | - `matrix.domain` should be set to your Homeserver domain (`server_name` in synapse configuration) | ||||||
| - `key.path` will store the signing keys, which must be kept safe! If the file does not exist, keys will be generated for you. | - `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.) | - `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). | Complete configuration guide is available [here](configure.md). | ||||||
|  |  | ||||||
| ## Integrate | ## 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 | ### Reverse proxy | ||||||
| #### Apache2 | #### Apache2 | ||||||
| In the `VirtualHost` section handling the domain with SSL, add the following and replace `0.0.0.0` by the internal | 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!** | **This line MUST be present before the one for the homeserver!** | ||||||
| ```apache | ```apache | ||||||
| ProxyPass /_matrix/identity http://0.0.0.0:8090/_matrix/identity | ProxyPass /_matrix/identity http://0.0.0.0:8090/_matrix/identity | ||||||
| @@ -83,9 +79,9 @@ ProxyPass /_matrix/identity http://0.0.0.0:8090/_matrix/identity | |||||||
| Typical configuration would look like: | Typical configuration would look like: | ||||||
| ```apache | ```apache | ||||||
| <VirtualHost *:443> | <VirtualHost *:443> | ||||||
|     ServerName example.org |     ServerName matrix.example.org | ||||||
|      |      | ||||||
|     ... |     # ... | ||||||
|      |      | ||||||
|     ProxyPreserveHost on |     ProxyPreserveHost on | ||||||
|     ProxyPass /_matrix/identity http://localhost:8090/_matrix/identity |     ProxyPass /_matrix/identity http://localhost:8090/_matrix/identity | ||||||
| @@ -95,7 +91,7 @@ Typical configuration would look like: | |||||||
|  |  | ||||||
| #### nginx | #### nginx | ||||||
| In the `server` section handling the domain with SSL, add the following and replace `0.0.0.0` with the internal | 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!** | **This line MUST be present before the one for the homeserver!** | ||||||
| ```nginx | ```nginx | ||||||
| location /_matrix/identity { | location /_matrix/identity { | ||||||
| @@ -107,9 +103,9 @@ Typical configuration would look like: | |||||||
| ```nginx | ```nginx | ||||||
| server { | server { | ||||||
|     listen 443 ssl; |     listen 443 ssl; | ||||||
|     server_name example.org; |     server_name matrix.example.org; | ||||||
|      |      | ||||||
|     ... |     # ... | ||||||
|      |      | ||||||
|     location /_matrix/identity { |     location /_matrix/identity { | ||||||
|         proxy_pass http://localhost:8090/_matrix/identity; |         proxy_pass http://localhost:8090/_matrix/identity; | ||||||
| @@ -126,33 +122,36 @@ server { | |||||||
| ``` | ``` | ||||||
|  |  | ||||||
| ### Synapse | ### Synapse | ||||||
| Add your mxisd domain into the `homeserver.yaml` at `trusted_third_party_id_servers` and restart synapse.   | 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: | In a typical configuration, you would end up with something similar to: | ||||||
| ```yaml | ```yaml | ||||||
| trusted_third_party_id_servers: | trusted_third_party_id_servers: | ||||||
|     - example.org |     - matrix.example.org | ||||||
| ``` | ``` | ||||||
| It is recommended to remove `matrix.org` and `vector.im` (or any other default entry) from your configuration so only | It is **highly recommended** to remove `matrix.org` and `vector.im` (or any other default entry) from your configuration | ||||||
| your own Identity server is authoritative for your HS. | 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 | **NOTE:** In case your homeserver has no working federation, step 5 will not happen. If step 4 took place, consider | ||||||
| your installation validated. | your installation validated. | ||||||
|  |  | ||||||
| 1. Log in using your Matrix client and set `https://example.org` as your Identity server URL, replacing `example.org` by | 1. Log in using your Matrix client and set `https://matrix.example.org` as your Identity server URL, replacing `matrix.example.org` | ||||||
| the relevant hostname which you configured in your reverse proxy. | 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. | 2. Create a new empty room. All further actions will take place in this room. | ||||||
| 3. Invite `mxisd-federation-test@kamax.io` | 3. Invite `ma1sd-federation-test@kamax.io` | ||||||
| 4. The 3PID invite should be turned into a Matrix invite to `@mxisd-lookup-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. | 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. | **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, [get in touch](../README.md#support) and we'll do our best to get you started. | 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 | ## 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: | infrastructure: | ||||||
|  |  | ||||||
| - [Enable extra features](features/) | - [Enable extra features](features/) | ||||||
| - [Use your own Identity stores](stores/README.md) | - [Use your own Identity stores](stores/README.md) | ||||||
|  | - [Hardening your ma1sd installation](install/security.md) | ||||||
|  | - [Learn about day-to-day operations](operations.md) | ||||||
|   | |||||||
| @@ -1,3 +1,9 @@ | |||||||
|  | --- | ||||||
|  |  | ||||||
|  | ** Outdated due to migrating to fork. ** | ||||||
|  |  | ||||||
|  | --- | ||||||
|  |  | ||||||
| # Arch Linux package | # Arch Linux package | ||||||
| An Arch Linux package in the AUR repos is maintained by [r3pek](https://matrix.to/#/@r3pek:r3pek.org), a community member.   | 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/ | See https://aur.archlinux.org/packages/mxisd/ | ||||||
|   | |||||||
| @@ -3,40 +3,40 @@ | |||||||
| - Any distribution that supports Java 8 | - Any distribution that supports Java 8 | ||||||
|  |  | ||||||
| ## Install | ## 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: | 2. Run: | ||||||
| ```bash | ```bash | ||||||
| dpkg -i /path/to/downloaded/mxisd.deb | dpkg -i /path/to/downloaded/ma1sd.deb | ||||||
| ``` | ``` | ||||||
| ## Files | ## Files | ||||||
| | Location                            | Purpose                                      | | | Location                            | Purpose                                      | | ||||||
| |-------------------------------------|----------------------------------------------| | |-------------------------------------|----------------------------------------------| | ||||||
| | `/etc/mxisd`                        | Configuration directory                      | | | `/etc/ma1sd`                        | Configuration directory                      | | ||||||
| | `/etc/mxisd/mxisd.yaml`             | Main configuration file                      | | | `/etc/ma1sd/ma1sd.yaml`             | Main configuration file                      | | ||||||
| | `/etc/systemd/system/mxisd.service` | Systemd configuration file for mxisd service | | | `/etc/systemd/system/ma1sd.service` | Systemd configuration file for ma1sd service | | ||||||
| | `/usr/lib/mxisd`                    | Binaries                                     | | | `/usr/lib/ma1sd`                    | Binaries                                     | | ||||||
| | `/var/lib/mxisd`                    | Data                                         | | | `/var/lib/ma1sd`                    | Data                                         | | ||||||
| | `/var/lib/mxisd/signing.key`        | Default location for mxisd signing keys      | | | `/var/lib/ma1sd/signing.key`        | Default location for ma1sd signing keys      | | ||||||
|  |  | ||||||
| ## Control | ## Control | ||||||
| Start mxisd using: | Start ma1sd using: | ||||||
| ```bash | ```bash | ||||||
| sudo systemctl start mxisd | sudo systemctl start ma1sd | ||||||
| ``` | ``` | ||||||
|  |  | ||||||
| Stop mxisd using: | Stop ma1sd using: | ||||||
| ```bash | ```bash | ||||||
| sudo systemctl stop mxisd | sudo systemctl stop ma1sd | ||||||
| ``` | ``` | ||||||
|  |  | ||||||
| ## Troubleshoot | ## Troubleshoot | ||||||
| All logs are sent to `STDOUT` which are saved in `/var/log/syslog` by default.   | All logs are sent to `STDOUT` which are saved in `/var/log/syslog` by default.   | ||||||
| You can: | 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: | - use Systemd's journal: | ||||||
| ``` | ``` | ||||||
| journalctl -f -n 99 -u mxisd | journalctl -f -n 99 -u ma1sd | ||||||
| ``` | ``` | ||||||
|   | |||||||
| @@ -1,13 +1,19 @@ | |||||||
|  | --- | ||||||
|  |  | ||||||
|  | ** Outdated due to migrating to fork. ** | ||||||
|  |  | ||||||
|  | --- | ||||||
|  |  | ||||||
| # Docker | # Docker | ||||||
| ## Fetch | ## Fetch | ||||||
| Pull the latest stable image: | Pull the latest stable image: | ||||||
| ```bash | ```bash | ||||||
| docker pull kamax/mxisd | docker pull ma1uta/ma1sd | ||||||
| ``` | ``` | ||||||
|  |  | ||||||
| ## Configure | ## Configure | ||||||
| On first run, simply using `MATRIX_DOMAIN` as an environment variable will create a default config for you.   | 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. | container. | ||||||
|  |  | ||||||
| ## Run | ## Run | ||||||
| @@ -16,7 +22,10 @@ Use the following command after adapting to your needs: | |||||||
| - The volumes host paths | - The volumes host paths | ||||||
|  |  | ||||||
| ```bash | ```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). | ||||||
|   | |||||||
| @@ -1,3 +1,9 @@ | |||||||
|  | --- | ||||||
|  |  | ||||||
|  | ** Outdated due to migrating to fork. ** | ||||||
|  |  | ||||||
|  | --- | ||||||
|  |  | ||||||
| # NixOS package | # NixOS package | ||||||
| mxisd is available as a NixOS package in the official repos. | mxisd is available as a NixOS package in the official repos. | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										30
									
								
								docs/install/security.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								docs/install/security.md
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,30 @@ | |||||||
|  | # Security hardening | ||||||
|  | ## Overview | ||||||
|  | This document outlines the various operations you may want to perform to increase the security of your installation and | ||||||
|  | avoid leak of credentials/key pairs | ||||||
|  |  | ||||||
|  | ## Configuration | ||||||
|  | Your config file should have the following ownership: | ||||||
|  | - 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 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 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 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, | ||||||
|  | everything before is using a file. | ||||||
|  | - If your version is directory-based, you will want to apply chmod `700` on it. | ||||||
|  | - If your version is file-based, you will want to apply chmod `600` on it. | ||||||
| @@ -5,40 +5,40 @@ Follow the [build instructions](../build.md) then: | |||||||
| ### Prepare files and directories: | ### Prepare files and directories: | ||||||
| ```bash | ```bash | ||||||
| # Create a dedicated user | # Create a dedicated user | ||||||
| useradd -r mxisd | useradd -r ma1sd | ||||||
|  |  | ||||||
| # Create config directory and set ownership | # Create config directory | ||||||
| mkdir -p /etc/mxisd | mkdir -p /etc/ma1sd | ||||||
|  |  | ||||||
| # Create data directory and set ownership | # Create data directory and set ownership | ||||||
| mkdir -p /var/lib/mxisd | mkdir -p /var/lib/ma1sd | ||||||
| chown -R mxisd /var/lib/mxisd | chown -R ma1sd /var/lib/ma1sd | ||||||
|  |  | ||||||
| # Create bin directory, copy the jar and launch scriot to bin directory | # Create bin directory, copy the jar and launch scriot to bin directory | ||||||
| mkdir /usr/lib/mxisd | mkdir /usr/lib/ma1sd | ||||||
| cp ./build/libs/mxisd.jar /usr/lib/mxisd/ | cp ./build/libs/ma1sd.jar /usr/lib/ma1sd/ | ||||||
| cp ./src/script/mxisd /usr/lib/mxisd | cp ./src/script/ma1sd /usr/lib/ma1sd | ||||||
| chown -R mxisd /usr/lib/mxisd | chown -R ma1sd /usr/lib/ma1sd | ||||||
| chmod a+x /usr/lib/mxisd/mxisd | chmod a+x /usr/lib/ma1sd/ma1sd | ||||||
|  |  | ||||||
| # Create symlink for easy exec | # 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 | ### Prepare config file | ||||||
| Copy the sample config file `./mxisd.example.yaml` to `/etc/mxisd/mxisd.yaml`, edit to your needs | Copy the configuration file you've created following the build instructions to `/etc/ma1sd/ma1sd.yaml` | ||||||
|  |  | ||||||
| ### Prepare Systemd | ### 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 | 2. Enable service for auto-startup | ||||||
| ```bash | ```bash | ||||||
| systemctl enable mxisd | systemctl enable ma1sd | ||||||
| ``` | ``` | ||||||
|  |  | ||||||
| ### Run | ### Run | ||||||
| ```bash | ```bash | ||||||
| systemctl start mxisd | systemctl start ma1sd | ||||||
| ``` | ``` | ||||||
|  |  | ||||||
| ## Debug | ## 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`. | ||||||
|   | |||||||
							
								
								
									
										16
									
								
								docs/migration-from-mxisd.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								docs/migration-from-mxisd.md
									
									
									
									
									
										Normal 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. | ||||||
							
								
								
									
										21
									
								
								docs/operations.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								docs/operations.md
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,21 @@ | |||||||
|  | # Operations Guide | ||||||
|  | - [Overview](#overview) | ||||||
|  | - [Maintenance](#maintenance) | ||||||
|  | - [Backuo](#backup) | ||||||
|  |  | ||||||
|  | ## Overview | ||||||
|  | This document gives various information for the day-to-day management and operations of ma1sd. | ||||||
|  |  | ||||||
|  | ## Maintenance | ||||||
|  | ma1sd does not require any maintenance task to run at optimal performance. | ||||||
|  |  | ||||||
|  | ## Backup | ||||||
|  | ### Run | ||||||
|  | ma1sd requires all file in its configuration and data directory to be backed up.   | ||||||
|  | They are usually located at: | ||||||
|  | - `/etc/ma1sd` | ||||||
|  | - `/var/lib/ma1sd` | ||||||
|  |  | ||||||
|  | ### Restore | ||||||
|  | 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. | ||||||
| @@ -39,10 +39,10 @@ | |||||||
| | [Authentication](../features/authentication.md) | Yes       | | | [Authentication](../features/authentication.md) | Yes       | | ||||||
| | [Directory](../features/directory.md)           | Yes       | | | [Directory](../features/directory.md)           | Yes       | | ||||||
| | [Identity](../features/identity.md)             | Yes       | | | [Identity](../features/identity.md)             | Yes       | | ||||||
| | [Profile](#profile)                             | Yes       | | | [Profile](../features/profile.md)               | Yes       | | ||||||
|  |  | ||||||
| This Identity Store lets you run arbitrary commands to handle the various requests in each support feature.   | 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 | ## Overview | ||||||
| Each request can be mapping to a fully customizable command configuration.   | Each request can be mapping to a fully customizable command configuration.   | ||||||
| @@ -190,7 +190,7 @@ The following types are available: | |||||||
| exec: | exec: | ||||||
|   auth: |   auth: | ||||||
|     enabled: true |     enabled: true | ||||||
|     command: '/opt/mxisd-exec/auth.sh' |     command: '/opt/ma1sd-exec/auth.sh' | ||||||
|     args: ['{localpart}'] |     args: ['{localpart}'] | ||||||
|     input: |     input: | ||||||
|       type: 'plain' |       type: 'plain' | ||||||
| @@ -198,8 +198,8 @@ exec: | |||||||
|   env: |   env: | ||||||
|     DOMAIN: '{domain}' |     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 `localoart` as username  | - 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 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 | - A single environment variable `DOMAIN` containing Matrix ID domain, if given | ||||||
|  |  | ||||||
| @@ -207,26 +207,34 @@ The command will use the default values for: | |||||||
| - Success exit status of `0` | - Success exit status of `0` | ||||||
| - Failure exit status of `1` | - Failure exit status of `1` | ||||||
| - Any other exit status considered as error | - Any other exit status considered as error | ||||||
| - The standard output processing as not processed | - Standard output will not be processed | ||||||
|  |  | ||||||
| #### Advanced | #### Advanced | ||||||
| Given the fictional `placeholder` feature: | Given the fictional `placeholder` feature: | ||||||
| ```yaml | ```yaml | ||||||
| exec.enabled: true | exec: | ||||||
| exec.token.mxid: '{matrixId}' |   enabled: true | ||||||
|  |   token: | ||||||
| exec.placeholder.token.localpart: '{username}' |     mxid: '{matrixId}' | ||||||
| exec.placeholder.command: '/path/to/executable' |   auth: | ||||||
| exec.placeholder.args: |     token: | ||||||
|   - '-u' |       localpart: '{username}' | ||||||
|   - '{username}' |     command: '/path/to/executable' | ||||||
| exec.placeholder.env: |     args: | ||||||
|   MATRIX_DOMAIN: '{domain}' |       - '-u' | ||||||
|   MATRIX_USER_ID: '{matrixId}' |       - '{username}' | ||||||
|    |     env: | ||||||
| exec.placeholder.output.type: 'json' |       MATRIX_DOMAIN: '{domain}' | ||||||
| exec.placeholder.exit.success: [0, 128] |       MATRIX_USER_ID: '{matrixId}' | ||||||
| exec.placeholder.exit.failure: [1, 129] |     output: | ||||||
|  |       type: 'json' | ||||||
|  |     exit: | ||||||
|  |       success: | ||||||
|  |         - 0 | ||||||
|  |         - 128 | ||||||
|  |       failure: | ||||||
|  |         - 1 | ||||||
|  |         - 129 | ||||||
| ``` | ``` | ||||||
| With: | With: | ||||||
| - The Identity store enabled for all features | - The Identity store enabled for all features | ||||||
|   | |||||||
| @@ -2,12 +2,12 @@ | |||||||
| https://firebase.google.com/ | https://firebase.google.com/ | ||||||
|  |  | ||||||
| ## Features | ## Features | ||||||
| |      Name      | Supported? | | |                       Name                      | Supported | | ||||||
| |----------------|------------| | |-------------------------------------------------|-----------| | ||||||
| | Authentication | Yes        | | | [Authentication](../features/authentication.md) | Yes       | | ||||||
| | Directory      | No         | | | [Directory](../features/directory.md)           | No        | | ||||||
| | Identity       | Yes        | | | [Identity](../features/identity.md)             | Yes       | | ||||||
| | Profile        | No         | | | [Profile](../features/profile.md)               | No        | | ||||||
|  |  | ||||||
| ## Requirements | ## Requirements | ||||||
| This backend requires a suitable Matrix client capable of performing Firebase authentication and passing the following | This backend requires a suitable Matrix client capable of performing Firebase authentication and passing the following | ||||||
|   | |||||||
| @@ -8,28 +8,28 @@ | |||||||
| For NetIQ, replace all the `ldap` prefix in the configuration by `netiq`. | For NetIQ, replace all the `ldap` prefix in the configuration by `netiq`. | ||||||
|  |  | ||||||
| ## Features | ## Features | ||||||
| |      Name      | Supported? | | |                       Name                      | Supported | | ||||||
| |----------------|------------| | |-------------------------------------------------|-----------| | ||||||
| | Authentication | Yes        | | | [Authentication](../features/authentication.md) | Yes       | | ||||||
| | Directory      | Yes        | | | [Directory](../features/directory.md)           | Yes       | | ||||||
| | Identity       | Yes        | | | [Identity](../features/identity.md)             | Yes       | | ||||||
| | Profile        | Yes        | | | [Profile](../features/profile.md)               | Yes       | | ||||||
|  |  | ||||||
| ## Getting started | ## Getting started | ||||||
| ### Base | ### 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 | ```yaml | ||||||
| ldap: | ldap: | ||||||
|   enabled: true |   enabled: true | ||||||
|   connection: |   connection: | ||||||
|     host: 'ldapHostnameOrIp' |     host: 'ldapHostnameOrIp' | ||||||
|     port: 389 |     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' |     bindPassword: 'TheUserPassword' | ||||||
|     baseDNs: |     baseDNs: | ||||||
|       - 'OU=Users,DC=example,DC=org' |       - '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`. | If you would like to use several Base DNs, simply add more entries under `baseDNs`. | ||||||
|  |  | ||||||
| @@ -89,7 +89,7 @@ ldap: | |||||||
| #### 3PIDs | #### 3PIDs | ||||||
| You can also change the attribute lists for 3PID, like email or phone numbers. | You can also change the attribute lists for 3PID, like email or phone numbers. | ||||||
|  |  | ||||||
| The following example would overwrite the [default list of attributes](../../src/main/resources/application.yaml#L67) | The following example would overwrite the [default list of attributes](../../src/main/java/io/kamax/ma1sd/config/ldap/LdapConfig.java#L64) | ||||||
| for emails and phone number: | for emails and phone number: | ||||||
| ```yaml | ```yaml | ||||||
| ldap: | ldap: | ||||||
| @@ -113,16 +113,18 @@ configuration item is needed to get started. | |||||||
| - `ldap.identity.medium`: Namespace to overwrite generated queries from the list of attributes for each 3PID medium. | - `ldap.identity.medium`: Namespace to overwrite generated queries from the list of attributes for each 3PID medium. | ||||||
|  |  | ||||||
| ### Authentication | ### Authentication | ||||||
| No further configuration is needed to use the Authentication feature with LDAP once globally enabled and configured. | After you have configured and enabled the [feature itself](../features/authentication.md), no further configuration is | ||||||
|  | needed with this identity store to make it work. | ||||||
|  |  | ||||||
| Profile auto-fill is enabled by default. It will use the `ldap.attribute.name` and `ldap.attribute.threepid` configuration | Profile auto-fill is enabled by default. It will use the `ldap.attribute.name` and `ldap.attribute.threepid` configuration | ||||||
| options to get a lit of attributes to be used to build the user profile to pass on to synapse during authentication. | options to get a lit of attributes to be used to build the user profile to pass on to synapse during authentication. | ||||||
|  |  | ||||||
| #### Configuration | #### Configuration | ||||||
| - `ldap.auth.filter`: Specific user filter applied during identity search. Global filter is used if blank/not set. | - `ldap.auth.filter`: Specific user filter applied during username search. Global filter is used if blank/not set. | ||||||
|  |  | ||||||
| ### Directory | ### Directory | ||||||
| No further configuration is needed to use the Directory feature with LDAP once globally enabled and configured. | After you have configured and enabled the [feature itself](../features/directory.md), no further configuration is | ||||||
|  | needed with this identity store to make it work. | ||||||
|  |  | ||||||
| #### Configuration | #### Configuration | ||||||
| To set a specific filter applied during directory search, use `ldap.directory.filter` | To set a specific filter applied during directory search, use `ldap.directory.filter` | ||||||
|   | |||||||
| @@ -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.enabled`                       | `false`                                        | Globally enable/disable the REST backend             | | ||||||
| | `rest.host`                          | *None*                                         | Default base URL to use for the different endpoints. | | | `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.auth`                | `/_ma1sd/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.directory`           | `/_ma1sd/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.single`     | `/_ma1sd/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.identity.bulk`       | `/_ma1sd/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.displayName` | `/_ma1sd/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.threepids`   | `/_ma1sd/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.profile.roles`       | `/_ma1sd/backend/api/v1/profile/roles`         | Query the Roles for a Matrix ID | ||||||
|  |  | ||||||
| Endpoint values can handle two formats: | Endpoint values can handle two formats: | ||||||
| - URL Path starting with `/` that gets happened to the `rest.host` | - URL Path starting with `/` that gets happened to the `rest.host` | ||||||
|   | |||||||
| @@ -6,12 +6,12 @@ | |||||||
| - SQLite | - SQLite | ||||||
|  |  | ||||||
| ## Features | ## Features | ||||||
| |      Name      | Supported? | | |                       Name                      | Supported | | ||||||
| |----------------|------------| | |-------------------------------------------------|-----------| | ||||||
| | Authentication | No         | | | [Authentication](../features/authentication.md) | No        | | ||||||
| | Directory      | Yes        | | | [Directory](../features/directory.md)           | Yes       | | ||||||
| | Identity       | Yes        | | | [Identity](../features/identity.md)             | Yes       | | ||||||
| | Profile        | Yes        | | | [Profile](../features/profile.md)               | Yes       | | ||||||
|  |  | ||||||
| Due to the implementation complexity of supporting arbitrary hashing/encoding mechanisms or auth flow, Authentication | Due to the implementation complexity of supporting arbitrary hashing/encoding mechanisms or auth flow, Authentication | ||||||
| will be out of scope of SQL Identity stores and should be done via one of the other identity stores, typically | will be out of scope of SQL Identity stores and should be done via one of the other identity stores, typically | ||||||
| @@ -80,7 +80,7 @@ sql: | |||||||
|         type: <string> |         type: <string> | ||||||
|         value: <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 | - `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. | - `mxid` will use the ID as-is. If it is not a valid Matrix ID, the search will fail. | ||||||
|  |  | ||||||
| @@ -102,9 +102,41 @@ sql: | |||||||
| ``` | ``` | ||||||
|  |  | ||||||
| ### Identity | ### Identity | ||||||
|  | **NOTE**: Only single lookup is supported. Bulk lookup always returns no mapping. This is a restriction as the Matrix API | ||||||
|  | does not allow paging or otherwise limit of results of the API, potentially leading to thousands and thousands 3PIDs at once. | ||||||
|  |  | ||||||
| ```yaml | ```yaml | ||||||
| sql: | sql: | ||||||
|   identity: |   identity: | ||||||
|  |     enabled: <boolean> | ||||||
|     type: <string> |     type: <string> | ||||||
|     query: <string> |     query: <string> | ||||||
|  |     medium: | ||||||
|  |      mediumTypeExample: <dedicated query> | ||||||
| ``` | ``` | ||||||
|  | `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. | ||||||
|  |  | ||||||
|  | A specific query can also given per 3PID medium type. | ||||||
|  |  | ||||||
|  | ### Profile | ||||||
|  | ```yaml | ||||||
|  | sql: | ||||||
|  |   profile: | ||||||
|  |     enabled: <boolean> | ||||||
|  |     displayName: | ||||||
|  |       query: <string> | ||||||
|  |     threepid: | ||||||
|  |       query: <string> | ||||||
|  |     role: | ||||||
|  |       type: <string> | ||||||
|  |       query: <string> | ||||||
|  |      | ||||||
|  |  | ||||||
|  | ``` | ||||||
|  | For the `role` query, `type` can be used to tell ma1sd how to inject the User ID in the query: | ||||||
|  | - `localpart` 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. | ||||||
|   | |||||||
| @@ -1,15 +1,17 @@ | |||||||
| # Synapse Identity Store | # Synapse Identity Store | ||||||
| Synapse's Database itself can be used as an Identity store. | Synapse's Database itself can be used as an Identity store. This identity store is a regular SQL store with | ||||||
|  | built-in default queries that matches Synapse DB. | ||||||
|  |  | ||||||
| ## Features | ## Features | ||||||
| |      Name      | Supported? | | |                       Name                      | Supported | | ||||||
| |----------------|------------| | |-------------------------------------------------|-----------| | ||||||
| | Authentication | No         | | | [Authentication](../features/authentication.md) | No        | | ||||||
| | Directory      | Yes        | | | [Directory](../features/directory.md)           | Yes       | | ||||||
| | Identity       | Yes        | | | [Identity](../features/identity.md)             | Yes       | | ||||||
| | Profile        | Yes        | | | [Profile](../features/profile.md)               | Yes       | | ||||||
|  |  | ||||||
| Authentication is done by Synapse itself. | - Authentication is done by Synapse itself. | ||||||
|  | - Roles are mapped to communities. The Role name/ID uses the community ID in the form `+id:domain.tld` | ||||||
|  |  | ||||||
| ## Configuration | ## Configuration | ||||||
| ### Basic | ### Basic | ||||||
|   | |||||||
| @@ -5,12 +5,12 @@ Two types of connections are required for full support: | |||||||
| - Direct SQL access | - Direct SQL access | ||||||
|  |  | ||||||
| ## Features | ## Features | ||||||
| |      Name      | Supported? | | |                       Name                      | Supported | | ||||||
| |----------------|------------| | |-------------------------------------------------|-----------| | ||||||
| | Authentication | Yes        | | | [Authentication](../features/authentication.md) | Yes       | | ||||||
| | Directory      | Yes        | | | [Directory](../features/directory.md)           | Yes       | | ||||||
| | Identity       | Yes        | | | [Identity](../features/identity.md)             | Yes       | | ||||||
| | Profile        | No         | | | [Profile](../features/profile.md)               | No        | | ||||||
|  |  | ||||||
| ## Requirements | ## Requirements | ||||||
| - [Wordpress](https://wordpress.org/download/) >= 4.4 | - [Wordpress](https://wordpress.org/download/) >= 4.4 | ||||||
| @@ -29,9 +29,9 @@ define('JWT_AUTH_SECRET_KEY', 'your-top-secret-key'); | |||||||
|  |  | ||||||
| #### Rewrite of `index.php` | #### Rewrite of `index.php` | ||||||
| Wordpress is normally configured with rewrite of `index.php` so it does not appear in URLs.   | 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: | Enable in the configuration: | ||||||
| ```yaml | ```yaml | ||||||
| wordpress: | wordpress: | ||||||
|   | |||||||
| @@ -1,6 +1,4 @@ | |||||||
| # Email notifications - SMTP connector | # Email notifications - SMTP connector | ||||||
| Enabled by default. |  | ||||||
|  |  | ||||||
| Connector ID: `smtp` | Connector ID: `smtp` | ||||||
|  |  | ||||||
| ## Configuration | ## Configuration | ||||||
| @@ -14,8 +12,8 @@ threepid: | |||||||
|       connectors: |       connectors: | ||||||
|         smtp: |         smtp: | ||||||
|           host: 'smtpHostname' |           host: 'smtpHostname' | ||||||
|           port: 587 |           tls: 1 # 0 = no STARTLS, 1 = try, 2 = force, 3 = TLS/SSL | ||||||
|           tls: 1 # 0 = no STARTLS, 1 = try, 2 = force |           port: 587 # Set appropriate value depending on your TLS setting | ||||||
|           login: 'smtpLogin' |           login: 'smtpLogin' | ||||||
|           password: 'smtpPassword' |           password: 'smtpPassword' | ||||||
| ``` | ``` | ||||||
|   | |||||||
| @@ -1,6 +1,4 @@ | |||||||
| # SMS notifications - Twilio connector | # SMS notifications - Twilio connector | ||||||
| Enabled by default. |  | ||||||
|  |  | ||||||
| Connector ID: `twilio` | Connector ID: `twilio` | ||||||
|  |  | ||||||
| ## Configuration | ## Configuration | ||||||
| @@ -10,7 +8,7 @@ threepid: | |||||||
|     msisdn: |     msisdn: | ||||||
|       connectors: |       connectors: | ||||||
|         twilio: |         twilio: | ||||||
|           accountSid: 'myAccountSid' |           account_sid: 'myAccountSid' | ||||||
|           authToken: 'myAuthToken' |           auth_token: 'myAuthToken' | ||||||
|           number: '+123456789' |           number: '+123456789' | ||||||
| ``` | ``` | ||||||
|   | |||||||
| @@ -26,19 +26,13 @@ notification: | |||||||
|             html: <Path to file containing the HTML 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> | ||||||
|         session: |         session: | ||||||
|           validation: |           validation: | ||||||
|             local: |             subject: <Subject of the email notification sent for 3PID sessions> | ||||||
|               subject: <Subject of the email notification sent for local 3PID sessions> |             body: | ||||||
|               body: |               text: <Path to file containing the raw text part of the email. Do not set to not use one> | ||||||
|                 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> | ||||||
|                 html: <Path to file containing the HTML part of the email. Do not set to not use one> |  | ||||||
|             remote: |  | ||||||
|               subject: <Subject of the email notification sent for remote 3PID sessions> |  | ||||||
|               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 HTML part of the email. Do not set to not use one> |  | ||||||
|           unbind: |           unbind: | ||||||
|             fraudulent: |             notification: | ||||||
|               subject: <Subject of the email notification sent for potentially fraudulent 3PID unbinds> |               subject: <Subject of the email notification sent for 3PID unbinds> | ||||||
|               body: |               body: | ||||||
|                 text: <Path to file containing the raw text part of the email. Do not set to not use one> |                 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> |                 html: <Path to file containing the raw text part of the email. Do not set to not use one> | ||||||
|   | |||||||
| @@ -1,77 +1,113 @@ | |||||||
| # Notifications: Generate from templates | # Notifications: Template generator | ||||||
| To create notification content, you can use the `template` generator if supported for the 3PID medium which will read | Most of the Identity actions will trigger a notification of some kind, informing the user of some confirmation, next step | ||||||
| content from configured files. | or just informing them about the current state of things. | ||||||
|  |  | ||||||
| Placeholders can be integrated into the templates to dynamically populate such content with relevant information like | Those notifications are by default generated from templates and by replacing placeholder tokens in them with the relevant | ||||||
| the 3PID that was requested, the domain of your Identity server, etc. | values of the notification. It is possible to customize the value of some placeholders, making easy to set values in the builtin templates, and/or | ||||||
|  | provide your own custom templates. | ||||||
|  |  | ||||||
| Templates can be configured for each event that would send a notification to the end user. Events share a set of common | Templates for the following events/actions are available: | ||||||
| placeholders and also have their own individual set of placeholders. | - [3PID invite](../../features/identity.md) | ||||||
|  | - [3PID session: validation](../session/session.md) | ||||||
|  | - [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 | ||||||
|  | All placeholders **MUST** be surrounded with `%` in the template. Per example, the `DOMAIN` placeholder would become | ||||||
|  | `%DOMAIN%` within the template. This ensures replacement doesn't happen on non-placeholder strings. | ||||||
|  |  | ||||||
|  | ### 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_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_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: | ||||||
|  |  | ||||||
|  | | Placeholder        | Purpose                                                                              | | ||||||
|  | |--------------------|--------------------------------------------------------------------------------------| | ||||||
|  | | `VALIDATION_LINK`  | URL, including token, to validate the 3PID session.                                  | | ||||||
|  | | `VALIDATION_TOKEN` | The token needed to validate the session, in case the user cannot use the link.      | | ||||||
|  | | `NEXT_URL`         | URL to redirect to after the sessions has been validated.                            | | ||||||
|  |  | ||||||
|  | ## Templates | ||||||
|  | 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 | ||||||
|  | version. Be sure to view the repo at the current tag. | ||||||
|  |  | ||||||
| ## Configuration | ## Configuration | ||||||
|  | All configuration is specific to [3PID mediums](https://matrix.org/docs/spec/appendices.html#pid-types) and happen | ||||||
|  | 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`: 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. | ||||||
|  |  | ||||||
|  | The `placeholder` map supports the following keys, mapped to their respective template placeholders: | ||||||
|  | - `REGISTER_URL` | ||||||
|  |  | ||||||
|  | ### Example | ||||||
|  | #### Simple | ||||||
|  | ```yaml | ||||||
|  | threepid: | ||||||
|  |   medium: | ||||||
|  |     email: | ||||||
|  |       generators: | ||||||
|  |         template: | ||||||
|  |           placeholder: | ||||||
|  |             REGISTER_URL: 'https://matrix-client.example.org' | ||||||
|  | ``` | ||||||
|  | In this configuration, the builtin templates are used and a static value for the `REGISTER_URL` is set, allowing to point | ||||||
|  | a newly invited user to a webapp allowing the creation of its account on the server. | ||||||
|  |  | ||||||
|  | #### Advanced | ||||||
| To configure paths to the various templates: | To configure paths to the various templates: | ||||||
| ```yaml | ```yaml | ||||||
| threepid: | threepid: | ||||||
|   medium: |   medium: | ||||||
|     <YOUR 3PID MEDIUM HERE>: |     email: | ||||||
|       generators: |       generators: | ||||||
|         template: |         template: | ||||||
|           invite: '/path/to/invite-template.eml' |           invite: '/path/to/invite-template.eml' | ||||||
|           session: |           session: | ||||||
|             validation: |             validation: '/path/to/validate-template.eml' | ||||||
|               local: '/path/to/validate-local-template.eml' |  | ||||||
|               remote: '/path/to/validate-remote-template.eml' |  | ||||||
|             unbind: |             unbind: | ||||||
|               frandulent: '/path/to/unbind-fraudulent-template.eml' |               notification: '/path/to/unbind-notification-template.eml' | ||||||
|           generic: |           generic: | ||||||
|             matrixId: '/path/to/mxid-invite-template.eml' |             matrixId: '/path/to/mxid-invite-template.eml' | ||||||
|  |           placeholder: | ||||||
|  |             REGISTER_URL: 'https://matrix-client.example.org' | ||||||
| ``` | ``` | ||||||
| The `template` generator is usually the default, so no further configuration is needed. | In this configuration, a custom template is used for each event and a static value for the `REGISTER_URL` is set. | ||||||
|  |  | ||||||
| ##  Global placeholders |  | ||||||
| | 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                                | |  | ||||||
|  |  | ||||||
| ## Events |  | ||||||
| ### Room invitation |  | ||||||
| This template is used when someone is invited into a room using an email address which has no known bind to a Matrix ID. |  | ||||||
| #### 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 | |  | ||||||
|  |  | ||||||
| ### Local validation of 3PID Session |  | ||||||
| This template is used when to user which added their 3PID address to their profile/settings and the session policy |  | ||||||
| allows at least local sessions.   |  | ||||||
|  |  | ||||||
| #### Placeholders |  | ||||||
| | Placeholder          | Purpose                                                                              | |  | ||||||
| |----------------------|--------------------------------------------------------------------------------------| |  | ||||||
| | `%VALIDATION_LINK%`  | URL, including token, to validate the 3PID session.                                  | |  | ||||||
| | `%VALIDATION_TOKEN%` | The token needed to validate the local session, in case the user cannot use the link | |  | ||||||
|  |  | ||||||
| ### Remote validation of 3PID Session |  | ||||||
| This template is used when to user which added their 3PID address to their profile/settings and the session policy only |  | ||||||
| allows remote sessions. |  | ||||||
|  |  | ||||||
| **NOTE:** 3PID session always require local validation of a token, even if a remote session is enforced.   |  | ||||||
| One cannot bind a Matrix ID to the session until both local and remote sessions have been validated. |  | ||||||
|  |  | ||||||
| #### Placeholders |  | ||||||
| | Placeholder          | Purpose                                                | |  | ||||||
| |----------------------|--------------------------------------------------------| |  | ||||||
| | `%VALIDATION_TOKEN%` | The token needed to validate the session               | |  | ||||||
| | `%NEXT_URL%`         | URL to continue with remote validation of the session. | |  | ||||||
|   | |||||||
| @@ -26,6 +26,14 @@ Two configuration keys are available that accept paths to HTML templates: | |||||||
| - `success` | - `success` | ||||||
| - `failure` | - `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 | ## Placeholders | ||||||
| ### Success | ### Success | ||||||
| No object/placeholder are currently available. | No object/placeholder are currently available. | ||||||
|   | |||||||
| @@ -30,11 +30,11 @@ by a 3PID, allowing it to be resolved to a Matrix ID. | |||||||
|  |  | ||||||
| ## Restrictions | ## Restrictions | ||||||
| ### Bindings | ### 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. | 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 | 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 | 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!**   | 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 | If a federated lookup was performed, Identity servers would try to find the 3PID bind at the `gmail.com` server, and | ||||||
| not `example.org`. | 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.  | Sadly, there is currently no mechanism to make this work for phone numbers.  | ||||||
|  |  | ||||||
| ## Notifications | ## 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 | 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. | 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. | - 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). | - Connector which actually send the notification (e.g. SMTP for email). | ||||||
|  |  | ||||||
| @@ -103,8 +103,8 @@ session: | |||||||
|     validation: |     validation: | ||||||
|       enabled: true |       enabled: true | ||||||
|     unbind: |     unbind: | ||||||
|       fraudulent: |       notifications: true | ||||||
|         sendWarning: true |       enabled: true | ||||||
|  |  | ||||||
| # DO NOT COPY/PASTE AS-IS IN YOUR CONFIGURATION | # DO NOT COPY/PASTE AS-IS IN YOUR CONFIGURATION | ||||||
| # CONFIGURATION EXAMPLE | # 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.   | `unbind` controls warning notifications for 3PID removal. Setting `notifications` for `unbind` to false will prevent unbind emails from sending. | ||||||
| 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). |  | ||||||
|  |  | ||||||
| ### Web views | ### Web views | ||||||
| Once a user click on a validation link, it is taken to the Identity Server validation page where the token is submitted.   | 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 | 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. | 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 | This would be used if ma1sd 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 | [REST password provider](https://github.com/ma1uta/matrix-synapse-rest-password-provider), where 3PID mappings would be | ||||||
| auto-populated. | auto-populated. | ||||||
|  |  | ||||||
| Use the following values to enable this mode: | Use the following values to enable this mode: | ||||||
|   | |||||||
							
								
								
									
										58
									
								
								docs/troubleshooting.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										58
									
								
								docs/troubleshooting.md
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,58 @@ | |||||||
|  | # Troubleshooting | ||||||
|  | - [Purpose](#purpose) | ||||||
|  | - [Logs](#logs) | ||||||
|  |   - [Locations](#locations) | ||||||
|  |   - [Reading Them](#reading-them) | ||||||
|  |   - [Common issues](#common-issues) | ||||||
|  | - [Submit an issue](#submit-an-issue) | ||||||
|  |  | ||||||
|  | ## Purpose | ||||||
|  | This document describes basic troubleshooting steps for ma1sd. | ||||||
|  |  | ||||||
|  | ## Logs | ||||||
|  | ### Locations | ||||||
|  | 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`.   | ||||||
|  | If you use the [Docker image](install/docker.md), this goes to the container logs.   | ||||||
|  |  | ||||||
|  | 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 `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 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 | ||||||
|  | always be included in any report. They also tend to be very specific about the issue at hand. | ||||||
|  |  | ||||||
|  | Example of a stacktrace: | ||||||
|  | ``` | ||||||
|  | Exception in thread "main" java.lang.NullPointerException | ||||||
|  |         at com.example.myproject.Book.getTitle(Book.java:16) | ||||||
|  |         at com.example.myproject.Author.getBookTitles(Author.java:25) | ||||||
|  |         at com.example.myproject.Bootstrap.main(Bootstrap.java:14) | ||||||
|  | ``` | ||||||
|  |  | ||||||
|  | ### Common issues | ||||||
|  | #### Internal Server Error | ||||||
|  | `Contact your administrator with reference Transaction #123456789` | ||||||
|  |  | ||||||
|  | This is a generic message produced in case of an unknown error. The transaction reference allows to easily find | ||||||
|  | the location in the logs to look for an error. | ||||||
|  |  | ||||||
|  | **IMPORTANT:** That line alone does not tell you anything about the error. You'll need the log lines before and after, | ||||||
|  | usually including a stacktrace, to know what happened. Please take the time to read the surround output to get | ||||||
|  | context about the issue at hand. | ||||||
|  |  | ||||||
|  | ## Submit an issue | ||||||
|  | In case the logs do not allow you to understand the issue at hand, please submit clean and complete logs | ||||||
|  | as explained [here](#reading-them) in a new issue on the repository, or [get in touch](../README.md#contact). | ||||||
							
								
								
									
										
											BIN
										
									
								
								gradle/wrapper/gradle-wrapper.jar
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										
											BIN
										
									
								
								gradle/wrapper/gradle-wrapper.jar
									
									
									
									
										vendored
									
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										6
									
								
								gradle/wrapper/gradle-wrapper.properties
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										6
									
								
								gradle/wrapper/gradle-wrapper.properties
									
									
									
									
										vendored
									
									
								
							| @@ -1,6 +1,6 @@ | |||||||
| #Fri Aug 11 17:19:02 CEST 2017 | #Thu Jul 04 22:47:59 MSK 2019 | ||||||
|  | distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.4-all.zip | ||||||
| distributionBase=GRADLE_USER_HOME | distributionBase=GRADLE_USER_HOME | ||||||
| distributionPath=wrapper/dists | distributionPath=wrapper/dists | ||||||
| zipStoreBase=GRADLE_USER_HOME |  | ||||||
| zipStorePath=wrapper/dists | zipStorePath=wrapper/dists | ||||||
| distributionUrl=https\://services.gradle.org/distributions/gradle-4.0.2-bin.zip | zipStoreBase=GRADLE_USER_HOME | ||||||
|   | |||||||
							
								
								
									
										18
									
								
								gradlew
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										18
									
								
								gradlew
									
									
									
									
										vendored
									
									
								
							| @@ -1,5 +1,21 @@ | |||||||
| #!/usr/bin/env sh | #!/usr/bin/env sh | ||||||
|  |  | ||||||
|  | # | ||||||
|  | # Copyright 2015 the original author or 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 | ||||||
|  | # | ||||||
|  | # Unless required by applicable law or agreed to in writing, software | ||||||
|  | # distributed under the License is distributed on an "AS IS" BASIS, | ||||||
|  | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||||
|  | # See the License for the specific language governing permissions and | ||||||
|  | # limitations under the License. | ||||||
|  | # | ||||||
|  |  | ||||||
| ############################################################################## | ############################################################################## | ||||||
| ## | ## | ||||||
| ##  Gradle start up script for UN*X | ##  Gradle start up script for UN*X | ||||||
| @@ -28,7 +44,7 @@ APP_NAME="Gradle" | |||||||
| APP_BASE_NAME=`basename "$0"` | 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. | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. | ||||||
| DEFAULT_JVM_OPTS="" | DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' | ||||||
|  |  | ||||||
| # Use the maximum available, or set MAX_FD != -1 to use that value. | # Use the maximum available, or set MAX_FD != -1 to use that value. | ||||||
| MAX_FD="maximum" | MAX_FD="maximum" | ||||||
|   | |||||||
							
								
								
									
										184
									
								
								gradlew.bat
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										184
									
								
								gradlew.bat
									
									
									
									
										vendored
									
									
								
							| @@ -1,84 +1,100 @@ | |||||||
| @if "%DEBUG%" == "" @echo off | @rem | ||||||
| @rem ########################################################################## | @rem Copyright 2015 the original author or authors. | ||||||
| @rem | @rem | ||||||
| @rem  Gradle startup script for Windows | @rem Licensed under the Apache License, Version 2.0 (the "License"); | ||||||
| @rem | @rem you may not use this file except in compliance with the License. | ||||||
| @rem ########################################################################## | @rem You may obtain a copy of the License at | ||||||
|  | @rem | ||||||
| @rem Set local scope for the variables with windows NT shell | @rem      http://www.apache.org/licenses/LICENSE-2.0 | ||||||
| if "%OS%"=="Windows_NT" setlocal | @rem | ||||||
|  | @rem Unless required by applicable law or agreed to in writing, software | ||||||
| set DIRNAME=%~dp0 | @rem distributed under the License is distributed on an "AS IS" BASIS, | ||||||
| if "%DIRNAME%" == "" set DIRNAME=. | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||||
| set APP_BASE_NAME=%~n0 | @rem See the License for the specific language governing permissions and | ||||||
| set APP_HOME=%DIRNAME% | @rem limitations under the License. | ||||||
|  | @rem | ||||||
| @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= | @if "%DEBUG%" == "" @echo off | ||||||
|  | @rem ########################################################################## | ||||||
| @rem Find java.exe | @rem | ||||||
| if defined JAVA_HOME goto findJavaFromJavaHome | @rem  Gradle startup script for Windows | ||||||
|  | @rem | ||||||
| set JAVA_EXE=java.exe | @rem ########################################################################## | ||||||
| %JAVA_EXE% -version >NUL 2>&1 |  | ||||||
| if "%ERRORLEVEL%" == "0" goto init | @rem Set local scope for the variables with windows NT shell | ||||||
|  | if "%OS%"=="Windows_NT" setlocal | ||||||
| echo. |  | ||||||
| echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. | set DIRNAME=%~dp0 | ||||||
| echo. | if "%DIRNAME%" == "" set DIRNAME=. | ||||||
| echo Please set the JAVA_HOME variable in your environment to match the | set APP_BASE_NAME=%~n0 | ||||||
| echo location of your Java installation. | set APP_HOME=%DIRNAME% | ||||||
|  |  | ||||||
| goto fail | @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" | ||||||
| :findJavaFromJavaHome |  | ||||||
| set JAVA_HOME=%JAVA_HOME:"=% | @rem Find java.exe | ||||||
| set JAVA_EXE=%JAVA_HOME%/bin/java.exe | if defined JAVA_HOME goto findJavaFromJavaHome | ||||||
|  |  | ||||||
| if exist "%JAVA_EXE%" goto init | set JAVA_EXE=java.exe | ||||||
|  | %JAVA_EXE% -version >NUL 2>&1 | ||||||
| echo. | if "%ERRORLEVEL%" == "0" goto init | ||||||
| echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% |  | ||||||
| echo. | echo. | ||||||
| echo Please set the JAVA_HOME variable in your environment to match the | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. | ||||||
| echo location of your Java installation. | echo. | ||||||
|  | echo Please set the JAVA_HOME variable in your environment to match the | ||||||
| goto fail | echo location of your Java installation. | ||||||
|  |  | ||||||
| :init | goto fail | ||||||
| @rem Get command-line arguments, handling Windows variants |  | ||||||
|  | :findJavaFromJavaHome | ||||||
| if not "%OS%" == "Windows_NT" goto win9xME_args | set JAVA_HOME=%JAVA_HOME:"=% | ||||||
|  | set JAVA_EXE=%JAVA_HOME%/bin/java.exe | ||||||
| :win9xME_args |  | ||||||
| @rem Slurp the command line arguments. | if exist "%JAVA_EXE%" goto init | ||||||
| set CMD_LINE_ARGS= |  | ||||||
| set _SKIP=2 | echo. | ||||||
|  | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% | ||||||
| :win9xME_args_slurp | echo. | ||||||
| if "x%~1" == "x" goto execute | echo Please set the JAVA_HOME variable in your environment to match the | ||||||
|  | echo location of your Java installation. | ||||||
| set CMD_LINE_ARGS=%* |  | ||||||
|  | goto fail | ||||||
| :execute |  | ||||||
| @rem Setup the command line | :init | ||||||
|  | @rem Get command-line arguments, handling Windows variants | ||||||
| set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar |  | ||||||
|  | if not "%OS%" == "Windows_NT" goto win9xME_args | ||||||
| @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% | :win9xME_args | ||||||
|  | @rem Slurp the command line arguments. | ||||||
| :end | set CMD_LINE_ARGS= | ||||||
| @rem End local scope for the variables with windows NT shell | set _SKIP=2 | ||||||
| if "%ERRORLEVEL%"=="0" goto mainEnd |  | ||||||
|  | :win9xME_args_slurp | ||||||
| :fail | if "x%~1" == "x" goto execute | ||||||
| rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of |  | ||||||
| rem the _cmd.exe /c_ return code! | set CMD_LINE_ARGS=%* | ||||||
| if  not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 |  | ||||||
| exit /b 1 | :execute | ||||||
|  | @rem Setup the command line | ||||||
| :mainEnd |  | ||||||
| if "%OS%"=="Windows_NT" endlocal | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar | ||||||
|  |  | ||||||
| :omega | @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 | ||||||
|   | |||||||
							
								
								
									
										111
									
								
								ma1sd.example.yaml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										111
									
								
								ma1sd.example.yaml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,111 @@ | |||||||
|  | # 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: '' | ||||||
|  |  | ||||||
|  |  | ||||||
|  | ################ | ||||||
|  | # 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/ma1sd/keys is a possible value | ||||||
|  | # For production, recommended location shall be one of the following: | ||||||
|  | #   - /var/lib/ma1sd/keys | ||||||
|  | #   - /var/opt/ma1sd/keys | ||||||
|  | #   - /var/local/ma1sd/keys | ||||||
|  | # | ||||||
|  | key: | ||||||
|  |   path: '' | ||||||
|  |  | ||||||
|  |  | ||||||
|  | # Path to the SQLite DB file for ma1sd internal storage | ||||||
|  | # /!\ THIS MUST **NOT** BE YOUR HOMESERVER DATABASE /!\ | ||||||
|  | # | ||||||
|  | # Examples: | ||||||
|  | #  - /var/opt/ma1sd/store.db | ||||||
|  | #  - /var/local/ma1sd/store.db | ||||||
|  | #  - /var/lib/ma1sd/store.db | ||||||
|  | # | ||||||
|  | storage: | ||||||
|  |   provider: | ||||||
|  |     sqlite: | ||||||
|  |       database: '/path/to/ma1sd.db' | ||||||
|  |  | ||||||
|  |  | ||||||
|  | ################### | ||||||
|  | # 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" | ||||||
| @@ -1,116 +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 |  | ||||||
|  |  | ||||||
| ####################### |  | ||||||
| # 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. |  | ||||||
| matrix: |  | ||||||
|   domain: '' |  | ||||||
|  |  | ||||||
|  |  | ||||||
| ################ |  | ||||||
| # Signing keys # |  | ||||||
| ################ |  | ||||||
| # Absolute path for the Identity Server signing key. |  | ||||||
| # This is **NOT** your homeserver key. |  | ||||||
| # The signing key is auto-generated during execution time if not present. |  | ||||||
| # |  | ||||||
| # During testing, /var/tmp/mxisd.key is a possible value |  | ||||||
| # For production, recommended location shall be one of the following: |  | ||||||
| #   - /var/opt/mxisd/sign.key |  | ||||||
| #   - /var/local/mxisd/sign.key |  | ||||||
| #   - /var/lib/mxisd/sign.key |  | ||||||
| # |  | ||||||
| key: |  | ||||||
|   path: '' |  | ||||||
|  |  | ||||||
|  |  | ||||||
| # Path to the SQLite DB file for mxisd internal storage |  | ||||||
| # |  | ||||||
| # Examples: |  | ||||||
| #  - /var/opt/mxisd/mxisd.db |  | ||||||
| #  - /var/local/mxisd/mxisd.db |  | ||||||
| #  - /var/lib/mxisd/mxisd.db |  | ||||||
| # |  | ||||||
| storage: |  | ||||||
|   provider: |  | ||||||
|     sqlite: |  | ||||||
|       database: '/path/to/mxisd.db' |  | ||||||
|  |  | ||||||
|  |  | ||||||
| #################### |  | ||||||
| # Fallback servers # |  | ||||||
| #################### |  | ||||||
| # |  | ||||||
| # Root/Central servers to be used as final fallback when performing lookups. |  | ||||||
| # By default, for privacy reasons, matrix.org servers are not enabled. |  | ||||||
| # See the following issue: https://github.com/kamax-matrix/mxisd/issues/76 |  | ||||||
| # |  | ||||||
| # If you would like to use them and trade away your privacy for convenience, uncomment the following option: |  | ||||||
| # |  | ||||||
| #forward: |  | ||||||
| #  servers: ['matrix-org'] |  | ||||||
|  |  | ||||||
|  |  | ||||||
| ################ |  | ||||||
| # LDAP Backend # |  | ||||||
| ################ |  | ||||||
| # 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 |  | ||||||
|  |  | ||||||
|  |  | ||||||
| ############### |  | ||||||
| # SQL Backend # |  | ||||||
| ############### |  | ||||||
| # If you would like to integrate with a MySQL/MariaDB/PostgreQL/SQLite DB, |  | ||||||
| # see https://github.com/kamax-matrix/mxisd/blob/master/docs/stores/sql.md |  | ||||||
|  |  | ||||||
|  |  | ||||||
| ################ |  | ||||||
| # REST Backend # |  | ||||||
| ################ |  | ||||||
| # If you would like to integrate with an existing web service/webapp, |  | ||||||
| # see https://github.com/kamax-matrix/mxisd/blob/master/docs/stores/rest.md |  | ||||||
|  |  | ||||||
|  |  | ||||||
| ################################################# |  | ||||||
| # Notifications for invites/addition to profile # |  | ||||||
| ################################################# |  | ||||||
| # If you would like to change the content, |  | ||||||
| # see https://github.com/kamax-matrix/mxisd/blob/master/docs/threepids/notification/template-generator.md |  | ||||||
| # |  | ||||||
| #### E-mail invite sender |  | ||||||
| threepid: |  | ||||||
|   medium: |  | ||||||
|     email: |  | ||||||
|       identity: |  | ||||||
|         # The e-mail to send as. |  | ||||||
|         from: "matrix-identity@example.org" |  | ||||||
|  |  | ||||||
|       connectors: |  | ||||||
|         smtp: |  | ||||||
|           # SMTP host |  | ||||||
|           host: "smtp.example.org" |  | ||||||
|  |  | ||||||
|           # SMTP port |  | ||||||
|           port: 587 |  | ||||||
|  |  | ||||||
|           # TLS mode for the connection. |  | ||||||
|           # |  | ||||||
|           # Possible values: |  | ||||||
|           #  0    Disable TLS entirely |  | ||||||
|           #  1    Enable TLS if supported by server (default) |  | ||||||
|           #  2    Force TLS and fail if not available |  | ||||||
|           # |  | ||||||
|           tls: 1 |  | ||||||
|  |  | ||||||
|           # Login for SMTP |  | ||||||
|           login: "matrix-identity@example.org" |  | ||||||
|  |  | ||||||
|           # Password for the account |  | ||||||
|           password: "ThePassword" |  | ||||||
| @@ -1,7 +1,9 @@ | |||||||
| Package: mxisd | Package: ma1sd | ||||||
| Maintainer: Kamax.io <foss@kamax.io> | Maintainer: ma1uta <sablintolya@gmail.com> | ||||||
| Homepage: https://github.com/kamax-matrix/mxisd | Homepage: https://github.com/ma1uta/ma1sd | ||||||
| Description: Federated Matrix Identity Server | Description: Federated Matrix Identity Server | ||||||
| Architecture: all | Architecture: all | ||||||
| Depends: openjdk-8-jre | openjdk-8-jre-headless | openjdk-8-jdk | openjdk-8-jdk-headless | Section: net | ||||||
|  | Priority: optional | ||||||
|  | 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 | Version: 0 | ||||||
|   | |||||||
| @@ -1,13 +1,19 @@ | |||||||
| #!/bin/bash -e | #!/bin/bash -e | ||||||
|  |  | ||||||
| # Add service account | # Add service account | ||||||
| useradd -r mxisd || true | useradd -r ma1sd || true | ||||||
|  |  | ||||||
| # Set permissions for data directory | # Set permissions for data directory | ||||||
| chown -R mxisd:mxisd %DEB_DATA_DIR% | chown -R ma1sd:ma1sd %DEB_DATA_DIR% | ||||||
|  |  | ||||||
| # Create symlink to mxisd run script | # Create symlink to ma1sd run script | ||||||
| ln -sfT /usr/lib/mxisd/mxisd /usr/bin/mxisd | ln -sfT /usr/lib/ma1sd/ma1sd /usr/bin/ma1sd | ||||||
|  |  | ||||||
| # Enable systemd service | # Enable systemd service | ||||||
| systemctl enable mxisd.service | systemctl enable ma1sd.service | ||||||
|  |  | ||||||
|  | # If we already have a config file setup, we attempt to run ma1sd automatically | ||||||
|  | # Specifically targeted at upgrades where the service needs to be restarted | ||||||
|  | if [ -f "%DEB_CONF_FILE%" ]; then | ||||||
|  |     systemctl restart ma1sd.service | ||||||
|  | fi | ||||||
|   | |||||||
| @@ -1,10 +1,10 @@ | |||||||
| #!/bin/bash | #!/bin/bash | ||||||
|  |  | ||||||
| # Stop running instance if needed | # Stop running instance if needed | ||||||
| systemctl stop mxisd.service | systemctl stop ma1sd.service | ||||||
|  |  | ||||||
| # Disable service if exists | # Disable service if exists | ||||||
| systemctl disable mxisd.service | systemctl disable ma1sd.service | ||||||
|  |  | ||||||
| # remove symlink | # remove symlink | ||||||
| rm /usr/bin/mxisd | rm /usr/bin/ma1sd | ||||||
|   | |||||||
| @@ -27,8 +27,8 @@ if [[ -n "$CONF_FILE_PATH" ]] && [ ! -f "$CONF_FILE_PATH" ]; then | |||||||
|         echo >> "$CONF_FILE_PATH" |         echo >> "$CONF_FILE_PATH" | ||||||
|     fi |     fi | ||||||
|  |  | ||||||
|     echo "Starting mxisd..." |     echo "Starting ma1sd..." | ||||||
|     echo |     echo | ||||||
| fi | fi | ||||||
|  |  | ||||||
| exec java -jar /app/mxisd.jar -c /etc/mxisd/mxisd.yaml | exec java -jar /app/ma1sd.jar -c /etc/ma1sd/ma1sd.yaml | ||||||
|   | |||||||
| @@ -1,27 +1,26 @@ | |||||||
| /* | /* | ||||||
| * The MIT License |  * The MIT License | ||||||
| * |  * | ||||||
| * Copyright (c) 2013 Edin Dazdarevic (edin.dazdarevic@gmail.com) |  * Copyright (c) 2013 Edin Dazdarevic (edin.dazdarevic@gmail.com) | ||||||
|  |  | ||||||
| * Permission is hereby granted, free of charge, to any person obtaining a copy |  * Permission is hereby granted, free of charge, to any person obtaining a copy | ||||||
| * of this software and associated documentation files (the "Software"), to deal |  * of this software and associated documentation files (the "Software"), to deal | ||||||
| * in the Software without restriction, including without limitation the rights |  * in the Software without restriction, including without limitation the rights | ||||||
| * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||||||
| * copies of the Software, and to permit persons to whom the Software is |  * copies of the Software, and to permit persons to whom the Software is | ||||||
| * furnished to do so, subject to the following conditions: |  * furnished to do so, subject to the following conditions: | ||||||
|  |  | ||||||
| * The above copyright notice and this permission notice shall be included in |  * The above copyright notice and this permission notice shall be included in | ||||||
| * all copies or substantial portions of the Software. |  * all copies or substantial portions of the Software. | ||||||
|  |  | ||||||
| * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||||
| * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||||
| * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||||||
| * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||||||
| * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||||||
| * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||||||
| * THE SOFTWARE. |  * THE SOFTWARE. | ||||||
| * |  */ | ||||||
| * */ |  | ||||||
|  |  | ||||||
| package edazdarevic.commons.net; | package edazdarevic.commons.net; | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										33
									
								
								src/main/java/io/kamax/matrix/MalformedEventException.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								src/main/java/io/kamax/matrix/MalformedEventException.java
									
									
									
									
									
										Normal 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"); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  | } | ||||||
							
								
								
									
										44
									
								
								src/main/java/io/kamax/matrix/MatrixErrorInfo.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										44
									
								
								src/main/java/io/kamax/matrix/MatrixErrorInfo.java
									
									
									
									
									
										Normal 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; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  | } | ||||||
							
								
								
									
										48
									
								
								src/main/java/io/kamax/matrix/MatrixException.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										48
									
								
								src/main/java/io/kamax/matrix/MatrixException.java
									
									
									
									
									
										Normal 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; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  | } | ||||||
							
								
								
									
										170
									
								
								src/main/java/io/kamax/matrix/MatrixID.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										170
									
								
								src/main/java/io/kamax/matrix/MatrixID.java
									
									
									
									
									
										Normal 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(); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  | } | ||||||
							
								
								
									
										93
									
								
								src/main/java/io/kamax/matrix/MatrixIdCodec.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										93
									
								
								src/main/java/io/kamax/matrix/MatrixIdCodec.java
									
									
									
									
									
										Normal 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(); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  | } | ||||||
							
								
								
									
										104
									
								
								src/main/java/io/kamax/matrix/MatrixPath.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										104
									
								
								src/main/java/io/kamax/matrix/MatrixPath.java
									
									
									
									
									
										Normal 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("r0"); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     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()); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  | } | ||||||
							
								
								
									
										61
									
								
								src/main/java/io/kamax/matrix/ThreePid.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										61
									
								
								src/main/java/io/kamax/matrix/ThreePid.java
									
									
									
									
									
										Normal 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; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     @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; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  | } | ||||||
							
								
								
									
										61
									
								
								src/main/java/io/kamax/matrix/ThreePidMapping.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										61
									
								
								src/main/java/io/kamax/matrix/ThreePidMapping.java
									
									
									
									
									
										Normal 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; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  | } | ||||||
							
								
								
									
										46
									
								
								src/main/java/io/kamax/matrix/ThreePidMedium.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										46
									
								
								src/main/java/io/kamax/matrix/ThreePidMedium.java
									
									
									
									
									
										Normal 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); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  | } | ||||||
							
								
								
									
										41
									
								
								src/main/java/io/kamax/matrix/_MatrixContent.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								src/main/java/io/kamax/matrix/_MatrixContent.java
									
									
									
									
									
										Normal 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(); | ||||||
|  |  | ||||||
|  | } | ||||||
							
								
								
									
										55
									
								
								src/main/java/io/kamax/matrix/_MatrixID.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										55
									
								
								src/main/java/io/kamax/matrix/_MatrixID.java
									
									
									
									
									
										Normal 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(); | ||||||
|  |  | ||||||
|  | } | ||||||
							
								
								
									
										31
									
								
								src/main/java/io/kamax/matrix/_MatrixUser.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								src/main/java/io/kamax/matrix/_MatrixUser.java
									
									
									
									
									
										Normal 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(); | ||||||
|  |  | ||||||
|  | } | ||||||
							
								
								
									
										42
									
								
								src/main/java/io/kamax/matrix/_MatrixUserProfile.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										42
									
								
								src/main/java/io/kamax/matrix/_MatrixUserProfile.java
									
									
									
									
									
										Normal 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(); | ||||||
|  |  | ||||||
|  | } | ||||||
							
								
								
									
										29
									
								
								src/main/java/io/kamax/matrix/_ThreePid.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								src/main/java/io/kamax/matrix/_ThreePid.java
									
									
									
									
									
										Normal 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(); | ||||||
|  |  | ||||||
|  | } | ||||||
							
								
								
									
										29
									
								
								src/main/java/io/kamax/matrix/_ThreePidMapping.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								src/main/java/io/kamax/matrix/_ThreePidMapping.java
									
									
									
									
									
										Normal 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(); | ||||||
|  |  | ||||||
|  | } | ||||||
							
								
								
									
										409
									
								
								src/main/java/io/kamax/matrix/client/AMatrixHttpClient.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										409
									
								
								src/main/java/io/kamax/matrix/client/AMatrixHttpClient.java
									
									
									
									
									
										Normal 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", "r0" }; | ||||||
|  |         segments = ArrayUtils.addAll(base, segments); | ||||||
|  |         return getPathBuilder(segments); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     protected HttpUrl.Builder getMediaPathBuilder(String... segments) { | ||||||
|  |         String[] base = { "media", "r0" }; | ||||||
|  |         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(); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  | } | ||||||
							
								
								
									
										154
									
								
								src/main/java/io/kamax/matrix/client/MatrixClientContext.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										154
									
								
								src/main/java/io/kamax/matrix/client/MatrixClientContext.java
									
									
									
									
									
										Normal 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; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  | } | ||||||
| @@ -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; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  | } | ||||||
| @@ -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); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  | } | ||||||
| @@ -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); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  | } | ||||||
							
								
								
									
										133
									
								
								src/main/java/io/kamax/matrix/client/MatrixHttpContent.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										133
									
								
								src/main/java/io/kamax/matrix/client/MatrixHttpContent.java
									
									
									
									
									
										Normal 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(); | ||||||
|  |         }); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  | } | ||||||
| @@ -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; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  | } | ||||||
							
								
								
									
										93
									
								
								src/main/java/io/kamax/matrix/client/MatrixHttpPushRule.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										93
									
								
								src/main/java/io/kamax/matrix/client/MatrixHttpPushRule.java
									
									
									
									
									
										Normal 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))))); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  | } | ||||||
							
								
								
									
										50
									
								
								src/main/java/io/kamax/matrix/client/MatrixHttpRequest.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										50
									
								
								src/main/java/io/kamax/matrix/client/MatrixHttpRequest.java
									
									
									
									
									
										Normal 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; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  | } | ||||||
							
								
								
									
										440
									
								
								src/main/java/io/kamax/matrix/client/MatrixHttpRoom.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										440
									
								
								src/main/java/io/kamax/matrix/client/MatrixHttpRoom.java
									
									
									
									
									
										Normal 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()); | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										125
									
								
								src/main/java/io/kamax/matrix/client/MatrixHttpUser.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										125
									
								
								src/main/java/io/kamax/matrix/client/MatrixHttpUser.java
									
									
									
									
									
										Normal 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))); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  | } | ||||||
| @@ -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; | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										45
									
								
								src/main/java/io/kamax/matrix/client/PresenceStatus.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										45
									
								
								src/main/java/io/kamax/matrix/client/PresenceStatus.java
									
									
									
									
									
										Normal 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); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  | } | ||||||
| @@ -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); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  | } | ||||||
| @@ -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(); | ||||||
|  |  | ||||||
|  | } | ||||||
| @@ -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(); | ||||||
|  |  | ||||||
|  | } | ||||||
							
								
								
									
										158
									
								
								src/main/java/io/kamax/matrix/client/_MatrixClient.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										158
									
								
								src/main/java/io/kamax/matrix/client/_MatrixClient.java
									
									
									
									
									
										Normal 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); | ||||||
|  |  | ||||||
|  | } | ||||||
							
								
								
									
										51
									
								
								src/main/java/io/kamax/matrix/client/_MatrixClientRaw.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										51
									
								
								src/main/java/io/kamax/matrix/client/_MatrixClientRaw.java
									
									
									
									
									
										Normal 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(); | ||||||
|  |  | ||||||
|  | } | ||||||
							
								
								
									
										29
									
								
								src/main/java/io/kamax/matrix/client/_Presence.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								src/main/java/io/kamax/matrix/client/_Presence.java
									
									
									
									
									
										Normal 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(); | ||||||
|  |  | ||||||
|  | } | ||||||
							
								
								
									
										43
									
								
								src/main/java/io/kamax/matrix/client/_PushRule.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										43
									
								
								src/main/java/io/kamax/matrix/client/_PushRule.java
									
									
									
									
									
										Normal 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); | ||||||
|  |  | ||||||
|  | } | ||||||
							
								
								
									
										253
									
								
								src/main/java/io/kamax/matrix/client/_SyncData.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										253
									
								
								src/main/java/io/kamax/matrix/client/_SyncData.java
									
									
									
									
									
										Normal 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(); | ||||||
|  |  | ||||||
|  | } | ||||||
							
								
								
									
										65
									
								
								src/main/java/io/kamax/matrix/client/_SyncOptions.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										65
									
								
								src/main/java/io/kamax/matrix/client/_SyncOptions.java
									
									
									
									
									
										Normal 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(); | ||||||
|  |  | ||||||
|  | } | ||||||
| @@ -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); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  | } | ||||||
| @@ -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); | ||||||
|  |  | ||||||
|  | } | ||||||
| @@ -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"); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  | } | ||||||
| @@ -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); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  | } | ||||||
							
								
								
									
										48
									
								
								src/main/java/io/kamax/matrix/client/regular/Presence.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										48
									
								
								src/main/java/io/kamax/matrix/client/regular/Presence.java
									
									
									
									
									
										Normal 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; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  | } | ||||||
							
								
								
									
										390
									
								
								src/main/java/io/kamax/matrix/client/regular/SyncDataJson.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										390
									
								
								src/main/java/io/kamax/matrix/client/regular/SyncDataJson.java
									
									
									
									
									
										Normal 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; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  | } | ||||||
							
								
								
									
										103
									
								
								src/main/java/io/kamax/matrix/client/regular/SyncOptions.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										103
									
								
								src/main/java/io/kamax/matrix/client/regular/SyncOptions.java
									
									
									
									
									
										Normal 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); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  | } | ||||||
							
								
								
									
										36
									
								
								src/main/java/io/kamax/matrix/codec/MxBase64.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								src/main/java/io/kamax/matrix/codec/MxBase64.java
									
									
									
									
									
										Normal 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)); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  | } | ||||||
							
								
								
									
										47
									
								
								src/main/java/io/kamax/matrix/codec/MxSha256.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										47
									
								
								src/main/java/io/kamax/matrix/codec/MxSha256.java
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,47 @@ | |||||||
|  | /* | ||||||
|  |  * 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.security.MessageDigest; | ||||||
|  | import java.security.NoSuchAlgorithmException; | ||||||
|  |  | ||||||
|  | public class MxSha256 { | ||||||
|  |  | ||||||
|  |     private MessageDigest md; | ||||||
|  |  | ||||||
|  |     public MxSha256() { | ||||||
|  |         try { | ||||||
|  |             md = MessageDigest.getInstance("SHA-256"); | ||||||
|  |         } catch (NoSuchAlgorithmException e) { | ||||||
|  |             throw new RuntimeException(e); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public String hash(byte[] data) { | ||||||
|  |         return MxBase64.encode(md.digest(data)); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public String hash(String data) { | ||||||
|  |         return hash(data.getBytes(StandardCharsets.UTF_8)); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  | } | ||||||
							
								
								
									
										80
									
								
								src/main/java/io/kamax/matrix/crypto/KeyFileStore.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										80
									
								
								src/main/java/io/kamax/matrix/crypto/KeyFileStore.java
									
									
									
									
									
										Normal 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); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  | } | ||||||
							
								
								
									
										100
									
								
								src/main/java/io/kamax/matrix/crypto/KeyManager.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										100
									
								
								src/main/java/io/kamax/matrix/crypto/KeyManager.java
									
									
									
									
									
										Normal 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()); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  | } | ||||||
							
								
								
									
										46
									
								
								src/main/java/io/kamax/matrix/crypto/KeyMemoryStore.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										46
									
								
								src/main/java/io/kamax/matrix/crypto/KeyMemoryStore.java
									
									
									
									
									
										Normal 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; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  | } | ||||||
							
								
								
									
										80
									
								
								src/main/java/io/kamax/matrix/crypto/SignatureManager.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										80
									
								
								src/main/java/io/kamax/matrix/crypto/SignatureManager.java
									
									
									
									
									
										Normal 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; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  | } | ||||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user