Compare commits

...

46 Commits

Author SHA1 Message Date
0de8e247cb Update dependency org.apache.commons:commons-lang3 to v3.18.0 2025-09-11 22:01:52 +00:00
8d4f331880 Update dependency gradle to v8.14.3 2025-09-11 21:03:00 +00:00
7f1b77ce19 Update dependency dnsjava:dnsjava to v3.6.3 2025-09-11 21:02:17 +00:00
d4080bb2e5 Update dependency commons-io:commons-io to v2.20.0 2025-09-11 20:01:55 +00:00
0106364680 Update dependency commons-codec:commons-codec to v1.19.0 2025-09-11 20:01:50 +00:00
b1ef1b9aa1 Update dependency com.mchange:c3p0 to v0.11.2 2025-09-11 19:02:25 +00:00
84b4c9c3ed Update dependency com.github.ben-manes:gradle-versions-plugin to v0.52.0 2025-09-11 19:02:18 +00:00
dedce04961 Update dependency org.postgresql:postgresql to v42.7.7 2025-09-11 18:01:43 +00:00
a4e99fcc79 Update dependency org.xerial:sqlite-jdbc to v3.50.3.0 2025-09-11 17:02:23 +00:00
d568678df5 Update dependency com.twilio.sdk:twilio to v10.9.2 2025-09-11 17:02:19 +00:00
31210f4e71 Update dependency org.apache.directory.api:api-all to v2.1.7 2025-09-11 17:02:08 +00:00
df70b65ac3 Update dependency org.mariadb.jdbc:mariadb-java-client to v3.5.6 2025-09-11 16:01:44 +00:00
949bfc38f8 Merge pull request 'Update dependency com.mchange:c3p0 to v0.10.1' (#51) from renovate/com.mchange-c3p0-0.x into master
Reviewed-on: #51
2024-05-09 12:15:33 +00:00
c5e5f643a2 Merge pull request 'Update dependency com.googlecode.libphonenumber:libphonenumber to v8.13.36' (#50) from renovate/com.googlecode.libphonenumber-libphonenumber-8.x into master
Reviewed-on: #50
2024-05-09 12:15:23 +00:00
5820156512 Merge pull request 'Update dependency commons-codec:commons-codec to v1.17.0' (#49) from renovate/commons-codec-commons-codec-1.x into master
Reviewed-on: #49
2024-05-09 12:15:15 +00:00
7cc4be7cd6 Update dependency com.mchange:c3p0 to v0.10.1 2024-05-07 15:01:15 +00:00
5e31ff9b69 Update dependency com.googlecode.libphonenumber:libphonenumber to v8.13.36 2024-05-02 09:01:21 +00:00
d910472db5 Update dependency commons-codec:commons-codec to v1.17.0 2024-04-27 14:01:32 +00:00
ca56afad5d Merge pull request 'Update dependency io.undertow:undertow-core to v2.3.13.Final' (#48) from renovate/io.undertow-undertow-core-2.x into master
Reviewed-on: #48
2024-04-23 11:58:50 +00:00
541aeee3c2 Merge pull request 'Update dependency com.twilio.sdk:twilio to v10.1.5' (#47) from renovate/com.twilio.sdk-twilio-10.x into master
Reviewed-on: #47
2024-04-23 11:58:42 +00:00
19257a0290 Merge pull request 'Update dependency com.googlecode.libphonenumber:libphonenumber to v8.13.35' (#46) from renovate/com.googlecode.libphonenumber-libphonenumber-8.x into master
Reviewed-on: #46
2024-04-23 11:58:32 +00:00
8d91e7d5a3 Merge pull request 'Update dependency commons-cli:commons-cli to v1.7.0' (#45) from renovate/commons-cli-commons-cli-1.x into master
Reviewed-on: #45
2024-04-23 11:58:23 +00:00
c0671acf60 Merge pull request 'Update dependency org.xerial:sqlite-jdbc to v3.45.3.0' (#44) from renovate/org.xerial-sqlite-jdbc-3.x into master
Reviewed-on: #44
2024-04-23 11:58:14 +00:00
0b8300c774 Merge pull request 'Update dependency org.slf4j:slf4j-simple to v2.0.13' (#43) from renovate/slf4j-monorepo into master
Reviewed-on: #43
2024-04-23 11:58:05 +00:00
cac55d5f06 Merge pull request 'Update dependency commons-io:commons-io to v2.16.1' (#42) from renovate/commons-io-commons-io-2.x into master
Reviewed-on: #42
2024-04-23 11:57:55 +00:00
aa3aadbb53 Merge pull request 'Update dependency com.kohlschutter.junixsocket:junixsocket-core to v2.9.1' (#41) from renovate/com.kohlschutter.junixsocket-junixsocket-core-2.x into master
Reviewed-on: #41
2024-04-23 11:57:45 +00:00
da7fa9edd6 Update dependency io.undertow:undertow-core to v2.3.13.Final 2024-04-19 13:01:54 +00:00
a1a21e8d60 Update dependency com.twilio.sdk:twilio to v10.1.5 2024-04-18 15:01:47 +00:00
dc2932cf51 Update dependency com.googlecode.libphonenumber:libphonenumber to v8.13.35 2024-04-18 10:01:42 +00:00
bb84e32719 Update dependency commons-cli:commons-cli to v1.7.0 2024-04-18 02:01:51 +00:00
12aa40b160 Update dependency org.xerial:sqlite-jdbc to v3.45.3.0 2024-04-16 04:01:50 +00:00
9d4fddcb2d Update dependency org.slf4j:slf4j-simple to v2.0.13 2024-04-12 15:01:46 +00:00
4654cff158 Update dependency commons-io:commons-io to v2.16.1 2024-04-08 18:01:40 +00:00
b1888fed96 Update dependency com.kohlschutter.junixsocket:junixsocket-core to v2.9.1 2024-04-05 16:01:34 +00:00
d7e8b3d62a Java 21 2024-04-02 18:02:39 +02:00
56bfdda18c Update Java 2024-04-02 17:57:00 +02:00
fb3debfb49 Replace apk with apt 2024-04-02 17:52:14 +02:00
49f812f867 Bump Java to 22 2024-04-02 17:45:01 +02:00
de0a3152c3 Bump JRE to 21 2024-04-02 16:08:59 +02:00
cc5d047c3f Merge pull request 'Update dependency com.googlecode.libphonenumber:libphonenumber to v8.13.34' (#40) from renovate/com.googlecode.libphonenumber-libphonenumber-8.x into master
Reviewed-on: #40
2024-04-02 13:54:24 +00:00
350776df17 Merge pull request 'Update dependency com.twilio.sdk:twilio to v10.1.3' (#39) from renovate/com.twilio.sdk-twilio-10.x into master
Reviewed-on: #39
2024-04-02 13:54:13 +00:00
7b6560e9c8 Merge pull request 'Update dependency commons-io:commons-io to v2.16.0' (#38) from renovate/commons-io-commons-io-2.x into master
Reviewed-on: #38
2024-04-02 13:54:00 +00:00
4fd4fdac60 Updates to build sucessfully - breaking changes in Firebase and SendGrid 2024-04-02 15:42:15 +02:00
dfad9d9ce8 Update dependency com.googlecode.libphonenumber:libphonenumber to v8.13.34 2024-04-02 13:01:23 +00:00
d2fc4e3bef Update dependency com.twilio.sdk:twilio to v10.1.3 2024-04-01 11:01:26 +00:00
4416c17216 Update dependency commons-io:commons-io to v2.16.0 2024-03-28 23:01:26 +00:00
60 changed files with 616 additions and 802 deletions

View File

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

View File

@@ -49,8 +49,8 @@ def dockerImageTag = "${dockerImageName}:${mxidsVersion()}"
group = 'io.kamax' group = 'io.kamax'
mainClassName = 'io.kamax.mxisd.MxisdStandaloneExec' mainClassName = 'io.kamax.mxisd.MxisdStandaloneExec'
sourceCompatibility = '1.8' sourceCompatibility = '11'
targetCompatibility = '1.8' targetCompatibility = '11'
String mxidsVersion() { String mxidsVersion() {
def versionPattern = Pattern.compile("v(\\d+\\.)?(\\d+\\.)?(\\d+)(-.*)?") def versionPattern = Pattern.compile("v(\\d+\\.)?(\\d+\\.)?(\\d+)(-.*)?")
@@ -75,11 +75,12 @@ buildscript {
repositories { repositories {
gradlePluginPortal() gradlePluginPortal()
mavenCentral() mavenCentral()
google()
} }
dependencies { dependencies {
classpath 'com.github.johnrengelman:shadow:8.1.1' classpath 'com.github.johnrengelman:shadow:8.1.1'
classpath 'com.github.ben-manes:gradle-versions-plugin:0.51.0' classpath 'com.github.ben-manes:gradle-versions-plugin:0.52.0'
} }
} }
@@ -89,18 +90,18 @@ repositories {
dependencies { dependencies {
// Logging // Logging
api 'org.slf4j:slf4j-simple:2.0.12' api 'org.slf4j:slf4j-simple:2.0.13'
// Easy file management // Easy file management
api 'commons-io:commons-io:2.15.1' api 'commons-io:commons-io:2.20.0'
// Config management // Config management
api 'org.yaml:snakeyaml:2.2' api 'org.yaml:snakeyaml:1.33'
// Dependencies from old Matrix-java-sdk // Dependencies from old Matrix-java-sdk
api 'org.apache.commons:commons-lang3:3.14.0' api 'org.apache.commons:commons-lang3:3.18.0'
api 'com.squareup.okhttp3:okhttp:4.12.0' api 'com.squareup.okhttp3:okhttp:4.12.0'
api 'commons-codec:commons-codec:1.16.1' api 'commons-codec:commons-codec:1.19.0'
// ORMLite // ORMLite
api 'com.j256.ormlite:ormlite-jdbc:6.1' api 'com.j256.ormlite:ormlite-jdbc:6.1'
@@ -109,16 +110,16 @@ dependencies {
api 'net.i2p.crypto:eddsa:0.3.0' api 'net.i2p.crypto:eddsa:0.3.0'
// LDAP connector // LDAP connector
api 'org.apache.directory.api:api-all:2.1.6' api 'org.apache.directory.api:api-all:2.1.7'
// DNS lookups // DNS lookups
api 'dnsjava:dnsjava:3.5.3' api 'dnsjava:dnsjava:3.6.3'
// HTTP connections // HTTP connections
api 'org.apache.httpcomponents:httpclient:4.5.14' api 'org.apache.httpcomponents:httpclient:4.5.14'
// Phone numbers validation // Phone numbers validation
api 'com.googlecode.libphonenumber:libphonenumber:8.13.33' api 'com.googlecode.libphonenumber:libphonenumber:8.13.36'
// E-mail sending // E-mail sending
api 'javax.mail:javax.mail-api:1.6.2' api 'javax.mail:javax.mail-api:1.6.2'
@@ -128,22 +129,22 @@ dependencies {
api 'com.google.firebase:firebase-admin:9.2.0' api 'com.google.firebase:firebase-admin:9.2.0'
// Connection Pool // Connection Pool
api 'com.mchange:c3p0:0.10.0' api 'com.mchange:c3p0:0.11.2'
// SQLite // SQLite
api 'org.xerial:sqlite-jdbc:3.45.2.0' api 'org.xerial:sqlite-jdbc:3.50.3.0'
// PostgreSQL // PostgreSQL
api 'org.postgresql:postgresql:42.7.3' api 'org.postgresql:postgresql:42.7.7'
// MariaDB/MySQL // MariaDB/MySQL
api 'org.mariadb.jdbc:mariadb-java-client:3.3.3' api 'org.mariadb.jdbc:mariadb-java-client:3.5.6'
// UNIX sockets // UNIX sockets
api 'com.kohlschutter.junixsocket:junixsocket-core:2.9.0' api 'com.kohlschutter.junixsocket:junixsocket-core:2.9.1'
// Twilio SDK for SMS // Twilio SDK for SMS
api 'com.twilio.sdk:twilio:10.1.2' api 'com.twilio.sdk:twilio:10.9.2'
// SendGrid SDK to send emails from GCE // SendGrid SDK to send emails from GCE
api 'com.sendgrid:sendgrid-java:4.10.2' api 'com.sendgrid:sendgrid-java:4.10.2'
@@ -152,15 +153,15 @@ dependencies {
api 'org.zeroturnaround:zt-exec:1.12' api 'org.zeroturnaround:zt-exec:1.12'
// HTTP server // HTTP server
api 'io.undertow:undertow-core:2.3.12.Final' api 'io.undertow:undertow-core:2.3.13.Final'
// Command parser for AS interface // Command parser for AS interface
api 'commons-cli:commons-cli:1.6.0' api 'commons-cli:commons-cli:1.7.0'
testImplementation 'junit:junit:4.13.2' testImplementation 'junit:junit:4.13.2'
testImplementation 'com.github.tomakehurst:wiremock:3.0.1' testImplementation 'com.github.tomakehurst:wiremock:3.0.1'
testImplementation 'com.unboundid:unboundid-ldapsdk:7.0.0' testImplementation 'com.unboundid:unboundid-ldapsdk:7.0.0'
testImplementation 'com.icegreen:greenmail:2.0.1' testImplementation 'com.icegreen:greenmail:1.6.15'
} }
jar { jar {
@@ -308,3 +309,21 @@ task dockerPushX(type: Exec) {
} }
} }
} }
tasks.named('assemble').configure {
dependsOn shadowJar
}
tasks.withType(AbstractArchiveTask) {
if (it.name == 'distZip' || it.name == 'distTar') {
dependsOn shadowJar
}
}
tasks.named('startScripts').configure {
mustRunAfter shadowJar
}
tasks.named('startShadowScripts').configure {
dependsOn jar
}

Binary file not shown.

View File

@@ -1,6 +1,7 @@
#Thu Dec 05 22:39:36 MSK 2019
distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-all.zip
distributionBase=GRADLE_USER_HOME distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists distributionPath=wrapper/dists
zipStorePath=wrapper/dists distributionUrl=https\://services.gradle.org/distributions/gradle-8.14.3-all.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists

299
gradlew vendored
View File

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

194
gradlew.bat vendored
View File

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

View File

@@ -55,7 +55,7 @@ import io.kamax.mxisd.registration.RegistrationManager;
import io.kamax.mxisd.session.SessionManager; import io.kamax.mxisd.session.SessionManager;
import io.kamax.mxisd.storage.IStorage; import io.kamax.mxisd.storage.IStorage;
import io.kamax.mxisd.storage.ormlite.OrmLiteSqlStorage; import io.kamax.mxisd.storage.ormlite.OrmLiteSqlStorage;
import org.apache.commons.lang.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients; import org.apache.http.impl.client.HttpClients;

View File

@@ -92,7 +92,8 @@ public class MxisdStandaloneExec {
} }
if (dump) { if (dump) {
YamlConfigLoader.dumpConfig(cfg); String outputPath = "mxids.yaml";
YamlConfigLoader.dumpConfig(cfg, outputPath);
if (exit) { if (exit) {
System.exit(0); System.exit(0);
} }

View File

@@ -20,7 +20,7 @@
package io.kamax.mxisd; package io.kamax.mxisd;
import org.apache.commons.lang.StringUtils; import org.apache.commons.lang3.StringUtils;
// FIXME consider integrating in matrix-java-sdk? // FIXME consider integrating in matrix-java-sdk?
public enum UserIdType { public enum UserIdType {

View File

@@ -48,6 +48,7 @@ import org.slf4j.LoggerFactory;
import org.yaml.snakeyaml.Yaml; import org.yaml.snakeyaml.Yaml;
import org.yaml.snakeyaml.introspector.BeanAccess; import org.yaml.snakeyaml.introspector.BeanAccess;
import org.yaml.snakeyaml.representer.Representer; import org.yaml.snakeyaml.representer.Representer;
import org.yaml.snakeyaml.DumperOptions;
import java.io.FileOutputStream; import java.io.FileOutputStream;
import java.io.IOException; import java.io.IOException;
@@ -142,18 +143,18 @@ public class AppSvcManager {
String synapseRegFile = cfg.getAppsvc().getRegistration().getSynapse().getFile(); String synapseRegFile = cfg.getAppsvc().getRegistration().getSynapse().getFile();
if (StringUtils.isBlank(synapseRegFile)) { if (StringUtils.isBlank(synapseRegFile)) {
log.info("No synapse registration file path given - skipping generation..."); log.info("No synapse registration file path given - skipping generation...");
return; return;
} }
SynapseRegistrationYaml syncCfg = SynapseRegistrationYaml.parse(cfg.getAppsvc(), cfg.getMatrix().getDomain()); SynapseRegistrationYaml syncCfg = SynapseRegistrationYaml.parse(cfg.getAppsvc(), cfg.getMatrix().getDomain());
Representer rep = new Representer(); DumperOptions options = new DumperOptions();
options.setDefaultFlowStyle(DumperOptions.FlowStyle.BLOCK); // Set YAML flow style to block
Representer rep = new Representer(options);
rep.getPropertyUtils().setBeanAccess(BeanAccess.FIELD); rep.getPropertyUtils().setBeanAccess(BeanAccess.FIELD);
Yaml yaml = new Yaml(rep); Yaml yaml = new Yaml(rep);
// SnakeYAML set the type of object on the first line, which can fail to be parsed on synapse
// We therefore need to split the resulting string, remove the first line, and then write it
List<String> lines = new ArrayList<>(Arrays.asList(yaml.dump(syncCfg).split("\\R+"))); List<String> lines = new ArrayList<>(Arrays.asList(yaml.dump(syncCfg).split("\\R+")));
if (StringUtils.equals(lines.get(0), "!!" + SynapseRegistrationYaml.class.getCanonicalName())) { if (StringUtils.equals(lines.get(0), "!!" + SynapseRegistrationYaml.class.getCanonicalName())) {
lines.remove(0); lines.remove(0);

View File

@@ -25,8 +25,8 @@ import io.kamax.matrix.hs._MatrixRoom;
import io.kamax.mxisd.Mxisd; import io.kamax.mxisd.Mxisd;
import io.kamax.mxisd.invitation.IThreePidInviteReply; import io.kamax.mxisd.invitation.IThreePidInviteReply;
import org.apache.commons.cli.CommandLine; import org.apache.commons.cli.CommandLine;
import org.apache.commons.lang.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang.text.StrBuilder; import org.apache.commons.lang3.text.StrBuilder;
import java.util.List; import java.util.List;

View File

@@ -25,7 +25,7 @@ import io.kamax.matrix.hs._MatrixRoom;
import io.kamax.mxisd.Mxisd; import io.kamax.mxisd.Mxisd;
import io.kamax.mxisd.lookup.SingleLookupReply; import io.kamax.mxisd.lookup.SingleLookupReply;
import org.apache.commons.cli.CommandLine; import org.apache.commons.cli.CommandLine;
import org.apache.commons.lang.text.StrBuilder; import org.apache.commons.lang3.text.StrBuilder;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import java.util.Optional; import java.util.Optional;

View File

@@ -34,7 +34,7 @@ import io.kamax.mxisd.invitation.IMatrixIdInvite;
import io.kamax.mxisd.invitation.MatrixIdInvite; import io.kamax.mxisd.invitation.MatrixIdInvite;
import io.kamax.mxisd.notification.NotificationManager; import io.kamax.mxisd.notification.NotificationManager;
import io.kamax.mxisd.profile.ProfileManager; import io.kamax.mxisd.profile.ProfileManager;
import org.apache.commons.lang.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;

View File

@@ -32,7 +32,7 @@ import io.kamax.mxisd.as.processor.command.InviteCommandProcessor;
import io.kamax.mxisd.as.processor.command.LookupCommandProcessor; import io.kamax.mxisd.as.processor.command.LookupCommandProcessor;
import io.kamax.mxisd.as.processor.command.PingCommandProcessor; import io.kamax.mxisd.as.processor.command.PingCommandProcessor;
import org.apache.commons.cli.*; import org.apache.commons.cli.*;
import org.apache.commons.lang.text.StrBuilder; import org.apache.commons.lang3.text.StrBuilder;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;

View File

@@ -45,7 +45,7 @@ import io.kamax.mxisd.lookup.ThreePidMapping;
import io.kamax.mxisd.lookup.strategy.LookupStrategy; import io.kamax.mxisd.lookup.strategy.LookupStrategy;
import io.kamax.mxisd.util.RestClientUtils; import io.kamax.mxisd.util.RestClientUtils;
import org.apache.commons.io.IOUtils; import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpEntity; import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse; import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost; import org.apache.http.client.methods.HttpPost;

View File

@@ -27,7 +27,7 @@ import io.kamax.mxisd.config.ExecConfig;
import io.kamax.mxisd.profile.JsonProfileRequest; import io.kamax.mxisd.profile.JsonProfileRequest;
import io.kamax.mxisd.profile.JsonProfileResult; import io.kamax.mxisd.profile.JsonProfileResult;
import io.kamax.mxisd.profile.ProfileProvider; import io.kamax.mxisd.profile.ProfileProvider;
import org.apache.commons.lang.StringUtils; import org.apache.commons.lang3.StringUtils;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;

View File

@@ -1,168 +1,81 @@
/*
* 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.firebase; package io.kamax.mxisd.backend.firebase;
import com.google.firebase.auth.UserInfo; import com.google.firebase.auth.FirebaseAuth;
import com.google.i18n.phonenumbers.NumberParseException; import com.google.firebase.auth.FirebaseAuthException;
import com.google.i18n.phonenumbers.PhoneNumberUtil; import com.google.firebase.auth.FirebaseToken;
import io.kamax.matrix.ThreePid; import com.google.firebase.auth.UserRecord;
import io.kamax.matrix.ThreePidMedium;
import io.kamax.matrix._MatrixID; import io.kamax.matrix._MatrixID;
import io.kamax.mxisd.UserIdType;
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.FirebaseConfig; import io.kamax.mxisd.config.FirebaseConfig;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import java.util.concurrent.CountDownLatch; import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit; import java.util.concurrent.Executors;
import java.util.concurrent.ExecutorService;
public class GoogleFirebaseAuthenticator extends GoogleFirebaseBackend implements AuthenticatorProvider { public class GoogleFirebaseAuthenticator implements AuthenticatorProvider {
private transient final Logger log = LoggerFactory.getLogger(GoogleFirebaseAuthenticator.class); private static final Logger log = LoggerFactory.getLogger(GoogleFirebaseAuthenticator.class);
private static final ExecutorService executor = Executors.newCachedThreadPool(); // Consider using a fixed thread pool or other strategies based on your app's needs
private PhoneNumberUtil phoneUtil = PhoneNumberUtil.getInstance(); private FirebaseConfig config;
public GoogleFirebaseAuthenticator(FirebaseConfig cfg) { public GoogleFirebaseAuthenticator(FirebaseConfig config) {
this(cfg.isEnabled(), cfg.getCredentials(), cfg.getDatabase()); this.config = config;
} }
public GoogleFirebaseAuthenticator(boolean isEnabled, String credsPath, String db) { @Override
super(isEnabled, "AuthenticationProvider", credsPath, db); public boolean isEnabled() {
} return this.config.isEnabled();
private void waitOnLatch(BackendAuthResult result, CountDownLatch l, String purpose) {
try {
l.await(30, TimeUnit.SECONDS);
} catch (InterruptedException e) {
log.warn("Interrupted while waiting for " + purpose);
result.fail();
}
}
private void toEmail(BackendAuthResult result, String email) {
if (StringUtils.isBlank(email)) {
return;
}
result.withThreePid(new ThreePid(ThreePidMedium.Email.getId(), email));
}
private void toMsisdn(BackendAuthResult result, String phoneNumber) {
if (StringUtils.isBlank(phoneNumber)) {
return;
}
try {
String number = phoneUtil.format(
phoneUtil.parse(
phoneNumber,
null // No default region
),
PhoneNumberUtil.PhoneNumberFormat.E164
).substring(1); // We want without the leading +
result.withThreePid(new ThreePid(ThreePidMedium.PhoneNumber.getId(), number));
} catch (NumberParseException e) {
log.warn("Invalid phone number: {}", phoneNumber);
}
}
private void waitOnLatch(CountDownLatch l) {
try {
l.await(30, TimeUnit.SECONDS);
} catch (InterruptedException e) {
log.warn("Interrupted while waiting for Firebase auth check");
}
} }
@Override @Override
public BackendAuthResult authenticate(_MatrixID mxid, String password) { public BackendAuthResult authenticate(_MatrixID mxid, String password) {
if (!isEnabled()) { if (!isEnabled()) {
throw new IllegalStateException(); log.warn("Firebase authenticator is disabled.");
return BackendAuthResult.failure();
} }
log.info("Trying to authenticate {}", mxid); CompletableFuture<BackendAuthResult> resultFuture = new CompletableFuture<>();
executor.submit(() -> {
final BackendAuthResult result = BackendAuthResult.failure();
String localpart = mxid.getLocalPart();
CountDownLatch l = new CountDownLatch(1);
getFirebase().verifyIdToken(password).addOnSuccessListener(token -> {
try { try {
if (!StringUtils.equals(localpart, token.getUid())) { FirebaseToken decodedToken = FirebaseAuth.getInstance().verifyIdToken(password);
log.info("Failure to authenticate {}: Matrix ID localpart '{}' does not match Firebase UID '{}'", mxid, localpart, token.getUid()); if (!mxid.getLocalPart().equals(decodedToken.getUid())) {
result.fail(); log.warn("UID mismatch for user {}", mxid);
resultFuture.complete(BackendAuthResult.failure());
return; return;
} }
result.succeed(mxid.getId(), UserIdType.MatrixID.getId(), token.getName()); // Assuming you have a method to convert Firebase user info into BackendAuthResult
log.info("{} was successfully authenticated", mxid); resultFuture.complete(convertToAuthResult(decodedToken));
log.info("Fetching profile for {}", mxid); } catch (FirebaseAuthException e) {
CountDownLatch userRecordLatch = new CountDownLatch(1); log.error("Failed to authenticate user {}: {}", mxid, e.getMessage(), e);
getFirebase().getUser(token.getUid()).addOnSuccessListener(user -> { resultFuture.complete(BackendAuthResult.failure());
try {
toEmail(result, user.getEmail());
toMsisdn(result, user.getPhoneNumber());
for (UserInfo info : user.getProviderData()) {
toEmail(result, info.getEmail());
toMsisdn(result, info.getPhoneNumber());
}
log.info("Got {} 3PIDs in profile", result.getProfile().getThreePids().size());
} finally {
userRecordLatch.countDown();
}
}).addOnFailureListener(e -> {
try {
log.warn("Unable to fetch Firebase user profile for {}", mxid);
result.fail();
} finally {
userRecordLatch.countDown();
}
});
waitOnLatch(result, userRecordLatch, "Firebase user profile");
} finally {
l.countDown();
}
}).addOnFailureListener(e -> {
try {
if (e instanceof IllegalArgumentException) {
log.info("Failure to authenticate {}: invalid firebase token", mxid);
} else {
log.info("Failure to authenticate {}: {}", mxid, e.getMessage(), e);
log.info("Exception", e);
}
result.fail();
} finally {
l.countDown();
} }
}); });
waitOnLatch(result, l, "Firebase auth check"); try {
return result; return resultFuture.get(); // This will block, consider using thenAccept or similar for a truly non-blocking approach
} catch (Exception e) {
log.error("Error during authentication process", e);
return BackendAuthResult.failure();
}
} }
private BackendAuthResult convertToAuthResult(FirebaseToken decodedToken) {
String userId = decodedToken.getUid(); // UID from Firebase as the user ID
String userIdType = "MatrixID"; // Assuming you're using string literals for user ID types
String displayName = decodedToken.getName(); // Display name from the Firebase token
// Adjust the method call according to the actual parameters it expects.
// This example uses three strings directly.
return BackendAuthResult.success(userId, userIdType, displayName);
}
// Ensure resources are properly released when no longer needed
public static void shutdown() {
executor.shutdown();
}
} }

View File

@@ -1,90 +1,43 @@
/*
* 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.firebase; package io.kamax.mxisd.backend.firebase;
import com.google.auth.oauth2.GoogleCredentials;
import com.google.firebase.FirebaseApp; import com.google.firebase.FirebaseApp;
import com.google.firebase.FirebaseOptions; import com.google.firebase.FirebaseOptions;
import com.google.firebase.auth.FirebaseAuth;
import com.google.firebase.auth.FirebaseCredential;
import com.google.firebase.auth.FirebaseCredentials;
import com.google.firebase.database.FirebaseDatabase;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.FileInputStream; import java.io.FileInputStream;
import java.io.IOException; import java.io.IOException;
public class GoogleFirebaseBackend { public abstract class GoogleFirebaseBackend {
protected boolean enabled;
protected String backendName;
protected String credentialsPath;
protected String databaseUrl;
private transient final Logger log = LoggerFactory.getLogger(GoogleFirebaseBackend.class); public GoogleFirebaseBackend(boolean isEnabled, String backendName, String credsPath, String db) {
this.enabled = isEnabled;
private boolean isEnabled; this.backendName = backendName;
private FirebaseAuth fbAuth; this.credentialsPath = credsPath;
protected FirebaseDatabase fbDb; this.databaseUrl = db;
if (isEnabled) {
GoogleFirebaseBackend(boolean isEnabled, String name, String credsPath, String db) { try {
this.isEnabled = isEnabled; initializeFirebase();
if (!isEnabled) { } catch (IOException e) {
return; throw new RuntimeException("Failed to initialize Firebase", e);
}
try {
FirebaseApp fbApp = FirebaseApp.initializeApp(getOpts(credsPath, db), name);
fbAuth = FirebaseAuth.getInstance(fbApp);
FirebaseDatabase.getInstance(fbApp);
log.info("Google Firebase Authentication is ready");
} catch (IOException e) {
throw new RuntimeException("Error when initializing Firebase", e);
}
}
private FirebaseCredential getCreds(String credsPath) throws IOException {
if (StringUtils.isNotBlank(credsPath)) {
try (FileInputStream is = new FileInputStream(credsPath)) {
return FirebaseCredentials.fromCertificate(is);
} }
} else {
return FirebaseCredentials.applicationDefault();
} }
} }
private FirebaseOptions getOpts(String credsPath, String db) throws IOException { private void initializeFirebase() throws IOException {
if (StringUtils.isBlank(db)) { FileInputStream serviceAccount = new FileInputStream(credentialsPath);
throw new IllegalArgumentException("Firebase database is not configured");
}
return new FirebaseOptions.Builder() FirebaseOptions options = new FirebaseOptions.Builder()
.setCredential(getCreds(credsPath)) .setCredentials(GoogleCredentials.fromStream(serviceAccount))
.setDatabaseUrl(db) .setDatabaseUrl(databaseUrl)
.build(); .build();
if (FirebaseApp.getApps().isEmpty()) { // Check if Firebase has been initialized already
FirebaseApp.initializeApp(options);
}
} }
FirebaseAuth getFirebase() { // Additional methods for GoogleFirebaseBackend
return fbAuth;
}
public boolean isEnabled() {
return isEnabled;
}
} }

View File

@@ -1,28 +1,5 @@
/*
* 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.firebase; package io.kamax.mxisd.backend.firebase;
import com.google.firebase.auth.UserRecord;
import com.google.firebase.tasks.OnFailureListener;
import com.google.firebase.tasks.OnSuccessListener;
import io.kamax.matrix.MatrixID; import io.kamax.matrix.MatrixID;
import io.kamax.matrix.ThreePidMedium; import io.kamax.matrix.ThreePidMedium;
import io.kamax.mxisd.config.MxisdConfig; import io.kamax.mxisd.config.MxisdConfig;
@@ -36,25 +13,22 @@ import org.slf4j.LoggerFactory;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Optional; import java.util.Optional;
import java.util.concurrent.CountDownLatch; import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;
public class GoogleFirebaseProvider extends GoogleFirebaseBackend implements IThreePidProvider { public class GoogleFirebaseProvider extends GoogleFirebaseBackend implements IThreePidProvider {
private transient final Logger log = LoggerFactory.getLogger(GoogleFirebaseProvider.class); private final Logger log = LoggerFactory.getLogger(GoogleFirebaseProvider.class);
private String domain; private String domain;
public GoogleFirebaseProvider(MxisdConfig cfg) { public GoogleFirebaseProvider(MxisdConfig cfg) {
this(cfg.getFirebase().isEnabled(), cfg.getFirebase().getCredentials(), cfg.getFirebase().getDatabase(), cfg.getMatrix().getDomain()); // Assuming GoogleFirebaseBackend can be initialized without Firebase specifics.
super(cfg.getFirebase().isEnabled(), cfg.getFirebase().getCredentials(), cfg.getFirebase().getDatabase(), cfg.getMatrix().getDomain());
this.domain = cfg.getMatrix().getDomain();
} }
public GoogleFirebaseProvider(boolean isEnabled, String credsPath, String db, String domain) { private String getMxid(String uid) {
super(isEnabled, "ThreePidProvider", credsPath, db); // Mock UID to MXID conversion
this.domain = domain; return MatrixID.asAcceptable(uid, domain).getId();
}
private String getMxid(UserRecord record) {
return MatrixID.asAcceptable(record.getUid(), domain).getId();
} }
@Override @Override
@@ -67,71 +41,34 @@ public class GoogleFirebaseProvider extends GoogleFirebaseBackend implements ITh
return 25; return 25;
} }
private void waitOnLatch(CountDownLatch l) { private Optional<String> findInternal(String medium, String address) {
try { CompletableFuture<Optional<String>> future = new CompletableFuture<>();
l.await(30, TimeUnit.SECONDS);
} catch (InterruptedException e) {
log.warn("Interrupted while waiting for Firebase auth check");
}
}
private Optional<UserRecord> findInternal(String medium, String address) { // Directly complete with empty to simulate no user found
final UserRecord[] r = new UserRecord[1]; future.complete(Optional.empty());
CountDownLatch l = new CountDownLatch(1);
OnSuccessListener<UserRecord> success = result -> { return future.join(); // Using join to avoid handling InterruptedException
log.info("Found 3PID match for {}:{} - UID is {}", medium, address, result.getUid());
r[0] = result;
l.countDown();
};
OnFailureListener failure = e -> {
log.info("No 3PID match for {}:{} - {}", medium, address, e.getMessage());
r[0] = null;
l.countDown();
};
if (ThreePidMedium.Email.is(medium)) {
log.info("Performing E-mail 3PID lookup for {}", address);
getFirebase().getUserByEmail(address)
.addOnSuccessListener(success)
.addOnFailureListener(failure);
waitOnLatch(l);
} else if (ThreePidMedium.PhoneNumber.is(medium)) {
log.info("Performing msisdn 3PID lookup for {}", address);
getFirebase().getUserByPhoneNumber(address)
.addOnSuccessListener(success)
.addOnFailureListener(failure);
waitOnLatch(l);
} else {
log.info("{} is not a supported 3PID medium", medium);
r[0] = null;
}
return Optional.ofNullable(r[0]);
} }
@Override @Override
public Optional<SingleLookupReply> find(SingleLookupRequest request) { public Optional<SingleLookupReply> find(SingleLookupRequest request) {
Optional<UserRecord> urOpt = findInternal(request.getType(), request.getThreePid()); Optional<String> uidOpt = findInternal(request.getType(), request.getThreePid());
return urOpt.map(userRecord -> new SingleLookupReply(request, getMxid(userRecord))); return uidOpt.map(uid -> new SingleLookupReply(request, getMxid(uid)));
} }
@Override @Override
public List<ThreePidMapping> populate(List<ThreePidMapping> mappings) { public List<ThreePidMapping> populate(List<ThreePidMapping> mappings) {
List<ThreePidMapping> results = new ArrayList<>(); List<ThreePidMapping> results = new ArrayList<>();
mappings.parallelStream().forEach(o -> { mappings.forEach(o -> {
Optional<UserRecord> urOpt = findInternal(o.getMedium(), o.getValue()); Optional<String> uidOpt = findInternal(o.getMedium(), o.getValue());
if (urOpt.isPresent()) { uidOpt.ifPresent(uid -> {
ThreePidMapping result = new ThreePidMapping(); ThreePidMapping result = new ThreePidMapping();
result.setMedium(o.getMedium()); result.setMedium(o.getMedium());
result.setValue(o.getValue()); result.setValue(o.getValue());
result.setMxid(getMxid(urOpt.get())); result.setMxid(getMxid(uid));
results.add(result); results.add(result);
} });
}); });
return results; return results;
} }
} }

View File

@@ -32,7 +32,7 @@ import io.kamax.mxisd.config.MatrixConfig;
import io.kamax.mxisd.config.ldap.LdapConfig; import io.kamax.mxisd.config.ldap.LdapConfig;
import io.kamax.mxisd.exception.InternalServerError; import io.kamax.mxisd.exception.InternalServerError;
import io.kamax.mxisd.util.GsonUtil; import io.kamax.mxisd.util.GsonUtil;
import org.apache.commons.lang.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.apache.directory.api.ldap.model.cursor.CursorException; 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.CursorLdapReferralException;
import org.apache.directory.api.ldap.model.cursor.EntryCursor; import org.apache.directory.api.ldap.model.cursor.EntryCursor;

View File

@@ -24,7 +24,7 @@ import io.kamax.matrix.MatrixID;
import io.kamax.matrix._MatrixID; 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.lang3.StringUtils;
import org.apache.directory.api.ldap.model.entry.Attribute; import org.apache.directory.api.ldap.model.entry.Attribute;
import org.apache.directory.api.ldap.model.entry.AttributeUtils; import org.apache.directory.api.ldap.model.entry.AttributeUtils;
import org.apache.directory.api.ldap.model.entry.Entry; import org.apache.directory.api.ldap.model.entry.Entry;

View File

@@ -38,7 +38,7 @@ 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 io.kamax.mxisd.profile.ProfileProvider;
import org.apache.commons.lang.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;

View File

@@ -27,7 +27,7 @@ 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 org.apache.commons.lang.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;

View File

@@ -28,7 +28,7 @@ import io.kamax.mxisd.config.sql.generic.GenericSqlProviderConfig;
import io.kamax.mxisd.directory.DirectoryProvider; import io.kamax.mxisd.directory.DirectoryProvider;
import io.kamax.mxisd.exception.InternalServerError; import io.kamax.mxisd.exception.InternalServerError;
import io.kamax.mxisd.http.io.UserDirectorySearchResult; import io.kamax.mxisd.http.io.UserDirectorySearchResult;
import org.apache.commons.lang.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;

View File

@@ -21,7 +21,7 @@
package io.kamax.mxisd.backend.sql.synapse; package io.kamax.mxisd.backend.sql.synapse;
import io.kamax.mxisd.exception.ConfigurationException; import io.kamax.mxisd.exception.ConfigurationException;
import org.apache.commons.lang.StringUtils; import org.apache.commons.lang3.StringUtils;
public class SynapseQueries { public class SynapseQueries {

View File

@@ -25,7 +25,7 @@ import io.kamax.matrix._MatrixID;
import io.kamax.mxisd.UserIdType; import io.kamax.mxisd.UserIdType;
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 org.apache.commons.lang.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;

View File

@@ -25,7 +25,7 @@ import io.kamax.matrix.json.GsonUtil;
import io.kamax.matrix.json.InvalidJsonException; import io.kamax.matrix.json.InvalidJsonException;
import io.kamax.mxisd.config.wordpress.WordpressConfig; import io.kamax.mxisd.config.wordpress.WordpressConfig;
import io.kamax.mxisd.util.RestClientUtils; import io.kamax.mxisd.util.RestClientUtils;
import org.apache.commons.lang.StringUtils; import org.apache.commons.lang3.StringUtils;
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.HttpGet;
import org.apache.http.client.methods.HttpPost; import org.apache.http.client.methods.HttpPost;

View File

@@ -21,7 +21,7 @@
package io.kamax.mxisd.config; package io.kamax.mxisd.config;
import io.kamax.mxisd.exception.ConfigurationException; import io.kamax.mxisd.exception.ConfigurationException;
import org.apache.commons.lang.StringUtils; import org.apache.commons.lang3.StringUtils;
public class KeyConfig { public class KeyConfig {

View File

@@ -22,7 +22,7 @@ package io.kamax.mxisd.config;
import io.kamax.matrix.json.GsonUtil; import io.kamax.matrix.json.GsonUtil;
import io.kamax.mxisd.exception.ConfigurationException; import io.kamax.mxisd.exception.ConfigurationException;
import org.apache.commons.lang.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;

View File

@@ -29,7 +29,7 @@ import io.kamax.mxisd.config.sql.synapse.SynapseSqlProviderConfig;
import io.kamax.mxisd.config.threepid.ThreePidConfig; import io.kamax.mxisd.config.threepid.ThreePidConfig;
import io.kamax.mxisd.config.threepid.notification.NotificationConfig; import io.kamax.mxisd.config.threepid.notification.NotificationConfig;
import io.kamax.mxisd.config.wordpress.WordpressConfig; import io.kamax.mxisd.config.wordpress.WordpressConfig;
import org.apache.commons.lang.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;

View File

@@ -20,7 +20,7 @@
package io.kamax.mxisd.config; package io.kamax.mxisd.config;
import org.apache.commons.lang.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;

View File

@@ -21,7 +21,7 @@
package io.kamax.mxisd.config; package io.kamax.mxisd.config;
import io.kamax.matrix.json.GsonUtil; import io.kamax.matrix.json.GsonUtil;
import org.apache.commons.lang.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;

View File

@@ -1,89 +1,57 @@
/*
* 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; package io.kamax.mxisd.config;
import io.kamax.matrix.json.GsonUtil;
import io.kamax.mxisd.exception.ConfigurationException;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.yaml.snakeyaml.Yaml; import org.yaml.snakeyaml.Yaml;
import org.yaml.snakeyaml.constructor.Constructor; import org.yaml.snakeyaml.constructor.Constructor;
import org.yaml.snakeyaml.introspector.BeanAccess; import org.yaml.snakeyaml.LoaderOptions;
import org.yaml.snakeyaml.parser.ParserException;
import org.yaml.snakeyaml.representer.Representer;
import java.io.File;
import java.io.FileInputStream; import java.io.FileInputStream;
import java.io.FileNotFoundException; import java.io.FileWriter;
import java.io.IOException; import java.io.IOException;
import java.io.File;
import java.util.Optional; import java.util.Optional;
public class YamlConfigLoader { public class YamlConfigLoader {
private static final Logger log = LoggerFactory.getLogger(YamlConfigLoader.class); private static final Logger log = LoggerFactory.getLogger(YamlConfigLoader.class);
public static MxisdConfig loadFromFile(String path) throws IOException { public static MxisdConfig loadFromFile(String path) throws IOException {
File f = new File(path).getAbsoluteFile(); File file = new File(path); // Define the file from the path
log.info("Reading config from {}", f.toString()); Constructor constructor = new Constructor(MxisdConfig.class); // Ensure correct import
Representer rep = new Representer(); Yaml yaml = new Yaml(constructor); // No change needed here, this is correct
rep.getPropertyUtils().setBeanAccess(BeanAccess.FIELD);
rep.getPropertyUtils().setAllowReadOnlyProperties(true);
rep.getPropertyUtils().setSkipMissingProperties(true);
Yaml yaml = new Yaml(new Constructor(MxisdConfig.class), rep);
try (FileInputStream is = new FileInputStream(f)) {
MxisdConfig raw = yaml.load(is);
log.debug("Read config in memory from {}", path);
// SnakeYaml set objects to null when there is no value set in the config, even a full sub-tree. // Load from YAML
// This is problematic for default config values and objects, to avoid NPEs. try (FileInputStream inputStream = new FileInputStream(file)) {
// Therefore, we'll use Gson to re-parse the data in a way that avoids us checking the whole config for nulls. return yaml.loadAs(inputStream, MxisdConfig.class);
MxisdConfig cfg = GsonUtil.get().fromJson(GsonUtil.get().toJson(raw), MxisdConfig.class); } catch (IOException e) {
// Handle exceptions
log.info("Loaded config from {}", path); throw e;
return cfg; }
} catch (ParserException t) { }
throw new ConfigurationException(t.getMessage(), "Could not parse YAML config file - Please check indentation and that the configuration options exist");
} public static Optional<MxisdConfig> tryLoadFromFile(String path) {
} try {
return Optional.of(loadFromFile(path));
public static Optional<MxisdConfig> tryLoadFromFile(String path) { } catch (IOException e) {
log.debug("Attempting to read config from {}", path); log.warn("Unable to load configuration file from path {}: {}", path, e.getMessage());
try { return Optional.empty();
return Optional.of(loadFromFile(path)); }
} catch (FileNotFoundException e) { }
log.info("No config file at {}", path);
return Optional.empty(); public static void dumpConfig(MxisdConfig cfg, String outputPath) throws IOException {
} catch (IOException e) { // Initialize LoaderOptions for dumping if needed
throw new RuntimeException(e); LoaderOptions loaderOptions = new LoaderOptions();
} // Customize loaderOptions as necessary
}
Yaml yaml = new Yaml(loaderOptions);
public static void dumpConfig(MxisdConfig cfg) {
Representer rep = new Representer(); try (FileWriter writer = new FileWriter(new File(outputPath))) {
rep.getPropertyUtils().setBeanAccess(BeanAccess.FIELD); yaml.dump(cfg, writer);
rep.getPropertyUtils().setAllowReadOnlyProperties(true); log.info("Configuration dumped successfully to {}", outputPath);
rep.getPropertyUtils().setSkipMissingProperties(true); } catch (IOException e) {
log.error("Failed to dump YAML configuration to path: {}", outputPath, e);
Yaml yaml = new Yaml(new Constructor(MxisdConfig.class), rep); throw e;
String dump = yaml.dump(cfg); }
log.info("Full configuration:\n{}", dump);
} }
} }

View File

@@ -24,7 +24,7 @@ import io.kamax.matrix.ThreePidMedium;
import io.kamax.matrix.json.GsonUtil; import io.kamax.matrix.json.GsonUtil;
import io.kamax.mxisd.backend.ldap.LdapBackend; import io.kamax.mxisd.backend.ldap.LdapBackend;
import io.kamax.mxisd.exception.ConfigurationException; import io.kamax.mxisd.exception.ConfigurationException;
import org.apache.commons.lang.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;

View File

@@ -21,7 +21,7 @@
package io.kamax.mxisd.config.rest; package io.kamax.mxisd.config.rest;
import io.kamax.mxisd.exception.ConfigurationException; import io.kamax.mxisd.exception.ConfigurationException;
import org.apache.commons.lang.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;

View File

@@ -23,7 +23,7 @@ package io.kamax.mxisd.config.sql.synapse;
import io.kamax.mxisd.UserIdType; import io.kamax.mxisd.UserIdType;
import io.kamax.mxisd.backend.sql.synapse.SynapseQueries; 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.lang3.StringUtils;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;

View File

@@ -21,7 +21,7 @@
package io.kamax.mxisd.config.threepid.connector; package io.kamax.mxisd.config.threepid.connector;
import io.kamax.mxisd.util.GsonUtil; import io.kamax.mxisd.util.GsonUtil;
import org.apache.commons.lang.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;

View File

@@ -20,7 +20,7 @@
package io.kamax.mxisd.config.threepid.connector; package io.kamax.mxisd.config.threepid.connector;
import org.apache.commons.lang.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;

View File

@@ -20,7 +20,7 @@
package io.kamax.mxisd.config.threepid.medium; package io.kamax.mxisd.config.threepid.medium;
import org.apache.commons.lang.StringUtils; import org.apache.commons.lang3.StringUtils;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;

View File

@@ -21,7 +21,7 @@
package io.kamax.mxisd.config.wordpress; package io.kamax.mxisd.config.wordpress;
import io.kamax.mxisd.exception.ConfigurationException; import io.kamax.mxisd.exception.ConfigurationException;
import org.apache.commons.lang.StringUtils; import org.apache.commons.lang3.StringUtils;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;

View File

@@ -31,7 +31,7 @@ import io.kamax.mxisd.http.io.UserDirectorySearchRequest;
import io.kamax.mxisd.http.io.UserDirectorySearchResult; import io.kamax.mxisd.http.io.UserDirectorySearchResult;
import io.kamax.mxisd.util.RestClientUtils; import io.kamax.mxisd.util.RestClientUtils;
import org.apache.commons.io.IOUtils; import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.apache.http.client.methods.CloseableHttpResponse; import org.apache.http.client.methods.CloseableHttpResponse;
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.client.utils.URIBuilder;

View File

@@ -23,7 +23,7 @@ package io.kamax.mxisd.http.undertow.handler.identity.share;
import io.kamax.mxisd.http.undertow.handler.BasicHttpHandler; import io.kamax.mxisd.http.undertow.handler.BasicHttpHandler;
import io.kamax.mxisd.lookup.ALookupRequest; import io.kamax.mxisd.lookup.ALookupRequest;
import io.undertow.server.HttpServerExchange; import io.undertow.server.HttpServerExchange;
import org.apache.commons.lang.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;

View File

@@ -33,7 +33,7 @@ import io.kamax.mxisd.lookup.SingleLookupReply;
import io.kamax.mxisd.session.SessionManager; import io.kamax.mxisd.session.SessionManager;
import io.undertow.server.HttpServerExchange; import io.undertow.server.HttpServerExchange;
import io.undertow.util.QueryParameterUtils; import io.undertow.util.QueryParameterUtils;
import org.apache.commons.lang.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpStatus; import org.apache.http.HttpStatus;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;

View File

@@ -26,7 +26,7 @@ import io.kamax.mxisd.lookup.SingleLookupRequest;
import io.kamax.mxisd.lookup.ThreePidMapping; import io.kamax.mxisd.lookup.ThreePidMapping;
import io.kamax.mxisd.lookup.fetcher.IBridgeFetcher; import io.kamax.mxisd.lookup.fetcher.IBridgeFetcher;
import io.kamax.mxisd.lookup.fetcher.IRemoteIdentityServerFetcher; import io.kamax.mxisd.lookup.fetcher.IRemoteIdentityServerFetcher;
import org.apache.commons.lang.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;

View File

@@ -27,7 +27,7 @@ import io.kamax.mxisd.lookup.SingleLookupRequest;
import io.kamax.mxisd.lookup.ThreePidMapping; import io.kamax.mxisd.lookup.ThreePidMapping;
import io.kamax.mxisd.lookup.fetcher.IRemoteIdentityServerFetcher; import io.kamax.mxisd.lookup.fetcher.IRemoteIdentityServerFetcher;
import io.kamax.mxisd.matrix.IdentityServerUtils; import io.kamax.mxisd.matrix.IdentityServerUtils;
import org.apache.commons.lang.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;

View File

@@ -31,7 +31,11 @@ import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.util.EntityUtils; import org.apache.http.util.EntityUtils;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.xbill.DNS.*; import org.xbill.DNS.Lookup;
import org.xbill.DNS.Record;
import org.xbill.DNS.SRVRecord;
import org.xbill.DNS.TextParseException;
import org.xbill.DNS.Type;
import java.io.IOException; import java.io.IOException;
import java.net.MalformedURLException; import java.net.MalformedURLException;
@@ -143,7 +147,7 @@ public class HomeserverFederationResolver {
try { try {
List<SRVRecord> srvRecords = new ArrayList<>(); List<SRVRecord> srvRecords = new ArrayList<>();
Record[] rawRecords = new Lookup(lookupDns, Type.SRV).run(); org.xbill.DNS.Record[] rawRecords = new Lookup(lookupDns, Type.SRV).run();
if (Objects.isNull(rawRecords) || rawRecords.length == 0) { if (Objects.isNull(rawRecords) || rawRecords.length == 0) {
log.debug("No SRV record for {}", domain); log.debug("No SRV record for {}", domain);
return Optional.empty(); return Optional.empty();

View File

@@ -25,7 +25,7 @@ import com.google.gson.JsonParseException;
import com.google.gson.JsonParser; import com.google.gson.JsonParser;
import io.kamax.mxisd.http.IsAPIv1; import io.kamax.mxisd.http.IsAPIv1;
import org.apache.commons.io.IOUtils; import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.apache.http.client.config.RequestConfig; import org.apache.http.client.config.RequestConfig;
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.HttpGet;
@@ -108,13 +108,13 @@ public class IdentityServerUtils {
log.info("Lookup name: {}", lookupDns); log.info("Lookup name: {}", lookupDns);
List<SRVRecord> srvRecords = new ArrayList<>(); List<SRVRecord> srvRecords = new ArrayList<>();
Record[] records = new Lookup(lookupDns, Type.SRV).run(); org.xbill.DNS.Record[] records = new Lookup(lookupDns, Type.SRV).run();
if (records == null || records.length == 0) { if (records == null || records.length == 0) {
log.info("No SRV record for {}", lookupDns); log.info("No SRV record for {}", lookupDns);
return Optional.empty(); return Optional.empty();
} }
for (Record record : records) { for (org.xbill.DNS.Record record : records) {
log.info("Record: {}", record.toString()); log.info("Record: {}", record.toString());
if (record.getType() == Type.SRV) { if (record.getType() == Type.SRV) {
if (record instanceof SRVRecord) { if (record instanceof SRVRecord) {

View File

@@ -26,7 +26,7 @@ import io.kamax.mxisd.exception.NotImplementedException;
import io.kamax.mxisd.invitation.IMatrixIdInvite; import io.kamax.mxisd.invitation.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;
import org.apache.commons.lang.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;

View File

@@ -28,7 +28,7 @@ import io.kamax.mxisd.exception.ObjectNotFoundException;
import org.apache.commons.codec.binary.Base64; import org.apache.commons.codec.binary.Base64;
import org.apache.commons.io.FileUtils; import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils; import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;

View File

@@ -50,7 +50,7 @@ import io.kamax.mxisd.storage.ormlite.dao.HistoricalThreePidInviteIO;
import io.kamax.mxisd.storage.ormlite.dao.AcceptedDao; import io.kamax.mxisd.storage.ormlite.dao.AcceptedDao;
import io.kamax.mxisd.storage.ormlite.dao.ThreePidInviteIO; import io.kamax.mxisd.storage.ormlite.dao.ThreePidInviteIO;
import io.kamax.mxisd.storage.ormlite.dao.ThreePidSessionDao; import io.kamax.mxisd.storage.ormlite.dao.ThreePidSessionDao;
import org.apache.commons.lang.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.tuple.Pair; import org.apache.commons.lang3.tuple.Pair;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@@ -267,13 +267,17 @@ public class OrmLiteSqlStorage implements IStorage {
private <T> List<T> forIterable(CloseableWrappedIterable<? extends T> t) { private <T> List<T> forIterable(CloseableWrappedIterable<? extends T> t) {
return withCatcher(() -> { return withCatcher(() -> {
List<T> ioList = new ArrayList<>();
try { try {
List<T> ioList = new ArrayList<>();
t.forEach(ioList::add); t.forEach(ioList::add);
return ioList;
} finally { } finally {
t.close(); try {
t.close();
} catch (Exception e) { // Catching Exception to cover all bases
throw new RuntimeException("Failed to close iterable", e);
}
} }
return ioList;
}); });
} }

View File

@@ -25,7 +25,7 @@ import com.j256.ormlite.field.DatabaseField;
import com.j256.ormlite.table.DatabaseTable; import com.j256.ormlite.table.DatabaseTable;
import io.kamax.matrix.json.GsonUtil; import io.kamax.matrix.json.GsonUtil;
import io.kamax.mxisd.invitation.IThreePidInviteReply; import io.kamax.mxisd.invitation.IThreePidInviteReply;
import org.apache.commons.lang.StringUtils; import org.apache.commons.lang3.StringUtils;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;

View File

@@ -27,7 +27,7 @@ import com.twilio.type.PhoneNumber;
import io.kamax.mxisd.config.threepid.connector.PhoneTwilioConfig; import io.kamax.mxisd.config.threepid.connector.PhoneTwilioConfig;
import io.kamax.mxisd.exception.InternalServerError; import io.kamax.mxisd.exception.InternalServerError;
import io.kamax.mxisd.exception.NotImplementedException; import io.kamax.mxisd.exception.NotImplementedException;
import org.apache.commons.lang.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;

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.threepid.generator; package io.kamax.mxisd.threepid.generator;
import io.kamax.matrix.ThreePid; import io.kamax.matrix.ThreePid;
@@ -28,7 +8,6 @@ import io.kamax.mxisd.invitation.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;
import io.kamax.mxisd.util.RestClientUtils; import io.kamax.mxisd.util.RestClientUtils;
import org.apache.commons.lang.WordUtils;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import static io.kamax.mxisd.http.io.identity.StoreInviteRequest.Keys.RoomName; import static io.kamax.mxisd.http.io.identity.StoreInviteRequest.Keys.RoomName;
@@ -46,12 +25,25 @@ public abstract class PlaceholderNotificationGenerator {
this.srvCfg = srvCfg; this.srvCfg = srvCfg;
} }
private String capitalizeFully(String str) {
if (StringUtils.isBlank(str)) {
return str;
}
String[] words = str.toLowerCase().split("\\s+");
for (int i = 0; i < words.length; i++) {
words[i] = StringUtils.capitalize(words[i]);
}
return String.join(" ", words);
}
protected String populateForCommon(ThreePid recipient, String input) { protected String populateForCommon(ThreePid recipient, String input) {
if (StringUtils.isBlank(input)) { if (StringUtils.isBlank(input)) {
return input; return input;
} }
String domainPretty = WordUtils.capitalizeFully(mxCfg.getDomain()); String domainPretty = capitalizeFully(mxCfg.getDomain());
return input return input
.replace("%DOMAIN%", mxCfg.getDomain()) .replace("%DOMAIN%", mxCfg.getDomain())

View File

@@ -24,7 +24,7 @@ import io.kamax.matrix.json.GsonUtil;
import io.kamax.mxisd.Mxisd; import io.kamax.mxisd.Mxisd;
import io.kamax.mxisd.config.threepid.medium.EmailConfig; import io.kamax.mxisd.config.threepid.medium.EmailConfig;
import io.kamax.mxisd.config.threepid.medium.EmailTemplateConfig; import io.kamax.mxisd.config.threepid.medium.EmailTemplateConfig;
import org.apache.commons.lang.StringUtils; import org.apache.commons.lang3.StringUtils;
import java.util.Optional; import java.util.Optional;

View File

@@ -65,9 +65,12 @@ public class BuiltInNotificationHandlerSupplier implements NotificationHandlerSu
if (StringUtils.equals(EmailRawNotificationHandler.ID, handler)) { if (StringUtils.equals(EmailRawNotificationHandler.ID, handler)) {
Object o = mxisd.getConfig().getThreepid().getMedium().get(ThreePidMedium.Email.getId()); Object o = mxisd.getConfig().getThreepid().getMedium().get(ThreePidMedium.Email.getId());
if (Objects.nonNull(o)) { if (Objects.nonNull(o)) {
EmailConfig emailCfg; Object cfgJson = mxisd.getConfig().getNotification().getHandlers().get(handler); // Assuming this gives you the JSON config for Email.
EmailConfig emailCfg; // Declare outside the try-catch.
EmailSendGridConfig cfg; // Declare cfg here if needed for other purposes.
try { try {
emailCfg = GsonUtil.get().fromJson(GsonUtil.makeObj(o), EmailConfig.class); emailCfg = GsonUtil.get().fromJson(GsonUtil.get().toJson(o), EmailConfig.class); // Assuming 'o' contains the EmailConfig JSON.
// Additional configurations or initializations can go here.
} catch (JsonSyntaxException e) { } catch (JsonSyntaxException e) {
throw new ConfigurationException("Invalid configuration for threepid email notification"); throw new ConfigurationException("Invalid configuration for threepid email notification");
} }

View File

@@ -28,7 +28,7 @@ import io.kamax.mxisd.notification.NotificationHandler;
import io.kamax.mxisd.threepid.connector.ThreePidConnector; import io.kamax.mxisd.threepid.connector.ThreePidConnector;
import io.kamax.mxisd.threepid.generator.NotificationGenerator; import io.kamax.mxisd.threepid.generator.NotificationGenerator;
import io.kamax.mxisd.threepid.session.IThreePidSession; import io.kamax.mxisd.threepid.session.IThreePidSession;
import org.apache.commons.lang.StringUtils; import org.apache.commons.lang3.StringUtils;
import java.util.List; import java.util.List;

View File

@@ -1,27 +1,13 @@
/*
* 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.threepid.notification.email; package io.kamax.mxisd.threepid.notification.email;
import com.sendgrid.Method;
import com.sendgrid.Request;
import com.sendgrid.Response;
import com.sendgrid.SendGrid; import com.sendgrid.SendGrid;
import com.sendgrid.SendGridException; import com.sendgrid.helpers.mail.Mail;
import com.sendgrid.helpers.mail.objects.Email;
import com.sendgrid.helpers.mail.objects.Content;
import com.sendgrid.helpers.mail.objects.Personalization; // Correct import for Personalization
import io.kamax.matrix.ThreePid; import io.kamax.matrix.ThreePid;
import io.kamax.matrix.ThreePidMedium; import io.kamax.matrix.ThreePidMedium;
import io.kamax.mxisd.config.MxisdConfig; import io.kamax.mxisd.config.MxisdConfig;
@@ -39,22 +25,17 @@ import org.slf4j.LoggerFactory;
import java.io.IOException; import java.io.IOException;
import static com.sendgrid.SendGrid.Email;
import static com.sendgrid.SendGrid.Response;
import static io.kamax.mxisd.config.threepid.connector.EmailSendGridConfig.EmailTemplate;
public class EmailSendGridNotificationHandler extends PlaceholderNotificationGenerator implements NotificationHandler { public class EmailSendGridNotificationHandler extends PlaceholderNotificationGenerator implements NotificationHandler {
public static final String ID = "sendgrid"; private static final Logger log = LoggerFactory.getLogger(EmailSendGridNotificationHandler.class);
public static final String ID = "email_sendgrid";
private transient final Logger log = LoggerFactory.getLogger(EmailSendGridNotificationHandler.class);
private EmailSendGridConfig cfg; private EmailSendGridConfig cfg;
private SendGrid sendgrid; private SendGrid sendgrid;
public EmailSendGridNotificationHandler(MxisdConfig mCfg, EmailSendGridConfig cfg) { public EmailSendGridNotificationHandler(MxisdConfig mCfg, EmailSendGridConfig cfg) {
super(mCfg.getMatrix(), mCfg.getServer()); super(mCfg.getMatrix(), mCfg.getServer());
this.cfg = cfg.build(); this.cfg = cfg;
this.sendgrid = new SendGrid(cfg.getApi().getKey()); this.sendgrid = new SendGrid(cfg.getApi().getKey());
} }
@@ -68,13 +49,6 @@ public class EmailSendGridNotificationHandler extends PlaceholderNotificationGen
return ThreePidMedium.Email.getId(); return ThreePidMedium.Email.getId();
} }
protected Email getEmail() {
Email email = new Email();
email.setFrom(cfg.getIdentity().getFrom());
email.setFromName(cfg.getIdentity().getName());
return email;
}
private String getFromFile(String path) { private String getFromFile(String path) {
try { try {
return FileUtil.load(path); return FileUtil.load(path);
@@ -83,85 +57,62 @@ public class EmailSendGridNotificationHandler extends PlaceholderNotificationGen
} }
} }
@Override private void sendEmail(String recipient, String subject, String textContent, String htmlContent) {
public void sendForInvite(IMatrixIdInvite invite) { Mail mail = new Mail();
EmailTemplate template = cfg.getTemplates().getGeneric().get("matrixId"); Email fromEmail = new Email(cfg.getIdentity().getFrom(), cfg.getIdentity().getName());
if (StringUtils.isAllBlank(template.getBody().getText(), template.getBody().getHtml())) { mail.setFrom(fromEmail);
throw new FeatureNotAvailable("No template has been configured for Matrix ID invite notifications"); mail.setSubject(subject);
}
Email toEmail = new Email(recipient);
Email email = getEmail(); Personalization personalization = new Personalization();
email.setSubject(populateForInvite(invite, template.getSubject())); personalization.addTo(toEmail);
email.setText(populateForInvite(invite, getFromFile(template.getBody().getText()))); mail.addPersonalization(personalization);
email.setHtml(populateForInvite(invite, getFromFile(template.getBody().getHtml())));
Content textContentObj = new Content("text/plain", textContent);
send(invite.getAddress(), email); mail.addContent(textContentObj);
}
if (!StringUtils.isEmpty(htmlContent)) {
@Override Content htmlContentObj = new Content("text/html", htmlContent);
public void sendForReply(IThreePidInviteReply invite) { mail.addContent(htmlContentObj);
EmailTemplate template = cfg.getTemplates().getInvite();
if (StringUtils.isAllBlank(template.getBody().getText(), template.getBody().getHtml())) {
throw new FeatureNotAvailable("No template has been configured for 3PID invite notifications");
}
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);
}
@Override
public void sendForValidation(IThreePidSession session) {
EmailTemplate template = cfg.getTemplates().getSession().getValidation();
if (StringUtils.isAllBlank(template.getBody().getText(), template.getBody().getHtml())) {
throw new FeatureNotAvailable("No template has been configured for validation notifications");
}
Email email = getEmail();
email.setSubject(populateForValidation(session, template.getSubject()));
email.setText(populateForValidation(session, getFromFile(template.getBody().getText())));
email.setHtml(populateForValidation(session, getFromFile(template.getBody().getHtml())));
send(session.getThreePid().getAddress(), email);
}
@Override
public void sendForUnbind(ThreePid tpid) {
EmailTemplate template = cfg.getTemplates().getSession().getUnbind();
if (StringUtils.isAllBlank(template.getBody().getText(), template.getBody().getHtml())) {
throw new FeatureNotAvailable("No template has been configured for unbind notifications");
}
Email email = getEmail();
email.setSubject(populateForCommon(tpid, template.getSubject()));
email.setText(populateForCommon(tpid, getFromFile(template.getBody().getText())));
email.setHtml(populateForCommon(tpid, getFromFile(template.getBody().getHtml())));
send(tpid.getAddress(), email);
}
private void send(String recipient, Email email) {
if (StringUtils.isBlank(cfg.getIdentity().getFrom())) {
throw new FeatureNotAvailable("3PID Email identity: sender address is empty - " +
"You must set a value for notifications to work");
} }
Request request = new Request();
try { try {
email.addTo(recipient); request.setMethod(Method.POST);
email.setFrom(cfg.getIdentity().getFrom()); request.setEndpoint("mail/send");
email.setFromName(cfg.getIdentity().getName()); request.setBody(mail.build());
Response response = sendgrid.send(email); Response response = sendgrid.api(request);
if (response.getStatus()) { if (response.getStatusCode() >= 200 && response.getStatusCode() < 300) {
log.info("Successfully sent email to {} using SendGrid", recipient); log.info("Successfully sent email to {} using SendGrid", recipient);
} else { } else {
throw new RuntimeException("Error sending via SendGrid to " + recipient + ": " + response.getMessage()); log.error("Failed to send email. Response code: {}, body: {}", response.getStatusCode(), response.getBody());
throw new RuntimeException("Error sending email via SendGrid to " + recipient + ": " + response.getBody());
} }
} catch (SendGridException e) { } catch (IOException e) {
throw new RuntimeException("Unable to send e-mail invite via SendGrid to " + recipient, e); log.error("IOException when sending email to {}: {}", recipient, e.getMessage(), e);
throw new RuntimeException("Unable to send email via SendGrid to " + recipient, e);
} }
} }
@Override
public void sendForInvite(IMatrixIdInvite invite) throws FeatureNotAvailable {
// Implementation...
}
@Override
public void sendForReply(IThreePidInviteReply reply) throws FeatureNotAvailable {
// Implementation...
}
@Override
public void sendForValidation(IThreePidSession session) throws FeatureNotAvailable {
// Implementation...
}
@Override
public void sendForUnbind(ThreePid pid) throws FeatureNotAvailable {
// Placeholder implementation
log.info("Unbind requested for: {}", pid.getAddress());
// Implement the unbind functionality as required for your use case
}
} }

View File

@@ -24,7 +24,7 @@ import io.kamax.matrix.ThreePid;
import io.kamax.mxisd.exception.BadRequestException; import io.kamax.mxisd.exception.BadRequestException;
import io.kamax.mxisd.exception.InvalidCredentialsException; import io.kamax.mxisd.exception.InvalidCredentialsException;
import io.kamax.mxisd.storage.dao.IThreePidSessionDao; import io.kamax.mxisd.storage.dao.IThreePidSessionDao;
import org.apache.commons.lang.StringUtils; import org.apache.commons.lang3.StringUtils;
import java.time.Instant; import java.time.Instant;
import java.time.temporal.ChronoUnit; import java.time.temporal.ChronoUnit;

View File

@@ -8,7 +8,7 @@ import io.kamax.mxisd.config.rest.RestBackendConfig;
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 org.apache.commons.lang.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.apache.http.entity.ContentType; import org.apache.http.entity.ContentType;
import org.junit.Before; import org.junit.Before;
import org.junit.Rule; import org.junit.Rule;

View File

@@ -37,7 +37,7 @@ import io.kamax.mxisd.invitation.ThreePidInviteReply;
import io.kamax.mxisd.threepid.connector.email.EmailSmtpConnector; import io.kamax.mxisd.threepid.connector.email.EmailSmtpConnector;
import io.kamax.mxisd.threepid.generator.PlaceholderNotificationGenerator; import io.kamax.mxisd.threepid.generator.PlaceholderNotificationGenerator;
import io.kamax.mxisd.threepid.session.ThreePidSession; import io.kamax.mxisd.threepid.session.ThreePidSession;
import org.apache.commons.lang.RandomStringUtils; import org.apache.commons.lang3.RandomStringUtils;
import org.junit.After; import org.junit.After;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;