Compare commits

..

6 Commits

Author SHA1 Message Date
Maxime Dor
3d39ee97dd Add 3PIDs at registration 2018-04-13 03:48:32 +02:00
Maxime Dor
94d60b6fc9 Auto-generate username 2018-04-13 03:48:32 +02:00
Maxime Dor
ac9881fa4b Fix login 2018-04-13 03:48:32 +02:00
Maxime Dor
547cafdd13 PoC of registration with Google 3PID 2018-04-13 03:48:32 +02:00
Maxime Dor
0da1af9869 registration handling skeleton 2018-04-13 03:48:32 +02:00
Maxime Dor
268df533f5 Research with Google auth integration 2018-04-13 03:48:32 +02:00
88 changed files with 844 additions and 1864 deletions

View File

@@ -1,6 +1,6 @@
mxisd - Federated Matrix Identity Server mxisd - Federated Matrix Identity Server
---------------------------------------- ----------------------------------------
![Travis-CI build status](https://travis-ci.org/kamax-matrix/mxisd.svg?branch=master) ![Travis-CI build status](https://travis-ci.org/kamax-io/mxisd.svg?branch=master)
- [Overview](#overview) - [Overview](#overview)
- [Features](#features) - [Features](#features)

View File

@@ -1,6 +1,6 @@
# Sample configuration file explaining the minimum required keys to be set to run mxisd # 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 # For a complete list of options, see https://github.com/kamax-io/mxisd
####################### #######################
# Matrix config items # # Matrix config items #
@@ -47,45 +47,30 @@ key.path: ''
storage.provider.sqlite.database: '/path/to/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 anymore.
# 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 # # LDAP Backend #
################ ################
# If you would like to integrate with your AD/Samba/LDAP server, # If you would like to integrate with your AD/Samba/LDAP server,
# see https://github.com/kamax-matrix/mxisd/blob/master/docs/backends/ldap.md # see https://github.com/kamax-io/mxisd/blob/master/docs/backends/ldap.md
############### ###############
# SQL Backend # # SQL Backend #
############### ###############
# If you would like to integrate with a MySQL/MariaDB/PostgreQL/SQLite DB, # If you would like to integrate with a MySQL/MariaDB/PostgreQL/SQLite DB,
# see https://github.com/kamax-matrix/mxisd/blob/master/docs/backends/sql.md # see https://github.com/kamax-io/mxisd/blob/master/docs/backends/sql.md
################ ################
# REST Backend # # REST Backend #
################ ################
# If you would like to integrate with an existing web service/webapp, # If you would like to integrate with an existing web service/webapp,
# see https://github.com/kamax-matrix/mxisd/blob/master/docs/backends/rest.md # see https://github.com/kamax-io/mxisd/blob/master/docs/backends/rest.md
################################################# #################################################
# Notifications for invites/addition to profile # # Notifications for invites/addition to profile #
################################################# #################################################
# If you would like to change the content, # If you would like to change the content,
# see https://github.com/kamax-matrix/mxisd/blob/master/docs/threepids/notifications/template-generator.md # see https://github.com/kamax-io/mxisd/blob/master/docs/threepids/notifications/template-generator.md
# #
#### E-mail invite sender #### E-mail invite sender
# #

View File

@@ -1,8 +1,8 @@
/* /*
* mxisd - Matrix Identity Server Daemon * mxisd - Matrix Identity Server Daemon
* Copyright (C) 2017 Kamax Sarl * Copyright (C) 2017 Maxime Dor
* *
* https://www.kamax.io/ * https://max.kamax.io/
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as * it under the terms of the GNU Affero General Public License as
@@ -65,9 +65,9 @@ buildscript {
} }
repositories { repositories {
mavenCentral()
maven { url "https://kamax.io/maven/releases/" } maven { url "https://kamax.io/maven/releases/" }
maven { url "https://kamax.io/maven/snapshots/" } maven { url "https://kamax.io/maven/snapshots/" }
mavenCentral()
} }
dependencies { dependencies {
@@ -81,7 +81,7 @@ dependencies {
compile "org.springframework.boot:spring-boot-starter-thymeleaf:1.5.10.RELEASE" compile "org.springframework.boot:spring-boot-starter-thymeleaf:1.5.10.RELEASE"
// Matrix Java SDK // Matrix Java SDK
compile 'io.kamax:matrix-java-sdk:0.0.14-8-g0e57ec6' compile 'io.kamax:matrix-java-sdk:0.0.11'
// ed25519 handling // ed25519 handling
compile 'net.i2p.crypto:eddsa:0.1.0' compile 'net.i2p.crypto:eddsa:0.1.0'
@@ -102,6 +102,9 @@ dependencies {
compile 'com.sun.mail:javax.mail:1.5.6' compile 'com.sun.mail:javax.mail:1.5.6'
compile 'javax.mail:javax.mail-api:1.5.6' compile 'javax.mail:javax.mail-api:1.5.6'
// Google Client APIs
compile 'com.google.api-client:google-api-client:1.23.0'
// Google Firebase Authentication backend // Google Firebase Authentication backend
compile 'com.google.firebase:firebase-admin:5.3.0' compile 'com.google.firebase:firebase-admin:5.3.0'

View File

@@ -1,6 +1,4 @@
# Table of Contents # Table of Contents
- [Identity Concepts in Matrix](concepts.md)
- [Getting Started](getting-started.md)
- [Build from sources](build.md) (Optional) - [Build from sources](build.md) (Optional)
- Installation - Installation
- [Debian package](install/debian.md) - [Debian package](install/debian.md)
@@ -22,4 +20,3 @@
- [SendGrid](threepids/notification/sendgrid-handler.md) - [SendGrid](threepids/notification/sendgrid-handler.md)
- [Sessions](threepids/session/session.md) - [Sessions](threepids/session/session.md)
- [Views](threepids/session/session-views.md) - [Views](threepids/session/session-views.md)
- [FAQ](faq.md)

View File

@@ -18,9 +18,12 @@ TCP 443
| +-------------------+ | +-------------------+
TCP 8090 +-> | mxisd | TCP 8090 +-> | mxisd |
| | | |
| - Profile's 3PIDs | | - Profile's 3PIDs >----+
| - 3PID Invites | | - 3PID Invites | | +--------------------------+
+-|-----------------+ +-|-----------------+ +>----------> | Central Identity service |
| | TCP 443 | Matrix.org / Vector.im |
| | +--------------------------+
+>-------------------->+
| |
TCP 443 TCP 443
| +------------------------+ | +------------------------+

View File

@@ -12,7 +12,7 @@
### Build ### Build
```bash ```bash
git clone https://github.com/kamax-matrix/mxisd.git git clone https://github.com/kamax-io/mxisd.git
cd mxisd cd mxisd
./gradlew build ./gradlew build
``` ```

View File

@@ -5,7 +5,7 @@ Identity in Matrix is one of the most difficult topic, mainly as it has not rece
We have tried our best to put together documentation that requires almost no knowledge of Matrix inner workings to get a We have tried our best to put together documentation that requires almost no knowledge of Matrix inner workings to get a
first basic setup running which relies on you reading the documentation in the right order: first basic setup running which relies on you reading the documentation in the right order:
- [The Concepts](concepts.md) in few words. - [The Concepts](concepts.md) in few words.
- [Getting Started](getting-started.md) step-by-step to a minimal working install. - [Getting Started](getting-started.md) step-by-step to a minimal working install.
- [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.
@@ -19,9 +19,8 @@ started and answer questions you might have.
### Do I need to use mxisd if I run a Homeserver? ### Do I need to use mxisd 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, mxisd will talk to the central Matrix Identity servers and use other federated public
It can also [be configured](features/identity.md#lookups) to use the central matrix.org servers, giving you access to at servers when performing queries, 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 It will also give your users a choice to make their 3PIDs available publicly, ensuring they are made aware of the
privacy consequences, which is not the case with the central Matrix.org servers. privacy consequences, which is not the case with the central Matrix.org servers.
@@ -71,15 +70,18 @@ So really, you should go with mxisd.
### 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 mxisd?
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, mxisd act as a proxy to Matrix.org/Vector.im. You will have access to the same data and
data and those of people you might know. behaviour than if you were using them directly. There is no downside in using mxisd with the default configuration.
mxisd [can be configured](features/identity.md#lookups) to talk to the central Identity servers if you wish. mxisd can also be configured not 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 mxisd is just a big hack! I don't want to use non-official features!
mxisd primary concerns are your privacy and to always be compatible with the Matrix ecosystem and the Identity service API. mxisd primary concern is 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, mxisd will follow, remaining 100% compatible with the ecosystem.
Therefore, using mxisd is a safe choice. It will be like using the central Matrix.org Identity servers, yet not closing
the door to a growing list of enhancements and integrations.
### Should I use mxisd if I don't host my own Homeserver? ### Should I use mxisd if I don't host my own Homeserver?
No. No.

View File

@@ -148,8 +148,7 @@ dns.overwrite.homeserver.client:
value: 'http://localhost:8008' value: 'http://localhost:8008'
``` ```
`name` must be the hostname of the URL that clients use when connecting to the Homeserver. `name` must be the hostname of the URL that clients use when connecting to the Homeserver.
You can use `${server.name}` to auto-populate the `value` using the `server.name` configuration option and avoid duplicating it. In case the hostname is the same as your Matrix domain, you can use `${matrix.domain}` to auto-populate the `value`
In case the hostname is the same as your Matrix domain and `server.name` is not explicitely set in the config, `server.name` will default to using the `matrix.domain` configuration option and avoid duplicating it.
`matrix.domain` and will still probably have the correct value.
`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 `/`.

View File

@@ -138,12 +138,5 @@ the `matrix.domain` configuration option and avoid duplicating it.
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 mxisd configuration file:
```yaml ```yaml
directory.exclude.homeserver: true directory.exclude.homeserever: true
```
### 3PID exclusion in search
You can configure if the 3PID should also be included when doing a directory search.
By default, a search is performed on the 3PIDs. If you would like to not include them:
```yaml
directory.exclude.threepid: true
``` ```

View File

@@ -1,72 +0,0 @@
# Integration as an Application Service
**WARNING:** These features are currently highly experimental. They can be removed or modified without notice.
All the features requires a Homeserver capable of connecting Application Services.
## Email notification for Room invites by Matrix ID
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.
### Requirements
- [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.
### Configuration
In your mxisd config file:
```yaml
matrix:
listener:
url: '<URL TO THE CS API OF THE HOMESERVER>'
localpart: 'appservice-mxisd'
token:
hs: 'HS_TOKEN_CHANGE_ME'
synapseSql:
enabled: false ## Do not use this line if Synapse is used as an Identity Store
type: '<DB TYPE>'
connection: '<DB CONNECTION URL>'
```
The `synapseSql` section 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).
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.
See [the Template generator documentation](../../threepids/notification/template-generator.md) for more info.
### Homeserver integration
#### 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.

View File

@@ -1,12 +0,0 @@
# Profile enhancement
**WARNING**: Alpha feature, not officially supported. Do not use.
This feature allows to enhance a profile query with more info than just Matrix ID and Display name, allowing for custom
applications to retrieve custom data not currently provided by synapse, per example.
## Configuration
### Reverse proxy
#### Apache
```apache
ProxyPassMatch "^/_matrix/client/r0/profile/([^/]+)$" "http://127.0.0.1:8090/_matrix/client/r0/profile/$1"
```

View File

@@ -5,8 +5,8 @@ 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, mxisd will talk to the central Identity server of matrix.org by
the central matrix.org one. See the [Identity feature](identity.md#lookups) for instructions on how to enable it. default.
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.
@@ -17,14 +17,16 @@ Outbound federation is enabled by default while inbound federation is opt-in and
| | | +------> +----------+ | | | +------> +----------+
| | | | | | | |
| Invites / Lookups | | | | Invites / Lookups | | |
Federated | +--------+ | | | Federated | +--------+ | | | +-------------------+
Identity ---->| Remote |>-----------+ | Identity ---->| Remote |>-----------+ +------> | Remote Federated |
Server | +--------+ | | Server | +--------+ | | | mxisd servers |
| | | | | | +-------------------+
| +--------+ | | +-------------------+ | +--------+ | |
Homeserver --->| Local |>------------------+------> | Remote Federated | Homeserver --->| Local |>------------------+
and clients | +--------+ | | mxisd servers | and clients | +--------+ | | +--------------------------+
+-------------------+ +-------------------+ +-------------------+ +------> | Central Identity service |
| Matrix.org / Vector.im |
+--------------------------+
``` ```
## Inbound ## Inbound

View File

@@ -3,16 +3,6 @@
Implementation of the [Unofficial Matrix Identity Service API](https://kamax.io/matrix/api/identity_service/unstable.html). Implementation of the [Unofficial Matrix Identity Service API](https://kamax.io/matrix/api/identity_service/unstable.html).
## Lookups
If you would like to use the central matrix.org Identity server to ensure maximum discovery at the cost of potentially
leaking all your contacts information, add the following to your configuration:
```yaml
forward.servers:
- 'matrix-org'
```
**NOTE:** You should carefully consider enabling this option, which is discouraged.
For more info, see the [relevant issue](https://github.com/kamax-matrix/mxisd/issues/76).
## Room Invitations ## Room Invitations
Resolution can be customized using the following configuration: Resolution can be customized using the following configuration:

9
docs/features/profile.md Normal file
View File

@@ -0,0 +1,9 @@
# Profile enhancement
**WARNING**: Alpha feature not officially supported. Do not use.
## Configuration
### Reverse proxy
#### Apache
```apache
ProxyPassMatch "^/_matrix/client/r0/profile/([^/]+)$" "http://127.0.0.1:8090/_matrix/client/r0/profile/$1"
```

View File

@@ -12,7 +12,7 @@ This will be a good ground work for further integration with features and your e
## Preparation ## Preparation
You will need: You will need:
- Working Homeserver, ideally with working federation - Homeserver
- 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 mxisd domain
As synapse requires an HTTPS connection when talking to an Identity service, **a reverse proxy is required** as mxisd does As synapse requires an HTTPS connection when talking to an Identity service, **a reverse proxy is required** as mxisd does
@@ -20,7 +20,7 @@ not support HTTPS listener at this time.
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 mxisd reachable via the same 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/kamax-io/mxisd/wiki/Gotchas#nating) if you use the same
hostname. hostname.
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 mxisd under the same hostname.
@@ -30,11 +30,10 @@ If you would like a high-level view of the infrastructure and how each feature i
## Install ## Install
Install via: Install via:
- [Debian package](install/debian.md) - [Debian package](install/debian.md)
- [ArchLinux](install/archlinux.md)
- [Docker image](install/docker.md) - [Docker image](install/docker.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/kamax-io/mxisd/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.
@@ -119,15 +118,10 @@ It is recommended to remove `matrix.org` and `vector.im` (or any other default e
your own Identity server is authoritative for your HS. your own Identity server is authoritative for your HS.
## Validate ## Validate
**NOTE:** In case your homeserver has no working federation, step 5 will not happen. If step 4 took place, consider Log in using your Matrix client and set `https://example.org` as your Identity server URL, replacing `example.org` by
your installation validated. the relevant hostname which you configured in your reverse proxy.
Invite `mxisd-federation-test@kamax.io` to a room, which should be turned into a Matrix invite to `@mxisd-lookup-test:kamax.io`.
1. Log in using your Matrix client and set `https://example.org` as your Identity server URL, replacing `example.org` by At this point, the test user will join the room, send a congratulation message and leave.
the relevant hostname which you configured in your reverse proxy.
2. Create a new empty room. All further actions will take place in this room.
3. Invite `mxisd-federation-test@kamax.io`
4. The 3PID invite should be turned into a Matrix invite to `@mxisd-lookup-test:kamax.io`.
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 mxisd in its basic mode! Congratulations!

View File

@@ -1,6 +1,6 @@
# Debian package # Debian package
## Install ## Install
1. Download the [latest release](https://github.com/kamax-matrix/mxisd/releases/latest) 1. Download the [latest release](https://github.com/kamax-io/mxisd/releases/latest)
2. Run: 2. Run:
```bash ```bash
dpkg -i /path/to/downloaded/mxisd.deb dpkg -i /path/to/downloaded/mxisd.deb

View File

@@ -7,7 +7,6 @@ https://firebase.google.com/
| Authentication | Yes | | Authentication | Yes |
| Directory | No | | Directory | No |
| Identity | Yes | | Identity | Yes |
| Profile | 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

View File

@@ -13,7 +13,6 @@ For NetIQ, replace all the `ldap` prefix in the configuration by `netiq`.
| Authentication | Yes | | Authentication | Yes |
| Directory | Yes | | Directory | Yes |
| Identity | Yes | | Identity | Yes |
| Profile | Yes |
## Getting started ## Getting started
### Base ### Base

View File

@@ -13,7 +13,6 @@ To integrate this backend with your webapp, you will need to implement three spe
| Authentication | Yes | | Authentication | Yes |
| Directory | Yes | | Directory | Yes |
| Identity | Yes | | Identity | Yes |
| Profile | No |
## Configuration ## Configuration
| Key | Default | Description | | Key | Default | Description |

View File

@@ -11,7 +11,6 @@
| Authentication | No | | Authentication | No |
| Directory | Yes | | Directory | Yes |
| Identity | Yes | | Identity | Yes |
| Profile | 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
@@ -45,7 +44,7 @@ Example: `/path/to/sqlite/file.db`
#### Others #### Others
```yaml ```yaml
sql.connection: //<HOST[:PORT]/DB?user=USER&password=PASS sql.connection: //<HOST[:PORT]/DB?username=USER&password=PASS
``` ```
Set the connection info for the database by replacing the following values: Set the connection info for the database by replacing the following values:
- `HOST`: Hostname of the SQL server - `HOST`: Hostname of the SQL server

View File

@@ -7,7 +7,6 @@ Synapse's Database itself can be used as an Identity store.
| Authentication | No | | Authentication | No |
| Directory | Yes | | Directory | Yes |
| Identity | Yes | | Identity | Yes |
| Profile | Yes |
Authentication is done by Synapse itself. Authentication is done by Synapse itself.
@@ -36,7 +35,7 @@ Example: `/path/to/synapse/sqliteFile.db`
### PostgreSQL ### PostgreSQL
```yaml ```yaml
synapseSql.connection: //<HOST[:PORT]/DB?user=USER&password=PASS synapseSql.connection: //<HOST[:PORT]/DB?username=USER&password=PASS
``` ```
Set the connection info for the database by replacing the following values: Set the connection info for the database by replacing the following values:
- `HOST`: Hostname of the SQL server - `HOST`: Hostname of the SQL server

View File

@@ -10,7 +10,6 @@ Two types of connections are required for full support:
| Authentication | Yes | | Authentication | Yes |
| Directory | Yes | | Directory | Yes |
| Identity | Yes | | Identity | Yes |
| Profile | No |
## Requirements ## Requirements
- [Wordpress](https://wordpress.org/download/) >= 4.4 - [Wordpress](https://wordpress.org/download/) >= 4.4
@@ -56,11 +55,3 @@ With possible values:
- `mariadb` - `mariadb`
- `postgresql` - `postgresql`
- `sqlite` - `sqlite`
---
To configure the tables prefix for default queries, in case a custom value was set during Wordpress install:
```yaml
wordpress.sql.tablePrefix: <string>
```
By default, the value is set to `wp_`.

View File

@@ -1,5 +1,5 @@
# SendGrid Notification handler # SendGrid Notification handler
To be completed. See [raw possible configuration items](https://github.com/kamax-matrix/mxisd/blob/master/src/main/resources/application.yaml#L172). To be completed. See [raw possible configuration items](https://github.com/kamax-io/mxisd/blob/master/src/main/resources/application.yaml#L172).
Enabled with: Enabled with:
```yaml ```yaml

View File

@@ -19,8 +19,6 @@ threepid.medium.<YOUR 3PID MEDIUM HERE>:
validation: validation:
local: '/path/to/validate-local-template.eml' local: '/path/to/validate-local-template.eml'
remote: 'path/to/validate-remote-template.eml' remote: 'path/to/validate-remote-template.eml'
generic:
matrixId: '/path/to/mxid-invite-template.eml'
``` ```
The `template` generator is usually the default, so no further configuration is needed. The `template` generator is usually the default, so no further configuration is needed.

View File

@@ -117,7 +117,6 @@ The following example of configuration (incomplete extract) shows which items ar
**IMPORTANT:** Most configuration items shown have default values and should not be included in your own configuration **IMPORTANT:** Most configuration items shown have default values and should not be included in your own configuration
file unless you want to specifically overwrite them. file unless you want to specifically overwrite them.
```yaml ```yaml
# CONFIGURATION EXAMPLE
# DO NOT COPY/PASTE THIS IN YOUR CONFIGURATION # DO NOT COPY/PASTE THIS IN YOUR CONFIGURATION
session.policy.validation.enabled: true session.policy.validation.enabled: true
session.policy.validation.forLocal: session.policy.validation.forLocal:
@@ -133,7 +132,6 @@ session.policy.validation.forRemote:
enabled: true enabled: true
server: 'configExample' # Not to be included in config! Already present in default config! server: 'configExample' # Not to be included in config! Already present in default config!
# DO NOT COPY/PASTE THIS IN YOUR CONFIGURATION # DO NOT COPY/PASTE THIS IN YOUR CONFIGURATION
# CONFIGURATION EXAMPLE
``` ```
`session.policy.validation` is the core configuration to control what users configured to use your Identity server `session.policy.validation` is the core configuration to control what users configured to use your Identity server
@@ -145,8 +143,8 @@ It is also divided into two sections: `forLocal` and `forRemote` which refers to
Each scope is divided into three parts: Each scope is divided into three parts:
- global on/off switch for 3PID sessions using `.enabled` - global on/off switch for 3PID sessions using `.enabled`
- `toLocal` allowing or not local 3PID session validations - `toLocal` allowing or not local 3PID session validations
- `toRemote` allowing or not remote 3PID session validations and to which server such sessions should be sent. - `toRemote` allowing or not remote 3PID session validations and to which server such sessions should be sent.
`.server` takes a Matrix Identity server list label. Only the first server in the list is currently used. `.server` takes a Matrix Identity server list label. Only the first server in the list is currently used.
If both `toLocal` and `toRemote` are enabled, the user will be offered to initiate a remote session once their 3PID If both `toLocal` and `toRemote` are enabled, the user will be offered to initiate a remote session once their 3PID
locally validated. locally validated.

View File

@@ -1,6 +1,6 @@
Package: mxisd Package: mxisd
Maintainer: Kamax.io <foss@kamax.io> Maintainer: Kamax.io <foss@kamax.io>
Homepage: https://github.com/kamax-matrix/mxisd Homepage: https://github.com/kamax-io/mxisd
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 Depends: openjdk-8-jre | openjdk-8-jre-headless | openjdk-8-jdk | openjdk-8-jdk-headless

View File

@@ -1,112 +0,0 @@
/*
* mxisd - Matrix Identity Server Daemon
* 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.mxisd.as;
import com.google.gson.JsonObject;
import io.kamax.matrix.MatrixID;
import io.kamax.matrix._MatrixID;
import io.kamax.matrix._ThreePid;
import io.kamax.matrix.event.EventKey;
import io.kamax.matrix.json.GsonUtil;
import io.kamax.mxisd.backend.sql.synapse.Synapse;
import io.kamax.mxisd.config.MatrixConfig;
import io.kamax.mxisd.notification.NotificationManager;
import io.kamax.mxisd.profile.ProfileManager;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@Component
public class AppServiceHandler {
private final Logger log = LoggerFactory.getLogger(AppServiceHandler.class);
private MatrixConfig cfg;
private ProfileManager profiler;
private NotificationManager notif;
private Synapse synapse;
@Autowired
public AppServiceHandler(MatrixConfig cfg, ProfileManager profiler, NotificationManager notif, Synapse synapse) {
this.cfg = cfg;
this.profiler = profiler;
this.notif = notif;
this.synapse = synapse;
}
public void processTransaction(List<JsonObject> eventsJson) {
eventsJson.forEach(ev -> {
if (!StringUtils.equals("m.room.member", GsonUtil.getStringOrNull(ev, "type"))) {
return;
}
if (!StringUtils.equals("invite", GsonUtil.getStringOrNull(ev, "membership"))) {
return;
}
String roomId = GsonUtil.getStringOrNull(ev, "room_id");
_MatrixID sender = MatrixID.asAcceptable(GsonUtil.getStringOrNull(ev, "sender"));
EventKey.StateKey.findString(ev).ifPresent(id -> {
_MatrixID mxid = MatrixID.asAcceptable(id);
if (!StringUtils.equals(mxid.getDomain(), cfg.getDomain())) {
log.debug("Ignoring invite for {}: not a local user");
return;
}
log.info("Got invite for {}", id);
boolean wasSent = false;
List<_ThreePid> tpids = profiler.getThreepids(mxid);
if (tpids.isEmpty()) {
log.info("No email found in identity stores for {}", id);
}
for (_ThreePid tpid : tpids) {
if (!StringUtils.equals("email", tpid.getMedium())) {
continue;
}
log.info("Found an email address to notify about room invitation: {}", tpid.getAddress());
Map<String, String> properties = new HashMap<>();
profiler.getDisplayName(sender).ifPresent(name -> properties.put("sender_display_name", name));
try {
synapse.getRoomName(roomId).ifPresent(name -> properties.put("room_name", name));
} catch (RuntimeException e) {
log.warn("Unable to fetch room name - Did you provide synapse DB information as documented?");
log.warn("Underlying error:", e);
}
IMatrixIdInvite inv = new MatrixIdInvite(roomId, sender, mxid, tpid.getMedium(), tpid.getAddress(), properties);
notif.sendForInvite(inv);
wasSent = true;
}
log.info("Was notification sent? {}", wasSent);
});
});
}
}

View File

@@ -1,77 +0,0 @@
/*
* mxisd - Matrix Identity Server Daemon
* 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.mxisd.as;
import io.kamax.matrix._MatrixID;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
public class MatrixIdInvite implements IMatrixIdInvite {
private String roomId;
private _MatrixID sender;
private _MatrixID invitee;
private String medium;
private String address;
private Map<String, String> properties;
public MatrixIdInvite(String roomId, _MatrixID sender, _MatrixID invitee, String medium, String address, Map<String, String> properties) {
this.roomId = Objects.requireNonNull(roomId);
this.sender = Objects.requireNonNull(sender);
this.invitee = Objects.requireNonNull(invitee);
this.medium = Objects.requireNonNull(medium);
this.address = Objects.requireNonNull(address);
this.properties = new HashMap<>(Objects.requireNonNull(properties));
}
@Override
public _MatrixID getSender() {
return sender;
}
@Override
public String getMedium() {
return medium;
}
@Override
public String getAddress() {
return address;
}
@Override
public _MatrixID getInvitee() {
return invitee;
}
@Override
public String getRoomId() {
return roomId;
}
@Override
public Map<String, String> getProperties() {
return properties;
}
}

View File

@@ -43,8 +43,7 @@ public class AuthManager {
private Logger log = LoggerFactory.getLogger(AuthManager.class); private Logger log = LoggerFactory.getLogger(AuthManager.class);
@Autowired private List<AuthenticatorProvider> providers;
private List<AuthenticatorProvider> providers = new ArrayList<>();
@Autowired @Autowired
private MatrixConfig mxCfg; private MatrixConfig mxCfg;
@@ -52,6 +51,10 @@ public class AuthManager {
@Autowired @Autowired
private InvitationManager invMgr; private InvitationManager invMgr;
public AuthManager(List<AuthenticatorProvider> providers) {
this.providers = new ArrayList<>(providers);
}
public UserAuthResult authenticate(String id, String password) { public UserAuthResult authenticate(String id, String password) {
_MatrixID mxid = MatrixID.asAcceptable(id); _MatrixID mxid = MatrixID.asAcceptable(id);
for (AuthenticatorProvider provider : providers) { for (AuthenticatorProvider provider : providers) {
@@ -59,6 +62,7 @@ public class AuthManager {
continue; continue;
} }
log.info("Attempting auth with " + provider.getClass().getSimpleName());
BackendAuthResult result = provider.authenticate(mxid, password); BackendAuthResult result = provider.authenticate(mxid, password);
if (result.isSuccess()) { if (result.isSuccess()) {

View File

@@ -49,8 +49,9 @@ public class BackendAuthResult {
return r; return r;
} }
public void fail() { public BackendAuthResult fail() {
success = false; success = false;
return this;
} }
public static BackendAuthResult success(String id, UserIdType type, String displayName) { public static BackendAuthResult success(String id, UserIdType type, String displayName) {
@@ -63,10 +64,11 @@ public class BackendAuthResult {
return r; return r;
} }
public void succeed(String id, String type, String displayName) { public BackendAuthResult succeed(String id, String type, String displayName) {
this.success = true; this.success = true;
this.id = new UserID(type, id); this.id = new UserID(type, id);
this.profile.displayName = displayName; this.profile.displayName = displayName;
return this;
} }
private Boolean success; private Boolean success;

View File

@@ -0,0 +1,134 @@
/*
* mxisd - Matrix Identity Server Daemon
* 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.mxisd.backend.google;
import com.google.api.client.googleapis.auth.oauth2.GoogleIdToken;
import com.google.api.client.googleapis.auth.oauth2.GoogleIdTokenVerifier;
import com.google.api.client.googleapis.javanet.GoogleNetHttpTransport;
import com.google.api.client.http.HttpTransport;
import com.google.api.client.json.JsonFactory;
import com.google.api.client.json.jackson2.JacksonFactory;
import io.kamax.matrix._MatrixID;
import io.kamax.matrix.ThreePid;
import io.kamax.mxisd.UserIdType;
import io.kamax.mxisd.auth.provider.AuthenticatorProvider;
import io.kamax.mxisd.auth.provider.BackendAuthResult;
import io.kamax.mxisd.config.GoogleConfig;
import io.kamax.mxisd.lookup.strategy.LookupStrategy;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.io.IOException;
import java.security.GeneralSecurityException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
@Component
public class GoogleProviderBackend implements AuthenticatorProvider {
private final Logger log = LoggerFactory.getLogger(GoogleProviderBackend.class);
private final GoogleConfig cfg;
private final LookupStrategy lookup;
private GoogleIdTokenVerifier verifier;
public Optional<GoogleIdToken> extractToken(String data) throws GeneralSecurityException, IOException {
return Optional.ofNullable(verifier.verify(data));
}
public List<ThreePid> extractThreepids(GoogleIdToken token) {
List<ThreePid> tpids = new ArrayList<>();
tpids.add(new ThreePid("io.kamax.google.id", token.getPayload().getSubject()));
if (token.getPayload().getEmailVerified()) {
tpids.add(new ThreePid("email", token.getPayload().getEmail()));
}
return tpids;
}
@Autowired
public GoogleProviderBackend(GoogleConfig cfg, LookupStrategy lookup) {
this.cfg = cfg;
this.lookup = lookup;
if (isEnabled()) {
try {
HttpTransport transport = GoogleNetHttpTransport.newTrustedTransport();
JsonFactory jsonFactory = JacksonFactory.getDefaultInstance();
verifier = new GoogleIdTokenVerifier.Builder(transport, jsonFactory)
.setAudience(Collections.singletonList(cfg.getClient().getId()))
.build();
} catch (IOException | GeneralSecurityException e) {
throw new RuntimeException(e);
}
}
}
@Override
public boolean isEnabled() {
return cfg.isEnabled();
}
@Override
public BackendAuthResult authenticate(_MatrixID mxid, String password) {
BackendAuthResult result = new BackendAuthResult();
try {
return extractToken(password).map(idToken -> {
GoogleIdToken.Payload payload = idToken.getPayload();
if (!payload.getEmailVerified()) { // We only want users who validated their email
return BackendAuthResult.failure();
}
// Get user identifier
String userId = payload.getSubject();
// We validate that the user who authenticated has his Google account associated already
return lookup.find("io.kamax.google.id", userId, false).map(r -> {
if (!r.getMxid().equals(mxid)) {
return result.fail();
}
// Get profile information from payload
extractThreepids(idToken).forEach(result::withThreePid);
String name = (String) payload.get("name");
payload.getUnknownKeys().keySet().forEach(key -> {
log.info("Unknown key in Google profile: {} -> ", key, payload.get(key));
});
return result.succeed(mxid.getId(), UserIdType.MatrixID.getId(), name);
}).orElse(BackendAuthResult.failure());
}).orElse(BackendAuthResult.failure());
} catch (GeneralSecurityException e) {
throw new RuntimeException(e);
} catch (IOException e) {
log.error("Unable to authenticate via Google due to network error", e);
return result.fail();
}
}
}

View File

@@ -1,8 +1,8 @@
/* /*
* mxisd - Matrix Identity Server Daemon * mxisd - Matrix Identity Server Daemon
* Copyright (C) 2017 Kamax Sarl * Copyright (C) 2017 Maxime Dor
* *
* https://www.kamax.io/ * https://max.kamax.io/
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as * it under the terms of the GNU Affero General Public License as
@@ -20,7 +20,6 @@
package io.kamax.mxisd.backend.ldap; package io.kamax.mxisd.backend.ldap;
import io.kamax.matrix._MatrixID;
import io.kamax.mxisd.config.MatrixConfig; import io.kamax.mxisd.config.MatrixConfig;
import io.kamax.mxisd.config.ldap.LdapConfig; import io.kamax.mxisd.config.ldap.LdapConfig;
import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.StringUtils;
@@ -71,7 +70,7 @@ public abstract class LdapBackend {
return getAt().getUid().getValue(); return getAt().getUid().getValue();
} }
protected synchronized LdapConnection getConn() { protected synchronized LdapConnection getConn() throws LdapException {
return new LdapNetworkConnection(cfg.getConnection().getHost(), cfg.getConnection().getPort(), cfg.getConnection().isTls()); return new LdapNetworkConnection(cfg.getConnection().getHost(), cfg.getConnection().getPort(), cfg.getConnection().isTls());
} }
@@ -125,17 +124,6 @@ public abstract class LdapBackend {
} }
} }
public String buildUidFromMatrixId(_MatrixID mxId) {
String uidType = getCfg().getAttribute().getUid().getType();
if (StringUtils.equals(UID, uidType)) {
return mxId.getLocalPart();
} else if (StringUtils.equals(MATRIX_ID, uidType)) {
return mxId.getId();
} else {
throw new IllegalArgumentException("Bind type " + uidType + " is not supported");
}
}
public Optional<String> getAttribute(Entry entry, String attName) { public Optional<String> getAttribute(Entry entry, String attName) {
Attribute attribute = entry.get(attName); Attribute attribute = entry.get(attName);
if (attribute == null) { if (attribute == null) {

View File

@@ -1,157 +0,0 @@
/*
* mxisd - Matrix Identity Server Daemon
* 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.mxisd.backend.ldap;
import io.kamax.matrix.ThreePid;
import io.kamax.matrix._MatrixID;
import io.kamax.matrix._ThreePid;
import io.kamax.mxisd.config.MatrixConfig;
import io.kamax.mxisd.config.ldap.LdapConfig;
import io.kamax.mxisd.exception.InternalServerError;
import io.kamax.mxisd.profile.ProfileProvider;
import org.apache.directory.api.ldap.model.cursor.CursorException;
import org.apache.directory.api.ldap.model.cursor.CursorLdapReferralException;
import org.apache.directory.api.ldap.model.cursor.EntryCursor;
import org.apache.directory.api.ldap.model.entry.Entry;
import org.apache.directory.api.ldap.model.exception.LdapException;
import org.apache.directory.api.ldap.model.message.SearchScope;
import org.apache.directory.ldap.client.api.LdapConnection;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
@Component
public class LdapProfileProvider extends LdapBackend implements ProfileProvider {
private transient Logger log = LoggerFactory.getLogger(LdapProfileProvider.class);
@Autowired
public LdapProfileProvider(LdapConfig cfg, MatrixConfig mxCfg) {
super(cfg, mxCfg);
}
@Override
public boolean isEnabled() {
return getCfg().isEnabled();
}
@Override
public Optional<String> getDisplayName(_MatrixID userId) {
String uid = buildUidFromMatrixId(userId);
log.info("Searching for display name of {}:", uid);
try (LdapConnection conn = getConn()) {
bind(conn);
String searchQuery = buildOrQueryWithFilter(getCfg().getProfile().getFilter(), uid, getUidAtt());
log.debug("Base DN: {}", getBaseDn());
log.debug("Query: {}", searchQuery);
try (EntryCursor cursor = conn.search(getBaseDn(), searchQuery, SearchScope.SUBTREE, getAt().getName())) {
while (cursor.next()) {
Entry entry = cursor.get();
log.info("Found possible match, DN: {}", entry.getDn().getName());
Optional<String> v = getAttribute(entry, getAt().getName()).flatMap(id -> {
log.info("DN {} is a valid match", entry.getDn().getName());
try {
return getAttribute(entry, getAt().getName());
} catch (IllegalArgumentException e) {
log.warn("Bind was found but type {} is not supported", getAt().getUid().getType());
return Optional.empty();
}
});
if (v.isPresent()) {
log.info("DN {} is the final match", entry.getDn().getName());
return v;
}
}
}
} catch (CursorLdapReferralException e) {
log.warn("An entry is only available via referral, skipping");
} catch (IOException | LdapException | CursorException e) {
throw new InternalServerError(e);
}
return Optional.empty();
}
@Override
public List<_ThreePid> getThreepids(_MatrixID userId) {
String uid = buildUidFromMatrixId(userId);
log.info("Searching for 3PIDs of {}:", uid);
List<_ThreePid> threePids = new ArrayList<>();
try (LdapConnection conn = getConn()) {
bind(conn);
log.debug("Base DN: {}", getBaseDn());
getCfg().getAttribute().getThreepid().forEach((medium, attributes) -> {
String[] attArray = new String[attributes.size()];
attributes.toArray(attArray);
String searchQuery = buildOrQueryWithFilter(getCfg().getProfile().getFilter(), uid, getUidAtt());
log.debug("Query for 3PID {}: {}", medium, searchQuery);
try (EntryCursor cursor = conn.search(getBaseDn(), searchQuery, SearchScope.SUBTREE, attArray)) {
while (cursor.next()) {
Entry entry = cursor.get();
log.info("Found possible match, DN: {}", entry.getDn().getName());
try {
attributes.stream()
.flatMap(at -> getAttributes(entry, at).stream())
.forEach(address -> {
log.info("Found 3PID: {} - {}", medium, address);
threePids.add(new ThreePid(medium, address));
});
} catch (IllegalArgumentException e) {
log.warn("Bind was found but type {} is not supported", getAt().getUid().getType());
}
}
} catch (CursorLdapReferralException e) {
log.warn("An entry is only available via referral, skipping");
} catch (IOException | LdapException | CursorException e) {
throw new InternalServerError(e);
}
});
} catch (IOException | LdapException e) {
throw new InternalServerError(e);
}
return threePids;
}
@Override
public List<String> getRoles(_MatrixID userId) {
return Collections.emptyList();
}
}

View File

@@ -1,50 +0,0 @@
/*
* mxisd - Matrix Identity Server Daemon
* 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.mxisd.backend.ldap.netiq;
import io.kamax.matrix._MatrixID;
import io.kamax.mxisd.backend.ldap.LdapProfileProvider;
import io.kamax.mxisd.config.MatrixConfig;
import io.kamax.mxisd.config.ldap.netiq.NetIqLdapConfig;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class NetIqLdapProfileProvider extends LdapProfileProvider {
@Autowired
public NetIqLdapProfileProvider(NetIqLdapConfig cfg, MatrixConfig mxCfg) {
super(cfg, mxCfg);
}
// FIXME this is duplicated in the other NetIQ classes, due to the Matrix ID generation code that was not abstracted
@Override
public String buildMatrixIdFromUid(String uid) {
return super.buildMatrixIdFromUid(uid).toLowerCase();
}
// FIXME this is duplicated in the other NetIQ classes, due to the Matrix ID generation code that was not abstracted
@Override
public String buildUidFromMatrixId(_MatrixID mxid) {
return super.buildUidFromMatrixId(mxid).toLowerCase();
}
}

View File

@@ -1,6 +1,6 @@
/* /*
* mxisd - Matrix Identity Server Daemon * mxisd - Matrix Identity Server Daemon
* Copyright (C) 2018 Kamax Sarl * Copyright (C) 2018 Maxime Dor
* *
* https://www.kamax.io/ * https://www.kamax.io/
* *
@@ -76,11 +76,6 @@ public class MemoryIdentityStore implements AuthenticatorProvider, IDirectoryPro
return cfg.isEnabled(); return cfg.isEnabled();
} }
@Override
public Optional<String> getDisplayName(_MatrixID mxid) {
return findByUsername(mxid.getLocalPart()).map(MemoryIdentityConfig::getDisplayName);
}
private UserDirectorySearchResult search( private UserDirectorySearchResult search(
Predicate<MemoryIdentityConfig> predicate, Predicate<MemoryIdentityConfig> predicate,
Function<MemoryIdentityConfig, UserDirectorySearchResult.Result> mapper Function<MemoryIdentityConfig, UserDirectorySearchResult.Result> mapper

View File

@@ -1,8 +1,8 @@
/* /*
* mxisd - Matrix Identity Server Daemon * mxisd - Matrix Identity Server Daemon
* Copyright (C) 2017 Kamax Sarl * Copyright (C) 2017 Maxime Dor
* *
* https://www.kamax.io/ * https://max.kamax.io/
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as * it under the terms of the GNU Affero General Public License as
@@ -18,12 +18,13 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
package io.kamax.mxisd.backend.sql.generic; package io.kamax.mxisd.backend.sql;
import io.kamax.matrix._MatrixID; import io.kamax.matrix._MatrixID;
import io.kamax.mxisd.auth.provider.AuthenticatorProvider; import io.kamax.mxisd.auth.provider.AuthenticatorProvider;
import io.kamax.mxisd.auth.provider.BackendAuthResult; import io.kamax.mxisd.auth.provider.BackendAuthResult;
import io.kamax.mxisd.config.sql.generic.GenericSqlProviderConfig; import io.kamax.mxisd.config.ServerConfig;
import io.kamax.mxisd.config.sql.GenericSqlProviderConfig;
import io.kamax.mxisd.invitation.InvitationManager; import io.kamax.mxisd.invitation.InvitationManager;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@@ -35,6 +36,9 @@ public class GenericSqlAuthProvider implements AuthenticatorProvider {
private Logger log = LoggerFactory.getLogger(GenericSqlAuthProvider.class); private Logger log = LoggerFactory.getLogger(GenericSqlAuthProvider.class);
@Autowired
private ServerConfig srvCfg;
@Autowired @Autowired
private GenericSqlProviderConfig cfg; private GenericSqlProviderConfig cfg;
@@ -43,7 +47,7 @@ public class GenericSqlAuthProvider implements AuthenticatorProvider {
@Override @Override
public boolean isEnabled() { public boolean isEnabled() {
return cfg.getAuth().isEnabled(); return cfg.isEnabled();
} }
@Override @Override

View File

@@ -1,8 +1,8 @@
/* /*
* mxisd - Matrix Identity Server Daemon * mxisd - Matrix Identity Server Daemon
* Copyright (C) 2017 Kamax Sarl * Copyright (C) 2017 Maxime Dor
* *
* https://www.kamax.io/ * https://max.kamax.io/
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as * it under the terms of the GNU Affero General Public License as
@@ -18,13 +18,12 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
package io.kamax.mxisd.backend.sql.generic; package io.kamax.mxisd.backend.sql;
import io.kamax.matrix.MatrixID; import io.kamax.matrix.MatrixID;
import io.kamax.mxisd.backend.sql.SqlConnectionPool;
import io.kamax.mxisd.config.MatrixConfig; import io.kamax.mxisd.config.MatrixConfig;
import io.kamax.mxisd.config.sql.GenericSqlProviderConfig;
import io.kamax.mxisd.config.sql.SqlConfig; import io.kamax.mxisd.config.sql.SqlConfig;
import io.kamax.mxisd.config.sql.generic.GenericSqlProviderConfig;
import io.kamax.mxisd.controller.directory.v1.io.UserDirectorySearchResult; import io.kamax.mxisd.controller.directory.v1.io.UserDirectorySearchResult;
import io.kamax.mxisd.directory.IDirectoryProvider; import io.kamax.mxisd.directory.IDirectoryProvider;
import io.kamax.mxisd.exception.InternalServerError; import io.kamax.mxisd.exception.InternalServerError;
@@ -45,7 +44,7 @@ public abstract class GenericSqlDirectoryProvider implements IDirectoryProvider
private Logger log = LoggerFactory.getLogger(GenericSqlDirectoryProvider.class); private Logger log = LoggerFactory.getLogger(GenericSqlDirectoryProvider.class);
protected SqlConfig cfg; protected SqlConfig cfg;
protected MatrixConfig mxCfg; private MatrixConfig mxCfg;
private SqlConnectionPool pool; private SqlConnectionPool pool;
@@ -57,7 +56,7 @@ public abstract class GenericSqlDirectoryProvider implements IDirectoryProvider
@Override @Override
public boolean isEnabled() { public boolean isEnabled() {
return cfg.getDirectory().isEnabled(); return cfg.isEnabled();
} }
protected void setParameters(PreparedStatement stmt, String searchTerm) throws SQLException { protected void setParameters(PreparedStatement stmt, String searchTerm) throws SQLException {

View File

@@ -1,8 +1,8 @@
/* /*
* mxisd - Matrix Identity Server Daemon * mxisd - Matrix Identity Server Daemon
* Copyright (C) 2017 Kamax Sarl * Copyright (C) 2017 Maxime Dor
* *
* https://www.kamax.io/ * https://max.kamax.io/
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as * it under the terms of the GNU Affero General Public License as
@@ -18,11 +18,10 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
package io.kamax.mxisd.backend.sql.generic; package io.kamax.mxisd.backend.sql;
import io.kamax.mxisd.backend.sql.SqlThreePidProvider;
import io.kamax.mxisd.config.MatrixConfig; import io.kamax.mxisd.config.MatrixConfig;
import io.kamax.mxisd.config.sql.generic.GenericSqlProviderConfig; import io.kamax.mxisd.config.sql.GenericSqlProviderConfig;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;

View File

@@ -1,8 +1,8 @@
/* /*
* mxisd - Matrix Identity Server Daemon * mxisd - Matrix Identity Server Daemon
* Copyright (C) 2017 Kamax Sarl * Copyright (C) 2017 Maxime Dor
* *
* https://www.kamax.io/ * https://max.kamax.io/
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as * it under the terms of the GNU Affero General Public License as
@@ -28,12 +28,6 @@ import java.sql.SQLException;
public class SqlConnectionPool { public class SqlConnectionPool {
public interface SqlFunction<T, R> {
R run(T connection) throws SQLException;
}
private ComboPooledDataSource ds; private ComboPooledDataSource ds;
public SqlConnectionPool(SqlConfig cfg) { public SqlConnectionPool(SqlConfig cfg) {
@@ -48,12 +42,4 @@ public class SqlConnectionPool {
return ds.getConnection(); return ds.getConnection();
} }
public <T> T withConnFunction(SqlFunction<Connection, T> function) {
try (Connection conn = get()) {
return function.run(conn);
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
} }

View File

@@ -1,105 +0,0 @@
/*
* mxisd - Matrix Identity Server Daemon
* 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.mxisd.backend.sql;
import io.kamax.matrix.ThreePid;
import io.kamax.matrix._MatrixID;
import io.kamax.matrix._ThreePid;
import io.kamax.mxisd.config.sql.SqlConfig;
import io.kamax.mxisd.profile.ProfileProvider;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
public abstract class SqlProfileProvider implements ProfileProvider {
private Logger log = LoggerFactory.getLogger(SqlProfileProvider.class);
private SqlConfig.Profile cfg;
private SqlConnectionPool pool;
public SqlProfileProvider(SqlConfig cfg) {
this.cfg = cfg.getProfile();
this.pool = new SqlConnectionPool(cfg);
}
@Override
public boolean isEnabled() {
return cfg.isEnabled();
}
@Override
public Optional<String> getDisplayName(_MatrixID user) {
String stmtSql = cfg.getDisplayName().getQuery();
try (Connection conn = pool.get()) {
try (PreparedStatement stmt = conn.prepareStatement(stmtSql)) {
stmt.setString(1, user.getId());
try (ResultSet rSet = stmt.executeQuery()) {
if (!rSet.next()) {
return Optional.empty();
}
return Optional.ofNullable(rSet.getString(1));
}
}
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
@Override
public List<_ThreePid> getThreepids(_MatrixID user) {
List<_ThreePid> threepids = new ArrayList<>();
String stmtSql = cfg.getThreepid().getQuery();
try (Connection conn = pool.get()) {
PreparedStatement stmt = conn.prepareStatement(stmtSql);
stmt.setString(1, user.getId());
ResultSet rSet = stmt.executeQuery();
while (rSet.next()) {
String medium = rSet.getString(1);
String address = rSet.getString(2);
threepids.add(new ThreePid(medium, address));
}
return threepids;
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
@Override
public List<String> getRoles(_MatrixID user) {
return Collections.emptyList();
}
}

View File

@@ -1,8 +1,8 @@
/* /*
* mxisd - Matrix Identity Server Daemon * mxisd - Matrix Identity Server Daemon
* Copyright (C) 2017 Kamax Sarl * Copyright (C) 2017 Maxime Dor
* *
* https://www.kamax.io/ * https://max.kamax.io/
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as * it under the terms of the GNU Affero General Public License as
@@ -21,12 +21,16 @@
package io.kamax.mxisd.backend.sql; package io.kamax.mxisd.backend.sql;
import io.kamax.matrix.MatrixID; import io.kamax.matrix.MatrixID;
import io.kamax.matrix.ThreePid;
import io.kamax.matrix._MatrixID;
import io.kamax.matrix._ThreePid;
import io.kamax.mxisd.config.MatrixConfig; import io.kamax.mxisd.config.MatrixConfig;
import io.kamax.mxisd.config.sql.SqlConfig; import io.kamax.mxisd.config.sql.SqlConfig;
import io.kamax.mxisd.lookup.SingleLookupReply; import io.kamax.mxisd.lookup.SingleLookupReply;
import io.kamax.mxisd.lookup.SingleLookupRequest; import io.kamax.mxisd.lookup.SingleLookupRequest;
import io.kamax.mxisd.lookup.ThreePidMapping; import io.kamax.mxisd.lookup.ThreePidMapping;
import io.kamax.mxisd.lookup.provider.IThreePidProvider; import io.kamax.mxisd.lookup.provider.IThreePidProvider;
import io.kamax.mxisd.profile.ProfileProvider;
import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@@ -36,10 +40,11 @@ import java.sql.PreparedStatement;
import java.sql.ResultSet; import java.sql.ResultSet;
import java.sql.SQLException; import java.sql.SQLException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Optional; import java.util.Optional;
public abstract class SqlThreePidProvider implements IThreePidProvider { public abstract class SqlThreePidProvider implements IThreePidProvider, ProfileProvider {
private Logger log = LoggerFactory.getLogger(SqlThreePidProvider.class); private Logger log = LoggerFactory.getLogger(SqlThreePidProvider.class);
@@ -54,6 +59,10 @@ public abstract class SqlThreePidProvider implements IThreePidProvider {
this.mxCfg = mxCfg; this.mxCfg = mxCfg;
} }
protected Connection getConnection() throws SQLException {
return pool.get();
}
@Override @Override
public boolean isEnabled() { public boolean isEnabled() {
return cfg.isEnabled(); return cfg.isEnabled();
@@ -109,4 +118,31 @@ public abstract class SqlThreePidProvider implements IThreePidProvider {
return new ArrayList<>(); return new ArrayList<>();
} }
@Override
public List<_ThreePid> getThreepids(_MatrixID mxid) {
List<_ThreePid> threepids = new ArrayList<>();
String stmtSql = cfg.getProfile().getThreepid().getQuery();
try (Connection conn = getConnection()) {
PreparedStatement stmt = conn.prepareStatement(stmtSql);
stmt.setString(1, mxid.getId());
ResultSet rSet = stmt.executeQuery();
while (rSet.next()) {
String medium = rSet.getString("medium");
String address = rSet.getString("address");
threepids.add(new ThreePid(medium, address));
}
return threepids;
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
@Override
public List<String> getRoles(_MatrixID mxid) {
return Collections.emptyList();
}
} }

View File

@@ -0,0 +1,69 @@
/*
* mxisd - Matrix Identity Server Daemon
* Copyright (C) 2017 Maxime Dor
*
* https://max.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.mxisd.backend.sql;
import io.kamax.mxisd.config.MatrixConfig;
import io.kamax.mxisd.config.sql.GenericSqlProviderConfig;
import io.kamax.mxisd.config.sql.synapse.SynapseSqlProviderConfig;
import io.kamax.mxisd.exception.ConfigurationException;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.sql.PreparedStatement;
import java.sql.SQLException;
@Component
public class SynapseSqlDirectoryProvider extends GenericSqlDirectoryProvider {
@Autowired
public SynapseSqlDirectoryProvider(SynapseSqlProviderConfig cfg, MatrixConfig mxCfg) {
super(cfg, mxCfg);
if (StringUtils.equals("sqlite", cfg.getType())) {
String userId = "'@' || p.user_id || ':" + mxCfg.getDomain() + "'";
GenericSqlProviderConfig.Type queries = cfg.getDirectory().getQuery();
queries.getName().setValue(
"select " + userId + ", displayname from profiles p where displayname like ?");
queries.getThreepid().setValue(
"select t.user_id, p.displayname " +
"from user_threepids t JOIN profiles p on t.user_id = " + userId + " " +
"where t.address like ?");
} else if (StringUtils.equals("postgresql", cfg.getType())) {
String userId = "concat('@',p.user_id,':" + mxCfg.getDomain() + "')";
GenericSqlProviderConfig.Type queries = cfg.getDirectory().getQuery();
queries.getName().setValue(
"select " + userId + ", displayname from profiles p where displayname ilike ?");
queries.getThreepid().setValue(
"select t.user_id, p.displayname " +
"from user_threepids t JOIN profiles p on t.user_id = " + userId + " " +
"where t.address ilike ?");
} else {
throw new ConfigurationException("Invalid SQL type");
}
}
@Override
protected void setParameters(PreparedStatement stmt, String searchTerm) throws SQLException {
stmt.setString(1, "%" + searchTerm + "%");
}
}

View File

@@ -0,0 +1,69 @@
/*
* mxisd - Matrix Identity Server Daemon
* Copyright (C) 2017 Maxime Dor
*
* https://max.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.mxisd.backend.sql;
import io.kamax.matrix.ThreePid;
import io.kamax.matrix._MatrixID;
import io.kamax.mxisd.config.MatrixConfig;
import io.kamax.mxisd.config.sql.synapse.SynapseSqlProviderConfig;
import io.kamax.mxisd.profile.ProfileWriter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.time.Instant;
@Component
public class SynapseSqlThreePidProvider extends SqlThreePidProvider implements ProfileWriter {
private final Logger log = LoggerFactory.getLogger(SynapseSqlThreePidProvider.class);
@Autowired
public SynapseSqlThreePidProvider(SynapseSqlProviderConfig cfg, MatrixConfig mxCfg) {
super(cfg, mxCfg);
}
@Override
public boolean addThreepid(_MatrixID mxid, ThreePid tpid) {
try (Connection conn = getConnection()) {
PreparedStatement stmt = conn.prepareStatement("INSERT INTO user_threepids (user_id, medium, address, validated_at, added_at) values (?,?,?,?,?)");
stmt.setString(1, mxid.getId());
stmt.setString(2, tpid.getMedium());
stmt.setString(3, tpid.getAddress());
stmt.setLong(4, Instant.now().toEpochMilli());
stmt.setLong(5, Instant.now().toEpochMilli());
int rows = stmt.executeUpdate();
if (rows != 1) {
log.error("Unable to update 3PID info. Modified row(s): {}", rows);
}
return true;
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
}

View File

@@ -1,34 +0,0 @@
/*
* mxisd - Matrix Identity Server Daemon
* 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.mxisd.backend.sql.generic;
import io.kamax.mxisd.backend.sql.SqlProfileProvider;
import io.kamax.mxisd.config.sql.generic.GenericSqlProviderConfig;
import org.springframework.stereotype.Component;
@Component
public class GenericSqlProfileProvider extends SqlProfileProvider {
public GenericSqlProfileProvider(GenericSqlProviderConfig cfg) {
super(cfg);
}
}

View File

@@ -1,55 +0,0 @@
/*
* mxisd - Matrix Identity Server Daemon
* 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.mxisd.backend.sql.synapse;
import io.kamax.mxisd.backend.sql.SqlConnectionPool;
import io.kamax.mxisd.config.sql.synapse.SynapseSqlProviderConfig;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.Optional;
@Component
public class Synapse {
private SqlConnectionPool pool;
@Autowired
public Synapse(SynapseSqlProviderConfig sqlCfg) {
this.pool = new SqlConnectionPool(sqlCfg);
}
public Optional<String> getRoomName(String id) {
return pool.withConnFunction(conn -> {
PreparedStatement stmt = conn.prepareStatement(SynapseQueries.getRoomName());
stmt.setString(1, id);
ResultSet rSet = stmt.executeQuery();
if (!rSet.next()) {
return Optional.empty();
}
return Optional.ofNullable(rSet.getString(1));
});
}
}

View File

@@ -1,74 +0,0 @@
/*
* mxisd - Matrix Identity Server Daemon
* 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.mxisd.backend.sql.synapse;
import io.kamax.mxisd.exception.ConfigurationException;
import org.apache.commons.lang.StringUtils;
public class SynapseQueries {
public static String getUserId(String type, String domain) {
if (StringUtils.equals("sqlite", type)) {
return "'@' || p.user_id || ':" + domain + "'";
} else if (StringUtils.equals("postgresql", type)) {
return "concat('@',p.user_id,':" + domain + "')";
} else {
throw new ConfigurationException("Invalid Synapse SQL type: " + type);
}
}
public static String getDisplayName() {
return "SELECT displayname FROM profiles WHERE user_id = ?";
}
public static String getThreepids() {
return "SELECT medium, address FROM user_threepids WHERE user_id = ?";
}
public static String findByDisplayName(String type, String domain) {
if (StringUtils.equals("sqlite", type)) {
return "select " + getUserId(type, domain) + ", displayname from profiles p where displayname like ?";
} else if (StringUtils.equals("postgresql", type)) {
return "select " + getUserId(type, domain) + ", displayname from profiles p where displayname ilike ?";
} else {
throw new ConfigurationException("Invalid Synapse SQL type: " + type);
}
}
public static String findByThreePidAddress(String type, String domain) {
if (StringUtils.equals("sqlite", type)) {
return "select t.user_id, p.displayname " +
"from user_threepids t JOIN profiles p on t.user_id = " + getUserId(type, domain) + " " +
"where t.address like ?";
} else if (StringUtils.equals("postgresql", type)) {
return "select t.user_id, p.displayname " +
"from user_threepids t JOIN profiles p on t.user_id = " + getUserId(type, domain) + " " +
"where t.address ilike ?";
} else {
throw new ConfigurationException("Invalid Synapse SQL type: " + type);
}
}
public static String getRoomName() {
return "select r.name from room_names r, events e, (select r1.room_id,max(e1.origin_server_ts) ts from room_names r1, events e1 where r1.event_id = e1.event_id group by r1.room_id) rle where e.origin_server_ts = rle.ts and r.event_id = e.event_id and r.room_id = ?";
}
}

View File

@@ -1,63 +0,0 @@
/*
* mxisd - Matrix Identity Server Daemon
* 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.mxisd.backend.sql.synapse;
import io.kamax.mxisd.backend.sql.generic.GenericSqlDirectoryProvider;
import io.kamax.mxisd.config.MatrixConfig;
import io.kamax.mxisd.config.sql.generic.GenericSqlProviderConfig;
import io.kamax.mxisd.config.sql.synapse.SynapseSqlProviderConfig;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.Objects;
@Component
public class SynapseSqlDirectoryProvider extends GenericSqlDirectoryProvider {
@Autowired
public SynapseSqlDirectoryProvider(SynapseSqlProviderConfig cfg, MatrixConfig mxCfg) {
super(cfg, mxCfg);
}
@Override
protected void setParameters(PreparedStatement stmt, String searchTerm) throws SQLException {
stmt.setString(1, "%" + searchTerm + "%");
}
@PostConstruct
public void build() {
if (!isEnabled()) {
return;
}
GenericSqlProviderConfig.Type queries = cfg.getDirectory().getQuery();
if (Objects.isNull(queries.getName().getValue())) {
queries.getName().setValue(SynapseQueries.findByDisplayName(cfg.getType(), mxCfg.getDomain()));
}
if (Objects.isNull(queries.getThreepid().getValue())) {
queries.getThreepid().setValue(SynapseQueries.findByThreePidAddress(cfg.getType(), mxCfg.getDomain()));
}
}
}

View File

@@ -1,36 +0,0 @@
/*
* mxisd - Matrix Identity Server Daemon
* 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.mxisd.backend.sql.synapse;
import io.kamax.mxisd.backend.sql.SqlProfileProvider;
import io.kamax.mxisd.config.sql.synapse.SynapseSqlProviderConfig;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class SynapseSqlProfileProvider extends SqlProfileProvider {
@Autowired
public SynapseSqlProfileProvider(SynapseSqlProviderConfig cfg) {
super(cfg);
}
}

View File

@@ -1,37 +0,0 @@
/*
* mxisd - Matrix Identity Server Daemon
* 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.mxisd.backend.sql.synapse;
import io.kamax.mxisd.backend.sql.SqlThreePidProvider;
import io.kamax.mxisd.config.MatrixConfig;
import io.kamax.mxisd.config.sql.synapse.SynapseSqlProviderConfig;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class SynapseSqlThreePidProvider extends SqlThreePidProvider {
@Autowired
public SynapseSqlThreePidProvider(SynapseSqlProviderConfig cfg, MatrixConfig mxCfg) {
super(cfg, mxCfg);
}
}

View File

@@ -1,49 +0,0 @@
/*
* mxisd - Matrix Identity Server Daemon
* 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.mxisd.config;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
import java.util.Objects;
@Configuration
@ConfigurationProperties(prefix = "lookup.bulk")
public class BulkLookupConfig {
private Boolean enabled;
public Boolean getEnabled() {
return enabled;
}
public void setEnabled(Boolean enabled) {
this.enabled = enabled;
}
public void build() {
if (Objects.isNull(enabled)) {
enabled = true;
}
}
}

View File

@@ -25,8 +25,6 @@ import org.slf4j.LoggerFactory;
import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import javax.annotation.PostConstruct;
@Configuration @Configuration
@ConfigurationProperties("directory") @ConfigurationProperties("directory")
public class DirectoryConfig { public class DirectoryConfig {
@@ -36,7 +34,6 @@ public class DirectoryConfig {
public static class Exclude { public static class Exclude {
private boolean homeserver; private boolean homeserver;
private boolean threepid;
public boolean getHomeserver() { public boolean getHomeserver() {
return homeserver; return homeserver;
@@ -47,14 +44,6 @@ public class DirectoryConfig {
return this; return this;
} }
public boolean getThreepid() {
return threepid;
}
public void setThreepid(boolean threepid) {
this.threepid = threepid;
}
} }
private Exclude exclude = new Exclude(); private Exclude exclude = new Exclude();
@@ -67,12 +56,4 @@ public class DirectoryConfig {
this.exclude = exclude; this.exclude = exclude;
} }
@PostConstruct
public void buid() {
log.info("--- Directory config ---");
log.info("Exclude:");
log.info("\tHomeserver: {}", getExclude().getHomeserver());
log.info("\t3PID: {}", getExclude().getThreepid());
}
} }

View File

@@ -0,0 +1,107 @@
/*
* mxisd - Matrix Identity Server Daemon
* 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.mxisd.config;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
import javax.annotation.PostConstruct;
@Configuration
@ConfigurationProperties("google")
public class GoogleConfig {
public static class Client {
private String id;
private String secret;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getSecret() {
return secret;
}
public void setSecret(String secret) {
this.secret = secret;
}
}
private final Logger log = LoggerFactory.getLogger(GoogleConfig.class);
private boolean enabled;
private Client client = new Client();
private String medium = "io.kamax.google.id";
private String prefix = "google_";
public boolean isEnabled() {
return enabled;
}
public void setEnabled(boolean enabled) {
this.enabled = enabled;
}
public Client getClient() {
return client;
}
public void setClient(Client client) {
this.client = client;
}
public String getMedium() {
return medium;
}
public void setMedium(String medium) {
this.medium = medium;
}
public String getPrefix() {
return prefix;
}
public void setPrefix(String prefix) {
this.prefix = prefix;
}
@PostConstruct
public void build() {
log.info("--- Google config ---");
log.info("Enabled: {}", isEnabled());
log.info("Client ID: {}", getClient().getId());
log.info("Client secret set? {}", StringUtils.isNotBlank(getClient().getSecret()));
log.info("3PID medium: {}", getMedium());
log.info("MXID prefix: {}", getPrefix());
}
}

View File

@@ -1,108 +0,0 @@
/*
* mxisd - Matrix Identity Server Daemon
* 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.mxisd.config;
import org.apache.commons.lang.StringUtils;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
import javax.annotation.PostConstruct;
import java.net.MalformedURLException;
import java.net.URL;
@Configuration
@ConfigurationProperties("matrix.listener")
public class ListenerConfig {
public static class Token {
private String as;
private String hs;
public String getAs() {
return as;
}
public void setAs(String as) {
this.as = as;
}
public String getHs() {
return hs;
}
public void setHs(String hs) {
this.hs = hs;
}
}
private transient URL csUrl;
private String url;
private String localpart;
private Token token = new Token();
public URL getUrl() {
return csUrl;
}
public void setUrl(String url) {
this.url = url;
}
public String getLocalpart() {
return localpart;
}
public void setLocalpart(String localpart) {
this.localpart = localpart;
}
public Token getToken() {
return token;
}
public void setToken(Token token) {
this.token = token;
}
@PostConstruct
public void build() throws MalformedURLException {
if (StringUtils.isBlank(url)) {
return;
}
csUrl = new URL(url);
if (StringUtils.isBlank(getLocalpart())) {
throw new IllegalArgumentException("localpart for matrix listener is not set");
}
if (StringUtils.isBlank(getToken().getAs())) {
throw new IllegalArgumentException("AS token is not set");
}
if (StringUtils.isBlank(getToken().getHs())) {
throw new IllegalArgumentException("HS token is not set");
}
}
}

View File

@@ -1,8 +1,8 @@
/* /*
* mxisd - Matrix Identity Server Daemon * mxisd - Matrix Identity Server Daemon
* Copyright (C) 2017 Kamax Sarl * Copyright (C) 2017 Maxime Dor
* *
* https://www.kamax.io/ * https://max.kamax.io/
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as * it under the terms of the GNU Affero General Public License as
@@ -234,19 +234,6 @@ public abstract class LdapConfig {
} }
public static class Profile {
private String filter;
public String getFilter() {
return filter;
}
public void setFilter(String filter) {
this.filter = filter;
}
}
private Logger log = LoggerFactory.getLogger(LdapConfig.class); private Logger log = LoggerFactory.getLogger(LdapConfig.class);
@@ -258,7 +245,6 @@ public abstract class LdapConfig {
private Auth auth; private Auth auth;
private Directory directory; private Directory directory;
private Identity identity; private Identity identity;
private Profile profile = new Profile();
protected abstract String getConfigName(); protected abstract String getConfigName();
@@ -318,14 +304,6 @@ public abstract class LdapConfig {
this.identity = identity; this.identity = identity;
} }
public Profile getProfile() {
return profile;
}
public void setProfile(Profile profile) {
this.profile = profile;
}
@PostConstruct @PostConstruct
public void build() { public void build() {
log.info("--- " + getConfigName() + " Config ---"); log.info("--- " + getConfigName() + " Config ---");
@@ -378,13 +356,9 @@ public abstract class LdapConfig {
getAuth().setFilter(StringUtils.defaultIfBlank(getAuth().getFilter(), getFilter())); getAuth().setFilter(StringUtils.defaultIfBlank(getAuth().getFilter(), getFilter()));
getDirectory().setFilter(StringUtils.defaultIfBlank(getDirectory().getFilter(), getFilter())); getDirectory().setFilter(StringUtils.defaultIfBlank(getDirectory().getFilter(), getFilter()));
getIdentity().setFilter(StringUtils.defaultIfBlank(getIdentity().getFilter(), getFilter())); getIdentity().setFilter(StringUtils.defaultIfBlank(getIdentity().getFilter(), getFilter()));
if (StringUtils.isBlank(getProfile().getFilter())) {
getProfile().setFilter(getFilter());
}
log.info("Host: {}", connection.getHost()); log.info("Host: {}", connection.getHost());
log.info("Port: {}", connection.getPort()); log.info("Port: {}", connection.getPort());
log.info("TLS: {}", connection.isTls());
log.info("Bind DN: {}", connection.getBindDn()); log.info("Bind DN: {}", connection.getBindDn());
log.info("Base DN: {}", connection.getBaseDn()); log.info("Base DN: {}", connection.getBaseDn());
@@ -392,7 +366,6 @@ public abstract class LdapConfig {
log.info("Auth: {}", GsonUtil.get().toJson(auth)); log.info("Auth: {}", GsonUtil.get().toJson(auth));
log.info("Directory: {}", GsonUtil.get().toJson(directory)); log.info("Directory: {}", GsonUtil.get().toJson(directory));
log.info("Identity: {}", GsonUtil.get().toJson(identity)); log.info("Identity: {}", GsonUtil.get().toJson(identity));
log.info("Profile: {}", GsonUtil.get().toJson(profile));
} }
} }

View File

@@ -30,7 +30,6 @@ public class MemoryIdentityConfig {
private String username; private String username;
private String password; private String password;
private String displayName;
private List<MemoryThreePid> threepids = new ArrayList<>(); private List<MemoryThreePid> threepids = new ArrayList<>();
private List<String> roles = new ArrayList<>(); private List<String> roles = new ArrayList<>();
@@ -50,14 +49,6 @@ public class MemoryIdentityConfig {
this.password = password; this.password = password;
} }
public String getDisplayName() {
return displayName;
}
public void setDisplayName(String displayName) {
this.displayName = displayName;
}
public List<MemoryThreePid> getThreepids() { public List<MemoryThreePid> getThreepids() {
return threepids; return threepids;
} }

View File

@@ -1,8 +1,8 @@
/* /*
* mxisd - Matrix Identity Server Daemon * mxisd - Matrix Identity Server Daemon
* Copyright (C) 2017 Kamax Sarl * Copyright (C) 2017 Maxime Dor
* *
* https://www.kamax.io/ * https://max.kamax.io/
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as * it under the terms of the GNU Affero General Public License as
@@ -18,9 +18,8 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
package io.kamax.mxisd.config.sql.generic; package io.kamax.mxisd.config.sql;
import io.kamax.mxisd.config.sql.SqlConfig;
import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary; import org.springframework.context.annotation.Primary;

View File

@@ -1,23 +1,3 @@
/*
* mxisd - Matrix Identity Server Daemon
* 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.mxisd.config.sql; package io.kamax.mxisd.config.sql;
import io.kamax.mxisd.util.GsonUtil; import io.kamax.mxisd.util.GsonUtil;
@@ -27,11 +7,10 @@ import org.slf4j.LoggerFactory;
import javax.annotation.PostConstruct; import javax.annotation.PostConstruct;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.Objects;
public abstract class SqlConfig { public abstract class SqlConfig {
private transient Logger log = LoggerFactory.getLogger(SqlConfig.class); private Logger log = LoggerFactory.getLogger(SqlConfig.class);
public static class Query { public static class Query {
@@ -157,20 +136,6 @@ public abstract class SqlConfig {
} }
public static class ProfileDisplayName {
private String query;
public String getQuery() {
return query;
}
public void setQuery(String query) {
this.query = query;
}
}
public static class ProfileThreepids { public static class ProfileThreepids {
private String query; private String query;
@@ -187,26 +152,8 @@ public abstract class SqlConfig {
public static class Profile { public static class Profile {
private Boolean enabled;
private ProfileDisplayName displayName = new ProfileDisplayName();
private ProfileThreepids threepid = new ProfileThreepids(); private ProfileThreepids threepid = new ProfileThreepids();
public Boolean isEnabled() {
return enabled;
}
public void setEnabled(Boolean enabled) {
this.enabled = enabled;
}
public ProfileDisplayName getDisplayName() {
return displayName;
}
public void setDisplayName(ProfileDisplayName displayName) {
this.displayName = displayName;
}
public ProfileThreepids getThreepid() { public ProfileThreepids getThreepid() {
return threepid; return threepid;
} }
@@ -283,8 +230,7 @@ public abstract class SqlConfig {
protected abstract String getProviderName(); protected abstract String getProviderName();
@PostConstruct protected void doBuild() {
public void build() {
if (getAuth().isEnabled() == null) { if (getAuth().isEnabled() == null) {
getAuth().setEnabled(isEnabled()); getAuth().setEnabled(isEnabled());
} }
@@ -296,15 +242,14 @@ public abstract class SqlConfig {
if (getIdentity().isEnabled() == null) { if (getIdentity().isEnabled() == null) {
getIdentity().setEnabled(isEnabled()); getIdentity().setEnabled(isEnabled());
} }
if (Objects.isNull(getProfile().isEnabled())) {
getProfile().setEnabled(isEnabled());
}
} }
protected void printConfig() { @PostConstruct
public void build() {
log.info("--- " + getProviderName() + " Provider config ---"); log.info("--- " + getProviderName() + " Provider config ---");
doBuild();
log.info("Enabled: {}", isEnabled()); log.info("Enabled: {}", isEnabled());
if (isEnabled()) { if (isEnabled()) {
log.info("Type: {}", getType()); log.info("Type: {}", getType());
@@ -314,12 +259,7 @@ public abstract class SqlConfig {
log.info("Identity type: {}", getIdentity().getType()); log.info("Identity type: {}", getIdentity().getType());
log.info("3PID mapping query: {}", getIdentity().getQuery()); log.info("3PID mapping query: {}", getIdentity().getQuery());
log.info("Identity medium queries: {}", GsonUtil.build().toJson(getIdentity().getMedium())); log.info("Identity medium queries: {}", GsonUtil.build().toJson(getIdentity().getMedium()));
log.info("Profile:"); log.info("Profile 3PID query: {}", getProfile().getThreepid().getQuery());
log.info("\tEnabled: {}", getProfile().isEnabled());
if (getProfile().isEnabled()) {
log.info("\tDisplay name query: {}", getProfile().getDisplayName().getQuery());
log.info("\tProfile 3PID query: {}", getProfile().getThreepid().getQuery());
}
} }
} }

View File

@@ -1,8 +1,8 @@
/* /*
* mxisd - Matrix Identity Server Daemon * mxisd - Matrix Identity Server Daemon
* Copyright (C) 2017 Kamax Sarl * Copyright (C) 2017 Maxime Dor
* *
* https://www.kamax.io/ * https://max.kamax.io/
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as * it under the terms of the GNU Affero General Public License as
@@ -20,7 +20,6 @@
package io.kamax.mxisd.config.sql.synapse; package io.kamax.mxisd.config.sql.synapse;
import io.kamax.mxisd.backend.sql.synapse.SynapseQueries;
import io.kamax.mxisd.config.sql.SqlConfig; import io.kamax.mxisd.config.sql.SqlConfig;
import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.StringUtils;
import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.boot.context.properties.ConfigurationProperties;
@@ -39,26 +38,22 @@ public class SynapseSqlProviderConfig extends SqlConfig {
@PostConstruct @PostConstruct
public void doBuild() { public void doBuild() {
getAuth().setEnabled(false); // Synapse does the auth, we only act as a directory/identity service. super.doBuild();
// FIXME check that the DB is not the mxisd one // FIXME check that the DB is not the mxisd one
// See https://matrix.to/#/!NPRUEisLjcaMtHIzDr:kamax.io/$1509377583327omXkC:kamax.io // See https://matrix.to/#/!NPRUEisLjcaMtHIzDr:kamax.io/$1509377583327omXkC:kamax.io
if (getIdentity().isEnabled() && StringUtils.isBlank(getIdentity().getType())) { getAuth().setEnabled(false); // Synapse does the auth, we only act as a directory/identity service.
getIdentity().setType("mxid");
getIdentity().setQuery("SELECT user_id AS uid FROM user_threepids WHERE medium = ? AND address = ?"); if (getDirectory().isEnabled()) {
//FIXME set default queries for name and threepid
} }
if (getProfile().isEnabled()) { if (getIdentity().isEnabled()) {
if (StringUtils.isBlank(getProfile().getDisplayName().getQuery())) { if (StringUtils.isBlank(getIdentity().getType())) {
getProfile().getDisplayName().setQuery(SynapseQueries.getDisplayName()); getIdentity().setType("mxid");
} getIdentity().setQuery("SELECT user_id AS uid FROM user_threepids WHERE medium = ? AND address = ?");
if (StringUtils.isBlank(getProfile().getThreepid().getQuery())) {
getProfile().getThreepid().setQuery(SynapseQueries.getThreepids());
} }
} }
printConfig();
} }
} }

View File

@@ -1,8 +1,8 @@
/* /*
* mxisd - Matrix Identity Server Daemon * mxisd - Matrix Identity Server Daemon
* Copyright (C) 2017 Kamax Sarl * Copyright (C) 2017 Maxime Dor
* *
* https://www.kamax.io/ * https://max.kamax.io/
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as * it under the terms of the GNU Affero General Public License as
@@ -28,8 +28,6 @@ import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import javax.annotation.PostConstruct; import javax.annotation.PostConstruct;
import java.util.HashMap;
import java.util.Map;
@Configuration @Configuration
@ConfigurationProperties("notification.handlers.sendgrid") @ConfigurationProperties("notification.handlers.sendgrid")
@@ -144,15 +142,6 @@ public class EmailSendGridConfig {
private EmailTemplate invite = new EmailTemplate(); private EmailTemplate invite = new EmailTemplate();
private TemplateSession session = new TemplateSession(); private TemplateSession session = new TemplateSession();
private Map<String, EmailTemplate> generic = new HashMap<>();
public Map<String, EmailTemplate> getGeneric() {
return generic;
}
public void setGeneric(Map<String, EmailTemplate> generic) {
this.generic = generic;
}
public EmailTemplate getInvite() { public EmailTemplate getInvite() {
return invite; return invite;

View File

@@ -1,8 +1,8 @@
/* /*
* mxisd - Matrix Identity Server Daemon * mxisd - Matrix Identity Server Daemon
* Copyright (C) 2017 Kamax Sarl * Copyright (C) 2017 Maxime Dor
* *
* https://www.kamax.io/ * https://max.kamax.io/
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as * it under the terms of the GNU Affero General Public License as
@@ -22,9 +22,6 @@ package io.kamax.mxisd.config.threepid.medium;
import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.StringUtils;
import java.util.HashMap;
import java.util.Map;
public class GenericTemplateConfig { public class GenericTemplateConfig {
private static final String classpathPrefix = "classpath:"; private static final String classpathPrefix = "classpath:";
@@ -76,7 +73,6 @@ public class GenericTemplateConfig {
private String invite; private String invite;
private Session session = new Session(); private Session session = new Session();
private Map<String, String> generic = new HashMap<>();
public String getInvite() { public String getInvite() {
return invite; return invite;
@@ -90,12 +86,4 @@ public class GenericTemplateConfig {
return session; return session;
} }
public Map<String, String> getGeneric() {
return generic;
}
public void setGeneric(Map<String, String> generic) {
this.generic = generic;
}
} }

View File

@@ -105,7 +105,6 @@ public class WordpressConfig {
private String type; private String type;
private String connection; private String connection;
private String tablePrefix;
private Query query; private Query query;
public String getType() { public String getType() {
@@ -124,14 +123,6 @@ public class WordpressConfig {
this.connection = connection; this.connection = connection;
} }
public String getTablePrefix() {
return tablePrefix;
}
public void setTablePrefix(String tablePrefix) {
this.tablePrefix = tablePrefix;
}
public Query getQuery() { public Query getQuery() {
return query; return query;
} }

View File

@@ -1,110 +0,0 @@
/*
* mxisd - Matrix Identity Server Daemon
* 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.mxisd.controller.app.v1;
import com.google.gson.JsonObject;
import io.kamax.matrix.json.GsonUtil;
import io.kamax.mxisd.as.AppServiceHandler;
import io.kamax.mxisd.config.ListenerConfig;
import io.kamax.mxisd.exception.HttpMatrixException;
import io.kamax.mxisd.exception.NotAllowedException;
import io.kamax.mxisd.util.GsonParser;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.List;
import static org.springframework.web.bind.annotation.RequestMethod.GET;
import static org.springframework.web.bind.annotation.RequestMethod.PUT;
@RestController
@CrossOrigin
@RequestMapping(produces = MediaType.APPLICATION_JSON_VALUE)
public class AppServiceController {
private final Logger log = LoggerFactory.getLogger(AppServiceController.class);
private final ListenerConfig cfg;
private final String notFoundBody;
private final GsonParser parser;
private final AppServiceHandler handler;
@Autowired
public AppServiceController(ListenerConfig cfg, AppServiceHandler handler) {
this.notFoundBody = GsonUtil.get().toJson(GsonUtil.makeObj("errcode", "io.kamax.mxisd.AS_NOT_FOUND"));
this.parser = new GsonParser();
this.cfg = cfg;
this.handler = handler;
}
private void validateToken(String token) {
if (StringUtils.isBlank(token)) {
throw new HttpMatrixException(401, "M_UNAUTHORIZED", "No HS token");
}
if (!StringUtils.equals(cfg.getToken().getHs(), token)) {
throw new NotAllowedException("Invalid HS token");
}
}
@RequestMapping(value = "/rooms/**", method = GET)
public String getRoom(HttpServletResponse res, @RequestParam(name = "access_token", required = false) String token) {
validateToken(token);
res.setStatus(404);
return notFoundBody;
}
@RequestMapping(value = "/users/**", method = GET)
public String getUser(HttpServletResponse res, @RequestParam(name = "access_token", required = false) String token) {
validateToken(token);
res.setStatus(404);
return notFoundBody;
}
@RequestMapping(value = "/transactions/{txnId:.+}", method = PUT)
public Object getTransaction(
HttpServletRequest request,
@RequestParam(name = "access_token", required = false) String token,
@PathVariable String txnId) {
try {
validateToken(token);
log.info("Processing transaction {}", txnId);
List<JsonObject> events = GsonUtil.asList(GsonUtil.getArray(parser.parse(request.getInputStream()), "events"), JsonObject.class);
handler.processTransaction(events);
return "{}";
} catch (Throwable e) {
log.warn("Unable to properly process transaction", e);
}
return "{}";
}
}

View File

@@ -0,0 +1,159 @@
/*
* mxisd - Matrix Identity Server Daemon
* 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.mxisd.controller.auth.v1;
import com.google.api.client.googleapis.auth.oauth2.GoogleIdToken;
import com.google.gson.Gson;
import com.google.gson.JsonObject;
import io.kamax.matrix.MatrixID;
import io.kamax.matrix.ThreePid;
import io.kamax.matrix._MatrixID;
import io.kamax.mxisd.backend.google.GoogleProviderBackend;
import io.kamax.mxisd.dns.ClientDnsOverwrite;
import io.kamax.mxisd.profile.ProfileManager;
import io.kamax.mxisd.util.GsonParser;
import io.kamax.mxisd.util.GsonUtil;
import io.kamax.mxisd.util.RestClientUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.net.URI;
import java.security.GeneralSecurityException;
import java.util.ArrayList;
import java.util.List;
@RestController
@CrossOrigin
@RequestMapping(produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
public class RegistrationController {
private final Logger log = LoggerFactory.getLogger(RegistrationController.class);
private final String registerV1Url = "/_matrix/client/r0/register";
private GoogleProviderBackend google;
private ProfileManager pMgr;
private ClientDnsOverwrite dns;
private CloseableHttpClient client;
private Gson gson;
private GsonParser parser;
@Autowired
public RegistrationController(GoogleProviderBackend google, ProfileManager pMgr, ClientDnsOverwrite dns, CloseableHttpClient client) {
this.google = google;
this.pMgr = pMgr;
this.dns = dns;
this.client = client;
this.gson = GsonUtil.build();
this.parser = new GsonParser(gson);
}
private String resolveProxyUrl(HttpServletRequest req) {
URI target = URI.create(req.getRequestURL().toString());
URIBuilder builder = dns.transform(target);
String urlToLogin = builder.toString();
log.info("Proxy resolution: {} to {}", target.toString(), urlToLogin);
return urlToLogin;
}
@RequestMapping(path = registerV1Url, method = RequestMethod.GET)
public String getLogin(HttpServletRequest req, HttpServletResponse res) {
try (CloseableHttpResponse hsResponse = client.execute(new HttpGet(resolveProxyUrl(req)))) {
res.setStatus(hsResponse.getStatusLine().getStatusCode());
return EntityUtils.toString(hsResponse.getEntity());
} catch (IOException e) {
throw new RuntimeException(e);
}
}
@RequestMapping(path = registerV1Url, method = RequestMethod.POST)
public String register(HttpServletRequest req, HttpServletResponse res) {
List<ThreePid> ids = new ArrayList<>();
try {
JsonObject reqJsonObject = parser.parse(req.getInputStream());
GsonUtil.findObj(reqJsonObject, "auth").ifPresent(auth -> {
GsonUtil.findPrimitive(auth, "type").ifPresent(type -> {
if (StringUtils.equals("io.kamax.google.auth", type.getAsString())) {
log.info("Got registration attempt with Google account");
if (!auth.has("googleId")) {
throw new IllegalArgumentException("Google ID is missing");
}
String gId = auth.get("googleId").getAsString();
try {
GoogleIdToken token = google.extractToken(reqJsonObject.get("password").getAsString()).orElseThrow(() -> new IllegalArgumentException("Google ID Token is missing or invalid"));
if (!StringUtils.equals(gId, token.getPayload().getSubject())) {
throw new IllegalArgumentException("Google ID does not match token");
}
log.info("Google ID: {}", gId);
ids.addAll(google.extractThreepids(token));
auth.addProperty("type", "m.login.dummy");
auth.remove("googleId");
reqJsonObject.addProperty("username", "g-" + gId);
reqJsonObject.addProperty("password", "");
} catch (IOException | GeneralSecurityException e) {
throw new RuntimeException(e);
}
}
});
});
log.info("Sending body: {}", gson.toJson(reqJsonObject));
HttpPost httpPost = RestClientUtils.post(resolveProxyUrl(req), gson, reqJsonObject);
try (CloseableHttpResponse httpResponse = client.execute(httpPost)) {
int sc = httpResponse.getStatusLine().getStatusCode();
String body = EntityUtils.toString(httpResponse.getEntity());
JsonObject json = parser.parse(body);
if (sc == 200 && json.has("user_id")) {
// Required here as synapse doesn't call pass provider on register
log.info("User was registered, adding 3PIDs");
_MatrixID mxid = new MatrixID(json.get("user_id").getAsString());
for (ThreePid tpid : ids) {
pMgr.addThreepid(mxid, tpid);
}
}
res.setStatus(sc);
return body;
}
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}

View File

@@ -20,8 +20,8 @@
package io.kamax.mxisd.controller.directory.v1.io; package io.kamax.mxisd.controller.directory.v1.io;
import java.util.HashSet; import java.util.ArrayList;
import java.util.Set; import java.util.List;
public class UserDirectorySearchResult { public class UserDirectorySearchResult {
@@ -55,31 +55,10 @@ public class UserDirectorySearchResult {
this.userId = userId; this.userId = userId;
} }
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Result result = (Result) o;
if (displayName != null ? !displayName.equals(result.displayName) : result.displayName != null)
return false;
if (avatarUrl != null ? !avatarUrl.equals(result.avatarUrl) : result.avatarUrl != null) return false;
return userId.equals(result.userId);
}
@Override
public int hashCode() {
int result = displayName != null ? displayName.hashCode() : 0;
result = 31 * result + (avatarUrl != null ? avatarUrl.hashCode() : 0);
result = 31 * result + userId.hashCode();
return result;
}
} }
private boolean limited; private boolean limited;
private Set<Result> results = new HashSet<>(); private List<Result> results = new ArrayList<>();
public boolean isLimited() { public boolean isLimited() {
return limited; return limited;
@@ -89,11 +68,11 @@ public class UserDirectorySearchResult {
this.limited = limited; this.limited = limited;
} }
public Set<Result> getResults() { public List<Result> getResults() {
return results; return results;
} }
public void setResults(Set<Result> results) { public void setResults(List<Result> results) {
this.results = results; this.results = results;
} }

View File

@@ -75,10 +75,6 @@ public class DirectoryManager {
} }
public UserDirectorySearchResult search(URI target, String accessToken, String query) { public UserDirectorySearchResult search(URI target, String accessToken, String query) {
if (StringUtils.startsWith(query, "@")) {
query = query.substring(1);
}
log.info("Performing search for '{}'", query); log.info("Performing search for '{}'", query);
log.info("Original request URL: {}", target); log.info("Original request URL: {}", target);
UserDirectorySearchResult result = new UserDirectorySearchResult(); UserDirectorySearchResult result = new UserDirectorySearchResult();
@@ -129,15 +125,11 @@ public class DirectoryManager {
result.setLimited(true); result.setLimited(true);
} }
if (cfg.getExclude().getThreepid()) { resultProvider = provider.searchBy3pid(query);
log.info("Skipping 3PID data, disabled in config"); log.info("Threepid: found {} match(es) for '{}'", resultProvider.getResults().size(), query);
} else { result.getResults().addAll(resultProvider.getResults());
resultProvider = provider.searchBy3pid(query); if (resultProvider.isLimited()) {
log.info("Threepid: found {} match(es) for '{}'", resultProvider.getResults().size(), query); result.setLimited(true);
result.getResults().addAll(resultProvider.getResults());
if (resultProvider.isLimited()) {
result.setLimited(true);
}
} }
} }

View File

@@ -1,8 +1,8 @@
/* /*
* mxisd - Matrix Identity Server Daemon * mxisd - Matrix Identity Server Daemon
* Copyright (C) 2017 Kamax Sarl * Copyright (C) 2017 Maxime Dor
* *
* https://www.kamax.io/ * https://max.kamax.io/
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as * it under the terms of the GNU Affero General Public License as
@@ -228,7 +228,7 @@ public class InvitationManager {
log.info("Invite is already pending for {}:{}, returning data", invitation.getMedium(), invitation.getAddress()); log.info("Invite is already pending for {}:{}, returning data", invitation.getMedium(), invitation.getAddress());
if (!StringUtils.equals(invitation.getRoomId(), reply.getInvite().getRoomId())) { if (!StringUtils.equals(invitation.getRoomId(), reply.getInvite().getRoomId())) {
log.info("Sending new notification as new invite room {} is different from the original {}", invitation.getRoomId(), reply.getInvite().getRoomId()); log.info("Sending new notification as new invite room {} is different from the original {}", invitation.getRoomId(), reply.getInvite().getRoomId());
notifMgr.sendForReply(new ThreePidInviteReply(reply.getId(), invitation, reply.getToken(), reply.getDisplayName())); notifMgr.sendForInvite(new ThreePidInviteReply(reply.getId(), invitation, reply.getToken(), reply.getDisplayName()));
} else { } else {
// FIXME we should check attempt and send if bigger // FIXME we should check attempt and send if bigger
} }
@@ -247,7 +247,7 @@ public class InvitationManager {
reply = new ThreePidInviteReply(invId, invitation, token, displayName); reply = new ThreePidInviteReply(invId, invitation, token, displayName);
log.info("Performing invite to {}:{}", invitation.getMedium(), invitation.getAddress()); log.info("Performing invite to {}:{}", invitation.getMedium(), invitation.getAddress());
notifMgr.sendForReply(reply); notifMgr.sendForInvite(reply);
log.info("Storing invite under ID {}", invId); log.info("Storing invite under ID {}", invId);
storage.insertInvite(reply); storage.insertInvite(reply);
@@ -319,13 +319,9 @@ public class InvitationManager {
CloseableHttpResponse response = client.execute(req); CloseableHttpResponse response = client.execute(req);
int statusCode = response.getStatusLine().getStatusCode(); int statusCode = response.getStatusLine().getStatusCode();
log.info("Answer code: {}", statusCode); log.info("Answer code: {}", statusCode);
if (statusCode >= 300 && statusCode != 403) { if (statusCode >= 300) {
log.warn("Answer body: {}", IOUtils.toString(response.getEntity().getContent(), StandardCharsets.UTF_8)); log.warn("Answer body: {}", IOUtils.toString(response.getEntity().getContent(), StandardCharsets.UTF_8));
} else { } else {
if (statusCode == 403) {
log.info("Invite was obsolete");
}
invitations.remove(getId(reply.getInvite())); invitations.remove(getId(reply.getInvite()));
storage.deleteInvite(reply.getId()); storage.deleteInvite(reply.getId());
log.info("Removed invite from internal store"); log.info("Removed invite from internal store");

View File

@@ -21,7 +21,6 @@
package io.kamax.mxisd.lookup.provider; package io.kamax.mxisd.lookup.provider;
import io.kamax.mxisd.config.ForwardConfig; import io.kamax.mxisd.config.ForwardConfig;
import io.kamax.mxisd.config.MatrixConfig;
import io.kamax.mxisd.lookup.SingleLookupReply; import io.kamax.mxisd.lookup.SingleLookupReply;
import io.kamax.mxisd.lookup.SingleLookupRequest; import io.kamax.mxisd.lookup.SingleLookupRequest;
import io.kamax.mxisd.lookup.ThreePidMapping; import io.kamax.mxisd.lookup.ThreePidMapping;
@@ -43,9 +42,6 @@ class ForwarderProvider implements IThreePidProvider {
@Autowired @Autowired
private ForwardConfig cfg; private ForwardConfig cfg;
@Autowired
private MatrixConfig mxCfg;
@Autowired @Autowired
private IRemoteIdentityServerFetcher fetcher; private IRemoteIdentityServerFetcher fetcher;
@@ -66,13 +62,10 @@ class ForwarderProvider implements IThreePidProvider {
@Override @Override
public Optional<SingleLookupReply> find(SingleLookupRequest request) { public Optional<SingleLookupReply> find(SingleLookupRequest request) {
for (String label : cfg.getServers()) { for (String root : cfg.getServers()) {
for (String srv : mxCfg.getIdentity().getServers(label)) { Optional<SingleLookupReply> answer = fetcher.find(root, request);
log.info("Using forward server {}", srv); if (answer.isPresent()) {
Optional<SingleLookupReply> answer = fetcher.find(srv, request); return answer;
if (answer.isPresent()) {
return answer;
}
} }
} }
@@ -84,15 +77,13 @@ class ForwarderProvider implements IThreePidProvider {
List<ThreePidMapping> mappingsToDo = new ArrayList<>(mappings); List<ThreePidMapping> mappingsToDo = new ArrayList<>(mappings);
List<ThreePidMapping> mappingsFoundGlobal = new ArrayList<>(); List<ThreePidMapping> mappingsFoundGlobal = new ArrayList<>();
for (String label : cfg.getServers()) { for (String root : cfg.getServers()) {
for (String srv : mxCfg.getIdentity().getServers(label)) { log.info("{} mappings remaining: {}", mappingsToDo.size(), mappingsToDo);
log.info("{} mappings remaining: {}", mappingsToDo.size(), mappingsToDo); log.info("Querying {}", root);
log.info("Querying {}", srv); List<ThreePidMapping> mappingsFound = fetcher.find(root, mappingsToDo);
List<ThreePidMapping> mappingsFound = fetcher.find(srv, mappingsToDo); log.info("{} returned {} mappings", root, mappingsFound.size());
log.info("{} returned {} mappings", srv, mappingsFound.size()); mappingsFoundGlobal.addAll(mappingsFound);
mappingsFoundGlobal.addAll(mappingsFound); mappingsToDo.removeAll(mappingsFound);
mappingsToDo.removeAll(mappingsFound);
}
} }
return mappingsFoundGlobal; return mappingsFoundGlobal;

View File

@@ -23,7 +23,6 @@ package io.kamax.mxisd.lookup.provider;
import com.google.gson.Gson; import com.google.gson.Gson;
import com.google.gson.JsonObject; import com.google.gson.JsonObject;
import com.google.gson.JsonParseException; import com.google.gson.JsonParseException;
import io.kamax.matrix.json.GsonUtil;
import io.kamax.mxisd.controller.identity.v1.ClientBulkLookupRequest; import io.kamax.mxisd.controller.identity.v1.ClientBulkLookupRequest;
import io.kamax.mxisd.exception.InvalidResponseJsonException; import io.kamax.mxisd.exception.InvalidResponseJsonException;
import io.kamax.mxisd.lookup.SingleLookupReply; import io.kamax.mxisd.lookup.SingleLookupReply;
@@ -34,20 +33,18 @@ import io.kamax.mxisd.matrix.IdentityServerUtils;
import io.kamax.mxisd.util.GsonParser; import io.kamax.mxisd.util.GsonParser;
import io.kamax.mxisd.util.RestClientUtils; import io.kamax.mxisd.util.RestClientUtils;
import org.apache.http.client.methods.CloseableHttpResponse; import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost; import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.util.EntityUtils; import org.apache.http.impl.client.HttpClients;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy; import org.springframework.context.annotation.Lazy;
import org.springframework.context.annotation.Scope; import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import java.io.IOException; import java.io.IOException;
import java.net.URISyntaxException; import java.net.HttpURLConnection;
import java.net.URL;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Optional; import java.util.Optional;
@@ -62,9 +59,6 @@ public class RemoteIdentityServerFetcher implements IRemoteIdentityServerFetcher
private Gson gson = new Gson(); private Gson gson = new Gson();
private GsonParser parser = new GsonParser(gson); private GsonParser parser = new GsonParser(gson);
@Autowired
private CloseableHttpClient client;
@Override @Override
public boolean isUsable(String remote) { public boolean isUsable(String remote) {
return IdentityServerUtils.isUsable(remote); return IdentityServerUtils.isUsable(remote);
@@ -75,40 +69,24 @@ public class RemoteIdentityServerFetcher implements IRemoteIdentityServerFetcher
log.info("Looking up {} 3PID {} using {}", request.getType(), request.getThreePid(), remote); log.info("Looking up {} 3PID {} using {}", request.getType(), request.getThreePid(), remote);
try { try {
URIBuilder b = new URIBuilder(remote); HttpURLConnection rootSrvConn = (HttpURLConnection) new URL(
b.setPath("/_matrix/identity/api/v1/lookup"); remote + "/_matrix/identity/api/v1/lookup?medium=" + request.getType() + "&address=" + request.getThreePid()
b.addParameter("medium", request.getType()); ).openConnection();
b.addParameter("address", request.getThreePid()); JsonObject obj = parser.parse(rootSrvConn.getInputStream());
HttpGet req = new HttpGet(b.build()); if (obj.has("address")) {
log.info("Found 3PID mapping: {}", gson.toJson(obj));
try (CloseableHttpResponse res = client.execute(req)) { return Optional.of(SingleLookupReply.fromRecursive(request, gson.toJson(obj)));
int statusCode = res.getStatusLine().getStatusCode();
String body = EntityUtils.toString(res.getEntity());
if (statusCode != 200) {
log.warn("Remote returned status code {}", statusCode);
log.warn("Body: {}", body);
return Optional.empty();
}
JsonObject obj = GsonUtil.parseObj(body);
if (obj.has("address")) {
log.debug("Found 3PID mapping: {}", gson.toJson(obj));
return Optional.of(SingleLookupReply.fromRecursive(request, gson.toJson(obj)));
}
log.info("Empty 3PID mapping from {}", remote);
return Optional.empty();
} }
log.info("Empty 3PID mapping from {}", remote);
return Optional.empty();
} catch (IOException e) { } catch (IOException e) {
log.warn("Error looking up 3PID mapping {}: {}", request.getThreePid(), e.getMessage()); log.warn("Error looking up 3PID mapping {}: {}", request.getThreePid(), e.getMessage());
return Optional.empty(); return Optional.empty();
} catch (JsonParseException e) { } catch (JsonParseException e) {
log.warn("Invalid JSON answer from {}", remote); log.warn("Invalid JSON answer from {}", remote);
return Optional.empty(); return Optional.empty();
} catch (URISyntaxException e) {
log.warn("Invalid remote address: {}", e.getMessage(), e);
return Optional.empty();
} }
} }
@@ -120,15 +98,12 @@ public class RemoteIdentityServerFetcher implements IRemoteIdentityServerFetcher
mappingRequest.setMappings(mappings); mappingRequest.setMappings(mappings);
String url = remote + "/_matrix/identity/api/v1/bulk_lookup"; String url = remote + "/_matrix/identity/api/v1/bulk_lookup";
CloseableHttpClient client = HttpClients.createDefault();
try { try {
HttpPost request = RestClientUtils.post(url, mappingRequest); HttpPost request = RestClientUtils.post(url, mappingRequest);
try (CloseableHttpResponse response = client.execute(request)) { try (CloseableHttpResponse response = client.execute(request)) {
int statusCode = response.getStatusLine().getStatusCode(); if (response.getStatusLine().getStatusCode() != 200) {
String body = EntityUtils.toString(response.getEntity()); log.info("Could not perform lookup at {} due to HTTP return code: {}", url, response.getStatusLine().getStatusCode());
if (statusCode != 200) {
log.warn("Could not perform lookup at {} due to HTTP return code: {}", url, statusCode);
log.warn("Body: {}", body);
return mappingsFound; return mappingsFound;
} }

View File

@@ -21,7 +21,6 @@
package io.kamax.mxisd.lookup.strategy; package io.kamax.mxisd.lookup.strategy;
import edazdarevic.commons.net.CIDRUtils; import edazdarevic.commons.net.CIDRUtils;
import io.kamax.mxisd.config.BulkLookupConfig;
import io.kamax.mxisd.config.RecursiveLookupConfig; import io.kamax.mxisd.config.RecursiveLookupConfig;
import io.kamax.mxisd.exception.ConfigurationException; import io.kamax.mxisd.exception.ConfigurationException;
import io.kamax.mxisd.lookup.*; import io.kamax.mxisd.lookup.*;
@@ -35,7 +34,6 @@ import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct; import javax.annotation.PostConstruct;
import java.net.UnknownHostException; import java.net.UnknownHostException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Optional; import java.util.Optional;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@@ -46,16 +44,14 @@ public class RecursivePriorityLookupStrategy implements LookupStrategy {
private Logger log = LoggerFactory.getLogger(RecursivePriorityLookupStrategy.class); private Logger log = LoggerFactory.getLogger(RecursivePriorityLookupStrategy.class);
private RecursiveLookupConfig cfg; private RecursiveLookupConfig cfg;
private BulkLookupConfig bulkCfg;
private List<IThreePidProvider> providers; private List<IThreePidProvider> providers;
private IBridgeFetcher bridge; private IBridgeFetcher bridge;
private List<CIDRUtils> allowedCidr = new ArrayList<>(); private List<CIDRUtils> allowedCidr = new ArrayList<>();
@Autowired @Autowired
public RecursivePriorityLookupStrategy(RecursiveLookupConfig cfg, BulkLookupConfig bulkCfg, List<IThreePidProvider> providers, IBridgeFetcher bridge) { public RecursivePriorityLookupStrategy(RecursiveLookupConfig cfg, List<IThreePidProvider> providers, IBridgeFetcher bridge) {
this.cfg = cfg; this.cfg = cfg;
this.bulkCfg = bulkCfg;
this.bridge = bridge; this.bridge = bridge;
this.providers = providers.stream().filter(p -> { this.providers = providers.stream().filter(p -> {
log.info("3PID Provider {} is enabled: {}", p.getClass().getSimpleName(), p.isEnabled()); log.info("3PID Provider {} is enabled: {}", p.getClass().getSimpleName(), p.isEnabled());
@@ -197,10 +193,6 @@ public class RecursivePriorityLookupStrategy implements LookupStrategy {
@Override @Override
public List<ThreePidMapping> find(BulkLookupRequest request) { public List<ThreePidMapping> find(BulkLookupRequest request) {
if (!bulkCfg.getEnabled()) {
return Collections.emptyList();
}
List<ThreePidMapping> mapToDo = new ArrayList<>(request.getMappings()); List<ThreePidMapping> mapToDo = new ArrayList<>(request.getMappings());
List<ThreePidMapping> mapFoundAll = new ArrayList<>(); List<ThreePidMapping> mapFoundAll = new ArrayList<>();

View File

@@ -67,7 +67,7 @@ public class IdentityServerUtils {
log.info("{} is not an URL, using as-is", domainOrUrl); log.info("{} is not an URL, using as-is", domainOrUrl);
} }
log.info("Discovering Identity Server for {}", domainOrUrl); log.info("Discovery Identity Server for {}", domainOrUrl);
log.info("Performing SRV lookup"); log.info("Performing SRV lookup");
String lookupDns = getSrvRecordName(domainOrUrl); String lookupDns = getSrvRecordName(domainOrUrl);
log.info("Lookup name: {}", lookupDns); log.info("Lookup name: {}", lookupDns);
@@ -98,12 +98,10 @@ public class IdentityServerUtils {
if (isUsable(baseUrl)) { if (isUsable(baseUrl)) {
log.info("Found Identity Server for domain {} at {}", domainOrUrl, baseUrl); log.info("Found Identity Server for domain {} at {}", domainOrUrl, baseUrl);
return Optional.of(baseUrl); return Optional.of(baseUrl);
} else {
log.info("Found no Identity server for domain {} at {}", domainOrUrl, baseUrl);
} }
} }
log.info("Found no Identity server for domain {}", domainOrUrl); log.info("Found no Identity server for domain {} at {}");
return Optional.empty(); return Optional.empty();
} catch (TextParseException e) { } catch (TextParseException e) {
log.warn(domainOrUrl + " is not a valid domain name"); log.warn(domainOrUrl + " is not a valid domain name");

View File

@@ -1,8 +1,8 @@
/* /*
* mxisd - Matrix Identity Server Daemon * mxisd - Matrix Identity Server Daemon
* Copyright (C) 2017 Kamax Sarl * Copyright (C) 2017 Maxime Dor
* *
* https://www.kamax.io/ * https://max.kamax.io/
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as * it under the terms of the GNU Affero General Public License as
@@ -20,7 +20,6 @@
package io.kamax.mxisd.notification; package io.kamax.mxisd.notification;
import io.kamax.mxisd.as.IMatrixIdInvite;
import io.kamax.mxisd.invitation.IThreePidInviteReply; import io.kamax.mxisd.invitation.IThreePidInviteReply;
import io.kamax.mxisd.threepid.session.IThreePidSession; import io.kamax.mxisd.threepid.session.IThreePidSession;
@@ -30,9 +29,7 @@ public interface INotificationHandler {
String getMedium(); String getMedium();
void sendForInvite(IMatrixIdInvite invite); void sendForInvite(IThreePidInviteReply invite);
void sendForReply(IThreePidInviteReply invite);
void sendForValidation(IThreePidSession session); void sendForValidation(IThreePidSession session);

View File

@@ -1,8 +1,8 @@
/* /*
* mxisd - Matrix Identity Server Daemon * mxisd - Matrix Identity Server Daemon
* Copyright (C) 2017 Kamax Sarl * Copyright (C) 2017 Maxime Dor
* *
* https://www.kamax.io/ * https://max.kamax.io/
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as * it under the terms of the GNU Affero General Public License as
@@ -20,7 +20,6 @@
package io.kamax.mxisd.notification; package io.kamax.mxisd.notification;
import io.kamax.mxisd.as.IMatrixIdInvite;
import io.kamax.mxisd.config.threepid.notification.NotificationConfig; import io.kamax.mxisd.config.threepid.notification.NotificationConfig;
import io.kamax.mxisd.exception.NotImplementedException; import io.kamax.mxisd.exception.NotImplementedException;
import io.kamax.mxisd.invitation.IThreePidInviteReply; import io.kamax.mxisd.invitation.IThreePidInviteReply;
@@ -69,12 +68,8 @@ public class NotificationManager {
return handlers.containsKey(medium); return handlers.containsKey(medium);
} }
public void sendForInvite(IMatrixIdInvite invite) { public void sendForInvite(IThreePidInviteReply invite) {
ensureMedium(invite.getMedium()).sendForInvite(invite); ensureMedium(invite.getInvite().getMedium()).sendForInvite(invite);
}
public void sendForReply(IThreePidInviteReply invite) {
ensureMedium(invite.getInvite().getMedium()).sendForReply(invite);
} }
public void sendForValidation(IThreePidSession session) { public void sendForValidation(IThreePidSession session) {

View File

@@ -20,68 +20,49 @@
package io.kamax.mxisd.profile; package io.kamax.mxisd.profile;
import io.kamax.matrix.ThreePid;
import io.kamax.matrix._MatrixID; import io.kamax.matrix._MatrixID;
import io.kamax.matrix._ThreePid; import io.kamax.matrix._ThreePid;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import java.util.Collection; import java.util.Collection;
import java.util.List; import java.util.List;
import java.util.Optional;
import java.util.function.Function; import java.util.function.Function;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@Component @Component
public class ProfileManager { public class ProfileManager {
private final Logger log = LoggerFactory.getLogger(ProfileManager.class); private List<ProfileProvider> readers;
private List<ProfileWriter> writers;
private List<ProfileProvider> providers; public ProfileManager(List<ProfileProvider> providers, List<ProfileWriter> writers) {
this.readers = providers.stream()
.filter(ProfileProvider::isEnabled)
.collect(Collectors.toList());
@Autowired this.writers = writers.stream()
public ProfileManager(List<ProfileProvider> providers) { .filter(ProfileWriter::isEnabled)
this.providers = providers;
}
@PostConstruct
public void build() {
log.info("--- Profile providers ---");
providers = providers.stream()
.filter(pp -> {
log.info("\t- {} - Is enabled? {}", pp.getClass().getSimpleName(), pp.isEnabled());
return pp.isEnabled();
})
.collect(Collectors.toList()); .collect(Collectors.toList());
} }
public <T> List<T> getList(Function<ProfileProvider, List<T>> function) { public <T> List<T> get(Function<ProfileProvider, List<T>> function) {
return providers.stream() return readers.stream()
.map(function) .map(function)
.flatMap(Collection::stream) .flatMap(Collection::stream)
.collect(Collectors.toList()); .collect(Collectors.toList());
} }
public <T> Optional<T> getOpt(Function<ProfileProvider, Optional<T>> function) { public List<_ThreePid> getThreepids(_MatrixID mxid) {
return providers.stream() return get(p -> p.getThreepids(mxid));
.map(function)
.filter(Optional::isPresent)
.map(Optional::get)
.findFirst();
} }
public Optional<String> getDisplayName(_MatrixID user) { public List<String> getRoles(_MatrixID mxid) {
return getOpt(p -> p.getDisplayName(user)); return get(p -> p.getRoles(mxid));
} }
public List<_ThreePid> getThreepids(_MatrixID user) { public void addThreepid(_MatrixID mxid, ThreePid tpid) {
return getList(p -> p.getThreepids(user)); writers.forEach(w -> w.addThreepid(mxid, tpid));
}
public List<String> getRoles(_MatrixID user) {
return getList(p -> p.getRoles(user));
} }
} }

View File

@@ -24,16 +24,13 @@ import io.kamax.matrix._MatrixID;
import io.kamax.matrix._ThreePid; import io.kamax.matrix._ThreePid;
import java.util.List; import java.util.List;
import java.util.Optional;
public interface ProfileProvider { public interface ProfileProvider {
boolean isEnabled(); boolean isEnabled();
Optional<String> getDisplayName(_MatrixID userId); List<_ThreePid> getThreepids(_MatrixID mxid);
List<_ThreePid> getThreepids(_MatrixID userId); List<String> getRoles(_MatrixID mxid);
List<String> getRoles(_MatrixID userId);
} }

View File

@@ -1,6 +1,6 @@
/* /*
* mxisd - Matrix Identity Server Daemon * mxisd - Matrix Identity Server Daemon
* Copyright (C) 2018 Kamax Sarl * Copyright (C) 2018 Kamax Sàrl
* *
* https://www.kamax.io/ * https://www.kamax.io/
* *
@@ -18,13 +18,15 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
package io.kamax.mxisd.as; package io.kamax.mxisd.profile;
import io.kamax.matrix.ThreePid;
import io.kamax.matrix._MatrixID; import io.kamax.matrix._MatrixID;
import io.kamax.mxisd.invitation.IThreePidInvite;
public interface IMatrixIdInvite extends IThreePidInvite { public interface ProfileWriter {
_MatrixID getInvitee(); boolean isEnabled();
boolean addThreepid(_MatrixID mxid, ThreePid tpid);
} }

View File

@@ -277,7 +277,8 @@ public class SessionMananger {
} }
String is = servers.get(0); String is = servers.get(0);
String url = IdentityServerUtils.findIsUrlForDomain(is).orElse(is); String url = IdentityServerUtils.findIsUrlForDomain(is)
.orElseThrow(() -> new InternalServerError(is + " could not be resolved to an Identity server"));
log.info("Will use IS endpoint {}", url); log.info("Will use IS endpoint {}", url);
String remoteSecret = session.isRemote() ? session.getRemoteSecret() : RandomStringUtils.randomAlphanumeric(16); String remoteSecret = session.isRemote() ? session.getRemoteSecret() : RandomStringUtils.randomAlphanumeric(16);

View File

@@ -30,11 +30,7 @@ public class CloseableHttpClientFactory {
@Bean @Bean
public CloseableHttpClient getClient() { public CloseableHttpClient getClient() {
return HttpClients.custom() return HttpClients.custom().setUserAgent("mxisd").build();
.setUserAgent("mxisd")
.setMaxConnPerRoute(Integer.MAX_VALUE)
.setMaxConnTotal(Integer.MAX_VALUE)
.build();
} }
} }

View File

@@ -24,7 +24,7 @@ import io.kamax.matrix.crypto.KeyFileStore;
import io.kamax.matrix.crypto.KeyManager; import io.kamax.matrix.crypto.KeyManager;
import io.kamax.matrix.crypto.SignatureManager; import io.kamax.matrix.crypto.SignatureManager;
import io.kamax.mxisd.config.KeyConfig; import io.kamax.mxisd.config.KeyConfig;
import io.kamax.mxisd.config.ServerConfig; import io.kamax.mxisd.config.MatrixConfig;
import org.apache.commons.io.FileUtils; import org.apache.commons.io.FileUtils;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
@@ -50,8 +50,8 @@ public class CryptoFactory {
} }
@Bean @Bean
public SignatureManager getSignatureManager(KeyManager keyMgr, ServerConfig cfg) { public SignatureManager getSignatureManager(KeyManager keyMgr, MatrixConfig mxCfg) {
return new SignatureManager(keyMgr, cfg.getName()); return new SignatureManager(keyMgr, mxCfg.getDomain());
} }
} }

View File

@@ -1,8 +1,8 @@
/* /*
* mxisd - Matrix Identity Server Daemon * mxisd - Matrix Identity Server Daemon
* Copyright (C) 2017 Kamax Sarl * Copyright (C) 2017 Maxime Dor
* *
* https://www.kamax.io/ * https://max.kamax.io/
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as * it under the terms of the GNU Affero General Public License as
@@ -23,7 +23,6 @@ package io.kamax.mxisd.threepid.connector.email;
import com.sendgrid.SendGrid; import com.sendgrid.SendGrid;
import com.sendgrid.SendGridException; import com.sendgrid.SendGridException;
import io.kamax.matrix.ThreePidMedium; import io.kamax.matrix.ThreePidMedium;
import io.kamax.mxisd.as.IMatrixIdInvite;
import io.kamax.mxisd.config.MatrixConfig; import io.kamax.mxisd.config.MatrixConfig;
import io.kamax.mxisd.config.ServerConfig; import io.kamax.mxisd.config.ServerConfig;
import io.kamax.mxisd.config.threepid.connector.EmailSendGridConfig; import io.kamax.mxisd.config.threepid.connector.EmailSendGridConfig;
@@ -88,25 +87,13 @@ public class EmailSendGridNotificationHandler extends PlaceholderNotificationGen
} }
@Override @Override
public void sendForInvite(IMatrixIdInvite invite) { public void sendForInvite(IThreePidInviteReply invite) {
EmailTemplate template = cfg.getTemplates().getGeneric().get("matrixId"); EmailTemplate template = cfg.getTemplates().getInvite();
Email email = getEmail(); Email email = getEmail();
email.setSubject(populateForInvite(invite, template.getSubject())); email.setSubject(populateForInvite(invite, template.getSubject()));
email.setText(populateForInvite(invite, getFromFile(template.getBody().getText()))); email.setText(populateForInvite(invite, getFromFile(template.getBody().getText())));
email.setHtml(populateForInvite(invite, getFromFile(template.getBody().getHtml()))); email.setHtml(populateForInvite(invite, getFromFile(template.getBody().getHtml())));
send(invite.getAddress(), email);
}
@Override
public void sendForReply(IThreePidInviteReply invite) {
EmailTemplate template = cfg.getTemplates().getInvite();
Email email = getEmail();
email.setSubject(populateForReply(invite, template.getSubject()));
email.setText(populateForReply(invite, getFromFile(template.getBody().getText())));
email.setHtml(populateForReply(invite, getFromFile(template.getBody().getHtml())));
send(invite.getInvite().getAddress(), email); send(invite.getInvite().getAddress(), email);
} }

View File

@@ -1,8 +1,8 @@
/* /*
* mxisd - Matrix Identity Server Daemon * mxisd - Matrix Identity Server Daemon
* Copyright (C) 2017 Kamax Sarl * Copyright (C) 2017 Maxime Dor
* *
* https://www.kamax.io/ * https://max.kamax.io/
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as * it under the terms of the GNU Affero General Public License as
@@ -20,7 +20,6 @@
package io.kamax.mxisd.threepid.notification; package io.kamax.mxisd.threepid.notification;
import io.kamax.mxisd.as.IMatrixIdInvite;
import io.kamax.mxisd.exception.ConfigurationException; import io.kamax.mxisd.exception.ConfigurationException;
import io.kamax.mxisd.invitation.IThreePidInviteReply; import io.kamax.mxisd.invitation.IThreePidInviteReply;
import io.kamax.mxisd.notification.INotificationHandler; import io.kamax.mxisd.notification.INotificationHandler;
@@ -56,13 +55,8 @@ public abstract class GenericNotificationHandler<A extends IThreePidConnector, B
} }
@Override @Override
public void sendForInvite(IMatrixIdInvite invite) { public void sendForInvite(IThreePidInviteReply invite) {
send(connector, invite.getAddress(), generator.getForInvite(invite)); send(connector, invite.getInvite().getAddress(), generator.getForInvite(invite));
}
@Override
public void sendForReply(IThreePidInviteReply invite) {
send(connector, invite.getInvite().getAddress(), generator.getForReply(invite));
} }
@Override @Override

View File

@@ -1,8 +1,8 @@
/* /*
* mxisd - Matrix Identity Server Daemon * mxisd - Matrix Identity Server Daemon
* Copyright (C) 2017 Kamax Sarl * Copyright (C) 2017 Maxime Dor
* *
* https://www.kamax.io/ * https://max.kamax.io/
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as * it under the terms of the GNU Affero General Public License as
@@ -20,7 +20,6 @@
package io.kamax.mxisd.threepid.notification; package io.kamax.mxisd.threepid.notification;
import io.kamax.mxisd.as.IMatrixIdInvite;
import io.kamax.mxisd.config.MatrixConfig; import io.kamax.mxisd.config.MatrixConfig;
import io.kamax.mxisd.config.ServerConfig; import io.kamax.mxisd.config.ServerConfig;
import io.kamax.mxisd.config.threepid.medium.GenericTemplateConfig; import io.kamax.mxisd.config.threepid.medium.GenericTemplateConfig;
@@ -66,20 +65,9 @@ public abstract class GenericTemplateNotificationGenerator extends PlaceholderNo
} }
@Override @Override
public String getForInvite(IMatrixIdInvite invite) { public String getForInvite(IThreePidInviteReply invite) {
String template = cfg.getGeneric().get("matrixId");
if (StringUtils.isBlank(template)) {
throw new InternalServerError("No " + invite.getMedium() + " template configured for Matrix ID invites");
}
log.info("Generating notification content for Matrix ID invite");
return populateForInvite(invite, getTemplateContent(template));
}
@Override
public String getForReply(IThreePidInviteReply invite) {
log.info("Generating notification content for 3PID invite"); log.info("Generating notification content for 3PID invite");
return populateForReply(invite, getTemplateContent(cfg.getInvite())); return populateForInvite(invite, getTemplateContent(cfg.getInvite()));
} }
@Override @Override

View File

@@ -1,8 +1,8 @@
/* /*
* mxisd - Matrix Identity Server Daemon * mxisd - Matrix Identity Server Daemon
* Copyright (C) 2017 Kamax Sarl * Copyright (C) 2017 Maxime Dor
* *
* https://www.kamax.io/ * https://max.kamax.io/
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as * it under the terms of the GNU Affero General Public License as
@@ -20,7 +20,6 @@
package io.kamax.mxisd.threepid.notification; package io.kamax.mxisd.threepid.notification;
import io.kamax.mxisd.as.IMatrixIdInvite;
import io.kamax.mxisd.invitation.IThreePidInviteReply; import io.kamax.mxisd.invitation.IThreePidInviteReply;
import io.kamax.mxisd.threepid.session.IThreePidSession; import io.kamax.mxisd.threepid.session.IThreePidSession;
@@ -30,9 +29,7 @@ public interface INotificationGenerator {
String getMedium(); String getMedium();
String getForInvite(IMatrixIdInvite invite); String getForInvite(IThreePidInviteReply invite);
String getForReply(IThreePidInviteReply invite);
String getForValidation(IThreePidSession session); String getForValidation(IThreePidSession session);

View File

@@ -1,8 +1,8 @@
/* /*
* mxisd - Matrix Identity Server Daemon * mxisd - Matrix Identity Server Daemon
* Copyright (C) 2017 Kamax Sarl * Copyright (C) 2017 Maxime Dor
* *
* https://www.kamax.io/ * https://max.kamax.io/
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as * it under the terms of the GNU Affero General Public License as
@@ -21,7 +21,6 @@
package io.kamax.mxisd.threepid.notification; package io.kamax.mxisd.threepid.notification;
import io.kamax.matrix.ThreePid; import io.kamax.matrix.ThreePid;
import io.kamax.mxisd.as.IMatrixIdInvite;
import io.kamax.mxisd.config.MatrixConfig; import io.kamax.mxisd.config.MatrixConfig;
import io.kamax.mxisd.config.ServerConfig; import io.kamax.mxisd.config.ServerConfig;
import io.kamax.mxisd.controller.identity.v1.IdentityAPIv1; import io.kamax.mxisd.controller.identity.v1.IdentityAPIv1;
@@ -40,7 +39,7 @@ public abstract class PlaceholderNotificationGenerator {
this.srvCfg = srvCfg; this.srvCfg = srvCfg;
} }
protected String populateForCommon(ThreePid recipient, String input) { protected String populateForCommon(String input, ThreePid recipient) {
String domainPretty = WordUtils.capitalizeFully(mxCfg.getDomain()); String domainPretty = WordUtils.capitalizeFully(mxCfg.getDomain());
return input return input
@@ -50,23 +49,7 @@ public abstract class PlaceholderNotificationGenerator {
.replace("%RECIPIENT_ADDRESS%", recipient.getAddress()); .replace("%RECIPIENT_ADDRESS%", recipient.getAddress());
} }
protected String populateForInvite(IMatrixIdInvite invite, String input) { protected String populateForInvite(IThreePidInviteReply invite, String input) {
String senderName = invite.getProperties().getOrDefault("sender_display_name", "");
String senderNameOrId = StringUtils.defaultIfBlank(senderName, invite.getSender().getId());
String roomName = invite.getProperties().getOrDefault("room_name", "");
String roomNameOrId = StringUtils.defaultIfBlank(roomName, invite.getRoomId());
return populateForCommon(new ThreePid(invite.getMedium(), invite.getAddress()), input)
.replace("%SENDER_ID%", invite.getSender().getId())
.replace("%SENDER_NAME%", senderName)
.replace("%SENDER_NAME_OR_ID%", senderNameOrId)
.replace("%RECIPIENT_ID%", invite.getInvitee().getId())
.replace("%ROOM_ID%", invite.getRoomId())
.replace("%ROOM_NAME%", roomName)
.replace("%ROOM_NAME_OR_ID%", roomNameOrId);
}
protected String populateForReply(IThreePidInviteReply invite, String input) {
ThreePid tpid = new ThreePid(invite.getInvite().getMedium(), invite.getInvite().getAddress()); ThreePid tpid = new ThreePid(invite.getInvite().getMedium(), invite.getInvite().getAddress());
String senderName = invite.getInvite().getProperties().getOrDefault("sender_display_name", ""); String senderName = invite.getInvite().getProperties().getOrDefault("sender_display_name", "");
@@ -74,7 +57,7 @@ public abstract class PlaceholderNotificationGenerator {
String roomName = invite.getInvite().getProperties().getOrDefault("room_name", ""); String roomName = invite.getInvite().getProperties().getOrDefault("room_name", "");
String roomNameOrId = StringUtils.defaultIfBlank(roomName, invite.getInvite().getRoomId()); String roomNameOrId = StringUtils.defaultIfBlank(roomName, invite.getInvite().getRoomId());
return populateForCommon(tpid, input) return populateForCommon(input, tpid)
.replace("%SENDER_ID%", invite.getInvite().getSender().getId()) .replace("%SENDER_ID%", invite.getInvite().getSender().getId())
.replace("%SENDER_NAME%", senderName) .replace("%SENDER_NAME%", senderName)
.replace("%SENDER_NAME_OR_ID%", senderNameOrId) .replace("%SENDER_NAME_OR_ID%", senderNameOrId)
@@ -93,7 +76,7 @@ public abstract class PlaceholderNotificationGenerator {
session.getToken() session.getToken()
); );
return populateForCommon(session.getThreePid(), input) return populateForCommon(input, session.getThreePid())
.replace("%VALIDATION_LINK%", validationLink) .replace("%VALIDATION_LINK%", validationLink)
.replace("%VALIDATION_TOKEN%", session.getToken()) .replace("%VALIDATION_TOKEN%", session.getToken())
.replace("%NEXT_URL%", validationLink); .replace("%NEXT_URL%", validationLink);

View File

@@ -46,8 +46,8 @@ public class EmailNotificationGenerator extends GenericTemplateNotificationGener
} }
@Override @Override
protected String populateForCommon(ThreePid recipient, String body) { protected String populateForCommon(String body, ThreePid recipient) {
body = super.populateForCommon(recipient, body); body = super.populateForCommon(body, recipient);
body = body.replace("%FROM_EMAIL%", cfg.getIdentity().getFrom()); body = body.replace("%FROM_EMAIL%", cfg.getIdentity().getFrom());
body = body.replace("%FROM_NAME%", cfg.getIdentity().getName()); body = body.replace("%FROM_NAME%", cfg.getIdentity().getName());
return body; return body;

View File

@@ -45,8 +45,8 @@ public class GsonParser {
this.gson = gson; this.gson = gson;
} }
public JsonObject parse(InputStream stream) throws IOException { public JsonObject parse(String raw) {
JsonElement el = parser.parse(IOUtils.toString(stream, StandardCharsets.UTF_8)); JsonElement el = parser.parse(raw);
if (!el.isJsonObject()) { if (!el.isJsonObject()) {
throw new InvalidResponseJsonException("Response body is not a JSON object"); throw new InvalidResponseJsonException("Response body is not a JSON object");
} }
@@ -54,6 +54,10 @@ public class GsonParser {
return el.getAsJsonObject(); return el.getAsJsonObject();
} }
public JsonObject parse(InputStream stream) throws IOException {
return parse(IOUtils.toString(stream, StandardCharsets.UTF_8));
}
public <T> T parse(HttpServletRequest req, Class<T> type) throws IOException { public <T> T parse(HttpServletRequest req, Class<T> type) throws IOException {
return gson.fromJson(parse(req.getInputStream()), type); return gson.fromJson(parse(req.getInputStream()), type);
} }

View File

@@ -1,7 +1,7 @@
# DO NOT USE THIS FILE AS-IS FOR YOUR INITIAL CONFIGURATION # DO NOT USE THIS FILE AS-IS FOR YOUR INITIAL CONFIGURATION
# ONLY TAKE THE SPECIFIC SECTION YOU WANT TO CONFIGURE # ONLY TAKE THE SPECIFIC SECTION YOU WANT TO CONFIGURE
# #
# For more information about configuration, visit https://github.com/kamax-matrix/mxisd/blob/master/docs/configure.md # For more information about configuration, visit https://github.com/kamax-io/mxisd/blob/master/docs/configure.md
spring: spring:
main: main:
@@ -24,14 +24,8 @@ matrix:
domain: '' domain: ''
identity: identity:
servers: servers:
matrix-org: root:
- 'https://matrix.org' - 'https://matrix.org'
listener:
url: ''
localpart: ''
token:
as: ''
hs: ''
lookup: lookup:
recursive: recursive:
@@ -138,6 +132,7 @@ netiq:
firebase: firebase:
enabled: false enabled: false
sql: sql:
enabled: false enabled: false
type: 'sqlite' type: 'sqlite'
@@ -160,20 +155,28 @@ sql:
threepid: threepid:
query: 'SELECT medium, address FROM user_threepids WHERE user_id = ?' query: 'SELECT medium, address FROM user_threepids WHERE user_id = ?'
synapseSql:
enabled: false
type: 'sqlite'
profile:
threepid:
query: 'SELECT medium, address FROM user_threepids WHERE user_id = ?'
wordpress: wordpress:
enabled: false enabled: false
sql: sql:
type: 'mysql' type: 'mysql'
tablePrefix: 'wp_'
query: query:
threepid: threepid:
email: 'SELECT user_login as uid FROM ${wordpress.sql.tablePrefix}users WHERE user_email = ?' email: 'SELECT user_login as uid FROM wp_users WHERE user_email = ?'
directory: directory:
name: "SELECT DISTINCT user_login, display_name FROM ${wordpress.sql.tablePrefix}users u LEFT JOIN ${wordpress.sql.tablePrefix}usermeta m ON m.user_id = u.id WHERE u.display_name LIKE ? OR (m.meta_key = 'nickname' AND m.meta_value = ?) OR (m.meta_key = 'first_name' AND m.meta_value = ?) OR (m.meta_key = 'last_name' AND m.meta_value = ?);" name: "SELECT DISTINCT user_login, display_name FROM wp_users u LEFT JOIN wp_usermeta m ON m.user_id = u.id WHERE u.display_name LIKE ? OR (m.meta_key = 'nickname' AND m.meta_value = ?) OR (m.meta_key = 'first_name' AND m.meta_value = ?) OR (m.meta_key = 'last_name' AND m.meta_value = ?);"
threepid: 'SELECT DISTINCT user_login, display_name FROM ${wordpress.sql.tablePrefix}users WHERE user_email LIKE ?' threepid: 'SELECT DISTINCT user_login, display_name FROM wp_users WHERE user_email LIKE ?'
forward: forward:
servers: [] servers:
- 'https://matrix.org'
- 'https://vector.im'
threepid: threepid:
medium: medium:
@@ -193,8 +196,6 @@ threepid:
generators: generators:
template: template:
invite: 'classpath:threepids/email/invite-template.eml' invite: 'classpath:threepids/email/invite-template.eml'
generic:
matrixId: 'classpath:threepids/email/mxid-template.eml'
session: session:
validation: validation:
local: 'classpath:threepids/email/validate-local-template.eml' local: 'classpath:threepids/email/validate-local-template.eml'
@@ -225,13 +226,13 @@ session:
toLocal: true toLocal: true
toRemote: toRemote:
enabled: true enabled: true
server: 'matrix-org' server: 'root'
forRemote: forRemote:
enabled: true enabled: true
toLocal: false toLocal: false
toRemote: toRemote:
enabled: true enabled: true
server: 'matrix-org' server: 'root'
notification: notification:
# handler: # handler:

View File

@@ -1,73 +0,0 @@
Subject: You have been invited to a room
MIME-Version: 1.0
Content-Type: multipart/alternative;
boundary="7REaIwWQCioQ6NaBlAQlg8ztbUQj6PKJ"
--7REaIwWQCioQ6NaBlAQlg8ztbUQj6PKJ
Content-Type: text/plain; charset=UTF-8
Content-Disposition: inline
Hi,
%SENDER_NAME_OR_ID% has invited you into a room [%ROOM_NAME_OR_ID%] on Matrix.
Thanks,
%DOMAIN_PRETTY% Admins
--7REaIwWQCioQ6NaBlAQlg8ztbUQj6PKJ
Content-Type: multipart/related;
boundary="M3yzHl5YZehm9v4bAM8sKEdcOoVnRnKR";
type="text/html"
--M3yzHl5YZehm9v4bAM8sKEdcOoVnRnKR
Content-Type: text/html; charset=UTF-8
Content-Disposition: inline
<!doctype html>
<html lang="en">
<head>
<style type="text/css">
body {
margin: 0px;
}
pre, code {
word-break: break-word;
white-space: pre-wrap;
}
#page {
font-family: 'Open Sans', Helvetica, Arial, Sans-Serif;
font-color: #454545;
font-size: 12pt;
width: 100%%;
padding: 20px;
}
#inner {
width: 640px;
}
</style>
</head>
<body>
<table id="page">
<tr>
<td> </td>
<td id="inner">
<p>Hi,</p>
<p>%SENDER_NAME_OR_ID% has invited you into a room [%ROOM_NAME_OR_ID%] on Matrix.</p>
<p>Thanks,</p>
<p>%DOMAIN_PRETTY% Admins</p>
</td>
<td> </td>
</tr>
</table>
</body>
</html>
--M3yzHl5YZehm9v4bAM8sKEdcOoVnRnKR--
--7REaIwWQCioQ6NaBlAQlg8ztbUQj6PKJ--

View File

@@ -33,7 +33,8 @@ import org.junit.Test;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import static com.github.tomakehurst.wiremock.client.WireMock.*; import static com.github.tomakehurst.wiremock.client.WireMock.*;
import static org.junit.Assert.*; import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
public class RestDirectoryProviderTest { public class RestDirectoryProviderTest {
@@ -88,8 +89,8 @@ public class RestDirectoryProviderTest {
UserDirectorySearchResult result = p.searchByDisplayName(byNameSearch); UserDirectorySearchResult result = p.searchByDisplayName(byNameSearch);
assertTrue(!result.isLimited()); assertTrue(!result.isLimited());
assertEquals(1, result.getResults().size()); assertTrue(result.getResults().size() == 1);
UserDirectorySearchResult.Result entry = result.getResults().iterator().next(); UserDirectorySearchResult.Result entry = result.getResults().get(0);
assertNotNull(entry); assertNotNull(entry);
assertTrue(StringUtils.equals(byNameAvatar, entry.getAvatarUrl())); assertTrue(StringUtils.equals(byNameAvatar, entry.getAvatarUrl()));
assertTrue(StringUtils.equals(byNameDisplay, entry.getDisplayName())); assertTrue(StringUtils.equals(byNameDisplay, entry.getDisplayName()));
@@ -131,8 +132,8 @@ public class RestDirectoryProviderTest {
UserDirectorySearchResult result = p.searchBy3pid(byThreepidSearch); UserDirectorySearchResult result = p.searchBy3pid(byThreepidSearch);
assertTrue(!result.isLimited()); assertTrue(!result.isLimited());
assertEquals(1, result.getResults().size()); assertTrue(result.getResults().size() == 1);
UserDirectorySearchResult.Result entry = result.getResults().iterator().next(); UserDirectorySearchResult.Result entry = result.getResults().get(0);
assertNotNull(entry); assertNotNull(entry);
assertTrue(StringUtils.equals(byThreepidAvatar, entry.getAvatarUrl())); assertTrue(StringUtils.equals(byThreepidAvatar, entry.getAvatarUrl()));
assertTrue(StringUtils.equals(byThreepidDisplay, entry.getDisplayName())); assertTrue(StringUtils.equals(byThreepidDisplay, entry.getDisplayName()));