mirror of
https://github.com/NixOS/nixpkgs.git
synced 2025-01-22 14:45:27 +00:00
nixos/prosody: make defaults comply with XEP-0423
Setting up a XMPP chat server is a pretty deep rabbit whole to jump in when you're not familiar with this whole universe. Your experience with this environment will greatly depends on whether or not your server implements the right set of XEPs. To tackle this problem, the XMPP community came with the idea of creating a meta-XEP in charge of listing the desirable XEPs to comply with. This meta-XMP is issued every year under an new XEP number. The 2020 one being XEP-0423[1]. This prosody nixos module refactoring makes complying with XEP-0423 easier. All the necessary extensions are enabled by default. For some extensions (MUC and HTTP_UPLOAD), we need some input from the user and cannot provide a sensible default nixpkgs-wide. For those, we guide the user using a couple of assertions explaining the remaining manual steps to perform. We took advantage of this substential refactoring to refresh the associated nixos test. Changelog: - Update the prosody package to provide the necessary community modules in order to comply with XEP-0423. This is a tradeoff, as depending on their configuration, the user might end up not using them and wasting some disk space. That being said, adding those will allow the XEP-0423 users, which I expect to be the majority of users, to leverage a bit more the binary cache. - Add a muc submodule populated with the prosody muc defaults. - Add a http_upload submodule in charge of setting up a basic http server handling the user uploads. This submodule is in is spinning up an HTTP(s) server in charge of receiving and serving the user's attachments. - Advertise both the MUCs and the http_upload endpoints using mod disco. - Use the slixmpp library in place of the now defunct sleekxmpp for the prosody NixOS test. - Update the nixos test to setup and test the MUC and http upload features. - Add a couple of assertions triggered if the setup is not xep-0423 compliant. [1] https://xmpp.org/extensions/xep-0423.html
This commit is contained in:
parent
5e4abf76c7
commit
8aea528872
|
@ -1,9 +1,7 @@
|
|||
{ config, lib, pkgs, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
|
||||
cfg = config.services.prosody;
|
||||
|
||||
sslOpts = { ... }: {
|
||||
|
@ -30,8 +28,21 @@ let
|
|||
};
|
||||
};
|
||||
|
||||
discoOpts = {
|
||||
options = {
|
||||
url = mkOption {
|
||||
type = types.str;
|
||||
description = "URL of the endpoint you want to make discoverable";
|
||||
};
|
||||
description = mkOption {
|
||||
type = types.str;
|
||||
description = "A short description of the endpoint you want to advertise";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
moduleOpts = {
|
||||
# Generally required
|
||||
# Required for compliance with https://compliance.conversations.im/about/
|
||||
roster = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
|
@ -69,6 +80,18 @@ let
|
|||
description = "Keep multiple clients in sync";
|
||||
};
|
||||
|
||||
csi = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
description = "Implements the CSI protocol that allows clients to report their active/inactive state to the server";
|
||||
};
|
||||
|
||||
cloud_notify = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
description = "Push notifications to inform users of new messages or other pertinent information even when they have no XMPP clients online";
|
||||
};
|
||||
|
||||
pep = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
|
@ -89,10 +112,22 @@ let
|
|||
|
||||
vcard = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
default = false;
|
||||
description = "Allow users to set vCards";
|
||||
};
|
||||
|
||||
vcard_legacy = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
description = "Converts users profiles and Avatars between old and new formats";
|
||||
};
|
||||
|
||||
bookmarks = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
description = "Allows interop between older clients that use XEP-0048: Bookmarks in its 1.0 version and recent clients which use it in PEP";
|
||||
};
|
||||
|
||||
# Nice to have
|
||||
version = mkOption {
|
||||
type = types.bool;
|
||||
|
@ -126,10 +161,16 @@ let
|
|||
|
||||
mam = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
default = true;
|
||||
description = "Store messages in an archive and allow users to access it";
|
||||
};
|
||||
|
||||
smacks = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
description = "Allow a client to resume a disconnected session, and prevent message loss";
|
||||
};
|
||||
|
||||
# Admin interfaces
|
||||
admin_adhoc = mkOption {
|
||||
type = types.bool;
|
||||
|
@ -137,6 +178,18 @@ let
|
|||
description = "Allows administration via an XMPP client that supports ad-hoc commands";
|
||||
};
|
||||
|
||||
http_files = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
description = "Serve static files from a directory over HTTP";
|
||||
};
|
||||
|
||||
proxy65 = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
description = "Enables a file transfer proxy service which clients behind NAT can use";
|
||||
};
|
||||
|
||||
admin_telnet = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
|
@ -156,12 +209,6 @@ let
|
|||
description = "Enable WebSocket support";
|
||||
};
|
||||
|
||||
http_files = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
description = "Serve static files from a directory over HTTP";
|
||||
};
|
||||
|
||||
# Other specific functionality
|
||||
limits = mkOption {
|
||||
type = types.bool;
|
||||
|
@ -210,13 +257,6 @@ let
|
|||
default = false;
|
||||
description = "Legacy authentication. Only used by some old clients and bots";
|
||||
};
|
||||
|
||||
proxy65 = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
description = "Enables a file transfer proxy service which clients behind NAT can use";
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
toLua = x:
|
||||
|
@ -235,6 +275,153 @@ let
|
|||
};
|
||||
'';
|
||||
|
||||
mucOpts = { ... }: {
|
||||
options = {
|
||||
domain = mkOption {
|
||||
type = types.str;
|
||||
description = "Domain name of the MUC";
|
||||
};
|
||||
name = mkOption {
|
||||
type = types.str;
|
||||
description = "The name to return in service discovery responses for the MUC service itself";
|
||||
default = "Prosody Chatrooms";
|
||||
};
|
||||
restrictRoomCreation = mkOption {
|
||||
type = types.enum [ true false "admin" "local" ];
|
||||
default = false;
|
||||
description = "Restrict room creation to server admins";
|
||||
};
|
||||
maxHistoryMessages = mkOption {
|
||||
type = types.int;
|
||||
default = 20;
|
||||
description = "Specifies a limit on what each room can be configured to keep";
|
||||
};
|
||||
roomLocking = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
description = ''
|
||||
Enables room locking, which means that a room must be
|
||||
configured before it can be used. Locked rooms are invisible
|
||||
and cannot be entered by anyone but the creator
|
||||
'';
|
||||
};
|
||||
roomLockTimeout = mkOption {
|
||||
type = types.int;
|
||||
default = 300;
|
||||
description = ''
|
||||
Timout after which the room is destroyed or unlocked if not
|
||||
configured, in seconds
|
||||
'';
|
||||
};
|
||||
tombstones = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
description = ''
|
||||
When a room is destroyed, it leaves behind a tombstone which
|
||||
prevents the room being entered or recreated. It also allows
|
||||
anyone who was not in the room at the time it was destroyed
|
||||
to learn about it, and to update their bookmarks. Tombstones
|
||||
prevents the case where someone could recreate a previously
|
||||
semi-anonymous room in order to learn the real JIDs of those
|
||||
who often join there.
|
||||
'';
|
||||
};
|
||||
tombstoneExpiry = mkOption {
|
||||
type = types.int;
|
||||
default = 2678400;
|
||||
description = ''
|
||||
This settings controls how long a tombstone is considered
|
||||
valid. It defaults to 31 days. After this time, the room in
|
||||
question can be created again.
|
||||
'';
|
||||
};
|
||||
|
||||
vcard_muc = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
description = "Adds the ability to set vCard for Multi User Chat rooms";
|
||||
};
|
||||
|
||||
# Extra parameters. Defaulting to prosody default values.
|
||||
# Adding them explicitly to make them visible from the options
|
||||
# documentation.
|
||||
#
|
||||
# See https://prosody.im/doc/modules/mod_muc for more details.
|
||||
roomDefaultPublic = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
description = "If set, the MUC rooms will be public by default.";
|
||||
};
|
||||
roomDefaultMembersOnly = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
description = "If set, the MUC rooms will only be accessible to the members by default.";
|
||||
};
|
||||
roomDefaultModerated = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
description = "If set, the MUC rooms will be moderated by default.";
|
||||
};
|
||||
roomDefaultPublicJids = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
description = "If set, the MUC rooms will display the public JIDs by default.";
|
||||
};
|
||||
roomDefaultChangeSubject = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
description = "If set, the rooms will display the public JIDs by default.";
|
||||
};
|
||||
roomDefaultHistoryLength = mkOption {
|
||||
type = types.int;
|
||||
default = 20;
|
||||
description = "Number of history message sent to participants by default.";
|
||||
};
|
||||
roomDefaultLanguage = mkOption {
|
||||
type = types.str;
|
||||
default = "en";
|
||||
description = "Default room language.";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
uploadHttpOpts = { ... }: {
|
||||
options = {
|
||||
domain = mkOption {
|
||||
type = types.nullOr types.str;
|
||||
description = "Domain name for the http-upload service";
|
||||
};
|
||||
uploadFileSizeLimit = mkOption {
|
||||
type = types.str;
|
||||
default = "50 * 1024 * 1024";
|
||||
description = "Maximum file size, in bytes. Defaults to 50MB.";
|
||||
};
|
||||
uploadExpireAfter = mkOption {
|
||||
type = types.str;
|
||||
default = "60 * 60 * 24 * 7";
|
||||
description = "Max age of a file before it gets deleted, in seconds.";
|
||||
};
|
||||
userQuota = mkOption {
|
||||
type = types.nullOr types.int;
|
||||
default = null;
|
||||
example = 1234;
|
||||
description = ''
|
||||
Maximum size of all uploaded files per user, in bytes. There
|
||||
will be no quota if this option is set to null.
|
||||
'';
|
||||
};
|
||||
httpUploadPath = mkOption {
|
||||
type = types.str;
|
||||
description = ''
|
||||
Directory where the uploaded files will be stored. By
|
||||
default, uploaded files are put in a sub-directory of the
|
||||
default Prosody storage path (usually /var/lib/prosody).
|
||||
'';
|
||||
default = "/var/lib/prosody";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
vHostOpts = { ... }: {
|
||||
|
||||
options = {
|
||||
|
@ -283,6 +470,27 @@ in
|
|||
description = "Whether to enable the prosody server";
|
||||
};
|
||||
|
||||
xmppComplianceSuite = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
description = ''
|
||||
The XEP-0423 defines a set of recommended XEPs to implement
|
||||
for a server. It's generally a good idea to implement this
|
||||
set of extensions if you want to provide your users with a
|
||||
good XMPP experience.
|
||||
|
||||
This NixOS module aims to provide a "advanced server"
|
||||
experience as per defined in the XEP-0423[1] specification.
|
||||
|
||||
Setting this option to true will prevent you from building a
|
||||
NixOS configuration which won't comply with this standard.
|
||||
You can explicitely decide to ignore this standard if you
|
||||
know what you are doing by setting this option to false.
|
||||
|
||||
[1] https://xmpp.org/extensions/xep-0423.html
|
||||
'';
|
||||
};
|
||||
|
||||
package = mkOption {
|
||||
type = types.package;
|
||||
description = "Prosody package to use";
|
||||
|
@ -302,6 +510,12 @@ in
|
|||
default = "/var/lib/prosody";
|
||||
};
|
||||
|
||||
disco_items = mkOption {
|
||||
type = types.listOf (types.submodule discoOpts);
|
||||
default = [];
|
||||
description = "List of discoverable items you want to advertise.";
|
||||
};
|
||||
|
||||
user = mkOption {
|
||||
type = types.str;
|
||||
default = "prosody";
|
||||
|
@ -320,6 +534,31 @@ in
|
|||
description = "Allow account creation";
|
||||
};
|
||||
|
||||
# HTTP server-related options
|
||||
httpPorts = mkOption {
|
||||
type = types.listOf types.int;
|
||||
description = "Listening HTTP ports list for this service.";
|
||||
default = [ 5280 ];
|
||||
};
|
||||
|
||||
httpInterfaces = mkOption {
|
||||
type = types.listOf types.str;
|
||||
default = [ "*" "::" ];
|
||||
description = "Interfaces on which the HTTP server will listen on.";
|
||||
};
|
||||
|
||||
httpsPorts = mkOption {
|
||||
type = types.listOf types.int;
|
||||
description = "Listening HTTPS ports list for this service.";
|
||||
default = [ 5281 ];
|
||||
};
|
||||
|
||||
httpsInterfaces = mkOption {
|
||||
type = types.listOf types.str;
|
||||
default = [ "*" "::" ];
|
||||
description = "Interfaces on which the HTTPS server will listen on.";
|
||||
};
|
||||
|
||||
c2sRequireEncryption = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
|
@ -387,6 +626,26 @@ in
|
|||
description = "Addtional path in which to look find plugins/modules";
|
||||
};
|
||||
|
||||
uploadHttp = mkOption {
|
||||
description = ''
|
||||
Configures the Prosody builtin HTTP server to handle user uploads.
|
||||
'';
|
||||
type = types.nullOr (types.submodule uploadHttpOpts);
|
||||
default = null;
|
||||
example = {
|
||||
domain = "uploads.my-xmpp-example-host.org";
|
||||
};
|
||||
};
|
||||
|
||||
muc = mkOption {
|
||||
type = types.listOf (types.submodule mucOpts);
|
||||
default = [ ];
|
||||
example = [ {
|
||||
domain = "conference.my-xmpp-example-host.org";
|
||||
} ];
|
||||
description = "Multi User Chat (MUC) configuration";
|
||||
};
|
||||
|
||||
virtualHosts = mkOption {
|
||||
|
||||
description = "Define the virtual hosts";
|
||||
|
@ -443,9 +702,44 @@ in
|
|||
|
||||
config = mkIf cfg.enable {
|
||||
|
||||
assertions = let
|
||||
genericErrMsg = ''
|
||||
|
||||
Having a server not XEP-0423-compliant might make your XMPP
|
||||
experience terrible. See the NixOS manual for further
|
||||
informations.
|
||||
|
||||
If you know what you're doing, you can disable this warning by
|
||||
setting config.services.prosody.xmppComplianceSuite to false.
|
||||
'';
|
||||
errors = [
|
||||
{ assertion = (builtins.length cfg.muc > 0) || !cfg.xmppComplianceSuite;
|
||||
message = ''
|
||||
You need to setup at least a MUC domain to comply with
|
||||
XEP-0423.
|
||||
'' + genericErrMsg;}
|
||||
{ assertion = cfg.uploadHttp != null || !cfg.xmppComplianceSuite;
|
||||
message = ''
|
||||
You need to setup the uploadHttp module through
|
||||
config.services.prosody.uploadHttp to comply with
|
||||
XEP-0423.
|
||||
'' + genericErrMsg;}
|
||||
];
|
||||
in errors;
|
||||
|
||||
environment.systemPackages = [ cfg.package ];
|
||||
|
||||
environment.etc."prosody/prosody.cfg.lua".text = ''
|
||||
environment.etc."prosody/prosody.cfg.lua".text =
|
||||
let
|
||||
httpDiscoItems = if (cfg.uploadHttp != null)
|
||||
then [{ url = cfg.uploadHttp.domain; description = "HTTP upload endpoint";}]
|
||||
else [];
|
||||
mucDiscoItems = builtins.foldl'
|
||||
(acc: muc: [{ url = muc.domain; description = "${muc.domain} MUC endpoint";}] ++ acc)
|
||||
[]
|
||||
cfg.muc;
|
||||
discoItems = cfg.disco_items ++ httpDiscoItems ++ mucDiscoItems;
|
||||
in ''
|
||||
|
||||
pidfile = "/run/prosody/prosody.pid"
|
||||
|
||||
|
@ -472,6 +766,10 @@ in
|
|||
${ lib.concatStringsSep "\n" (map (x: "${toLua x};") cfg.extraModules)}
|
||||
};
|
||||
|
||||
disco_items = {
|
||||
${ lib.concatStringsSep "\n" (builtins.map (x: ''{ "${x.url}", "${x.description}"};'') discoItems)}
|
||||
};
|
||||
|
||||
allow_registration = ${toLua cfg.allowRegistration}
|
||||
|
||||
c2s_require_encryption = ${toLua cfg.c2sRequireEncryption}
|
||||
|
@ -486,6 +784,42 @@ in
|
|||
|
||||
authentication = ${toLua cfg.authentication}
|
||||
|
||||
http_interfaces = ${toLua cfg.httpInterfaces}
|
||||
|
||||
https_interfaces = ${toLua cfg.httpsInterfaces}
|
||||
|
||||
http_ports = ${toLua cfg.httpPorts}
|
||||
|
||||
https_ports = ${toLua cfg.httpsPorts}
|
||||
|
||||
${lib.concatMapStrings (muc: ''
|
||||
Component ${toLua muc.domain} "muc"
|
||||
modules_enabled = { "muc_mam"; ${optionalString muc.vcard_muc ''"vcard_muc";'' } }
|
||||
name = ${toLua muc.name}
|
||||
restrict_room_creation = ${toLua muc.restrictRoomCreation}
|
||||
max_history_messages = ${toLua muc.maxHistoryMessages}
|
||||
muc_room_locking = ${toLua muc.roomLocking}
|
||||
muc_room_lock_timeout = ${toLua muc.roomLockTimeout}
|
||||
muc_tombstones = ${toLua muc.tombstones}
|
||||
muc_tombstone_expiry = ${toLua muc.tombstoneExpiry}
|
||||
muc_room_default_public = ${toLua muc.roomDefaultPublic}
|
||||
muc_room_default_members_only = ${toLua muc.roomDefaultMembersOnly}
|
||||
muc_room_default_moderated = ${toLua muc.roomDefaultModerated}
|
||||
muc_room_default_public_jids = ${toLua muc.roomDefaultPublicJids}
|
||||
muc_room_default_change_subject = ${toLua muc.roomDefaultChangeSubject}
|
||||
muc_room_default_history_length = ${toLua muc.roomDefaultHistoryLength}
|
||||
muc_room_default_language = ${toLua muc.roomDefaultLanguage}
|
||||
|
||||
'') cfg.muc}
|
||||
|
||||
${ lib.optionalString (cfg.uploadHttp != null) ''
|
||||
Component ${toLua cfg.uploadHttp.domain} "http_upload"
|
||||
http_upload_file_size_limit = ${cfg.uploadHttp.uploadFileSizeLimit}
|
||||
http_upload_expire_after = ${cfg.uploadHttp.uploadExpireAfter}
|
||||
${lib.optionalString (cfg.uploadHttp.userQuota != null) "http_upload_quota = ${toLua cfg.uploadHttp.userQuota}"}
|
||||
http_upload_path = ${toLua cfg.uploadHttp.httpUploadPath}
|
||||
''}
|
||||
|
||||
${ cfg.extraConfig }
|
||||
|
||||
${ lib.concatStringsSep "\n" (lib.mapAttrsToList (n: v: ''
|
||||
|
|
|
@ -1,27 +1,80 @@
|
|||
import ../make-test-python.nix {
|
||||
name = "prosody";
|
||||
let
|
||||
cert = pkgs: pkgs.runCommandNoCC "selfSignedCerts" { buildInputs = [ pkgs.openssl ]; } ''
|
||||
openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -nodes -subj '/CN=example.com/CN=uploads.example.com/CN=conference.example.com'
|
||||
mkdir -p $out
|
||||
cp key.pem cert.pem $out
|
||||
'';
|
||||
createUsers = pkgs: pkgs.writeScriptBin "create-prosody-users" ''
|
||||
#!${pkgs.bash}/bin/bash
|
||||
set -e
|
||||
|
||||
# Creates and set password for the 2 xmpp test users.
|
||||
#
|
||||
# Doing that in a bash script instead of doing that in the test
|
||||
# script allow us to easily provision the users when running that
|
||||
# test interactively.
|
||||
|
||||
prosodyctl register cthon98 example.com nothunter2
|
||||
prosodyctl register azurediamond example.com hunter2
|
||||
'';
|
||||
delUsers = pkgs: pkgs.writeScriptBin "delete-prosody-users" ''
|
||||
#!${pkgs.bash}/bin/bash
|
||||
set -e
|
||||
|
||||
# Deletes the test users.
|
||||
#
|
||||
# Doing that in a bash script instead of doing that in the test
|
||||
# script allow us to easily provision the users when running that
|
||||
# test interactively.
|
||||
|
||||
prosodyctl deluser cthon98@example.com
|
||||
prosodyctl deluser azurediamond@example.com
|
||||
'';
|
||||
in import ../make-test-python.nix {
|
||||
name = "prosody";
|
||||
nodes = {
|
||||
client = { nodes, pkgs, ... }: {
|
||||
client = { nodes, pkgs, config, ... }: {
|
||||
security.pki.certificateFiles = [ "${cert pkgs}/cert.pem" ];
|
||||
console.keyMap = "fr-bepo";
|
||||
networking.extraHosts = ''
|
||||
${nodes.server.config.networking.primaryIPAddress} example.com
|
||||
${nodes.server.config.networking.primaryIPAddress} conference.example.com
|
||||
${nodes.server.config.networking.primaryIPAddress} uploads.example.com
|
||||
'';
|
||||
environment.systemPackages = [
|
||||
(pkgs.callPackage ./xmpp-sendmessage.nix { connectTo = nodes.server.config.networking.primaryIPAddress; })
|
||||
];
|
||||
};
|
||||
server = { config, pkgs, ... }: {
|
||||
security.pki.certificateFiles = [ "${cert pkgs}/cert.pem" ];
|
||||
console.keyMap = "fr-bepo";
|
||||
networking.extraHosts = ''
|
||||
${config.networking.primaryIPAddress} example.com
|
||||
${config.networking.primaryIPAddress} conference.example.com
|
||||
${config.networking.primaryIPAddress} uploads.example.com
|
||||
'';
|
||||
networking.firewall.enable = false;
|
||||
environment.systemPackages = [
|
||||
(createUsers pkgs)
|
||||
(delUsers pkgs)
|
||||
];
|
||||
services.prosody = {
|
||||
enable = true;
|
||||
# TODO: use a self-signed certificate
|
||||
c2sRequireEncryption = false;
|
||||
extraConfig = ''
|
||||
storage = "sql"
|
||||
'';
|
||||
virtualHosts.test = {
|
||||
ssl.cert = "${cert pkgs}/cert.pem";
|
||||
ssl.key = "${cert pkgs}/key.pem";
|
||||
virtualHosts.example = {
|
||||
domain = "example.com";
|
||||
enabled = true;
|
||||
ssl.cert = "${cert pkgs}/cert.pem";
|
||||
ssl.key = "${cert pkgs}/key.pem";
|
||||
};
|
||||
muc = [
|
||||
{
|
||||
domain = "conference.example.com";
|
||||
}
|
||||
];
|
||||
uploadHttp = {
|
||||
domain = "uploads.example.com";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
@ -31,16 +84,8 @@ import ../make-test-python.nix {
|
|||
server.wait_for_unit("prosody.service")
|
||||
server.succeed('prosodyctl status | grep "Prosody is running"')
|
||||
|
||||
# set password to 'nothunter2' (it's asked twice)
|
||||
server.succeed("yes nothunter2 | prosodyctl adduser cthon98@example.com")
|
||||
# set password to 'y'
|
||||
server.succeed("yes | prosodyctl adduser azurediamond@example.com")
|
||||
# correct password to "hunter2"
|
||||
server.succeed("yes hunter2 | prosodyctl passwd azurediamond@example.com")
|
||||
|
||||
client.succeed("send-message")
|
||||
|
||||
server.succeed("prosodyctl deluser cthon98@example.com")
|
||||
server.succeed("prosodyctl deluser azurediamond@example.com")
|
||||
server.succeed("create-prosody-users")
|
||||
client.succeed('send-message 2>&1 | grep "XMPP SCRIPT TEST SUCCESS"')
|
||||
server.succeed("delete-prosody-users")
|
||||
'';
|
||||
}
|
||||
|
|
|
@ -1,46 +1,61 @@
|
|||
{ writeScriptBin, python3, connectTo ? "localhost" }:
|
||||
writeScriptBin "send-message" ''
|
||||
#!${(python3.withPackages (ps: [ ps.sleekxmpp ])).interpreter}
|
||||
# Based on the sleekxmpp send_client example, look there for more details:
|
||||
# https://github.com/fritzy/SleekXMPP/blob/develop/examples/send_client.py
|
||||
import sleekxmpp
|
||||
{ writeScriptBin, writeText, python3, connectTo ? "localhost" }:
|
||||
let
|
||||
dummyFile = writeText "dummy-file" ''
|
||||
Dear dog,
|
||||
|
||||
class SendMsgBot(sleekxmpp.ClientXMPP):
|
||||
"""
|
||||
A basic SleekXMPP bot that will log in, send a message,
|
||||
and then log out.
|
||||
"""
|
||||
def __init__(self, jid, password, recipient, message):
|
||||
sleekxmpp.ClientXMPP.__init__(self, jid, password)
|
||||
Please find this *really* important attachment.
|
||||
|
||||
self.recipient = recipient
|
||||
self.msg = message
|
||||
Yours truly,
|
||||
John
|
||||
'';
|
||||
in writeScriptBin "send-message" ''
|
||||
#!${(python3.withPackages (ps: [ ps.slixmpp ])).interpreter}
|
||||
import logging
|
||||
import sys
|
||||
from types import MethodType
|
||||
|
||||
self.add_event_handler("session_start", self.start, threaded=True)
|
||||
|
||||
def start(self, event):
|
||||
self.send_presence()
|
||||
self.get_roster()
|
||||
|
||||
self.send_message(mto=self.recipient,
|
||||
mbody=self.msg,
|
||||
mtype='chat')
|
||||
|
||||
self.disconnect(wait=True)
|
||||
from slixmpp import ClientXMPP
|
||||
from slixmpp.exceptions import IqError, IqTimeout
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
xmpp = SendMsgBot("cthon98@example.com", "nothunter2", "azurediamond@example.com", "hey, if you type in your pw, it will show as stars")
|
||||
xmpp.register_plugin('xep_0030') # Service Discovery
|
||||
xmpp.register_plugin('xep_0199') # XMPP Ping
|
||||
class CthonTest(ClientXMPP):
|
||||
|
||||
# TODO: verify certificate
|
||||
# If you want to verify the SSL certificates offered by a server:
|
||||
# xmpp.ca_certs = "path/to/ca/cert"
|
||||
def __init__(self, jid, password):
|
||||
ClientXMPP.__init__(self, jid, password)
|
||||
self.add_event_handler("session_start", self.session_start)
|
||||
|
||||
if xmpp.connect(('${connectTo}', 5222)):
|
||||
xmpp.process(block=True)
|
||||
else:
|
||||
print("Unable to connect.")
|
||||
sys.exit(1)
|
||||
async def session_start(self, event):
|
||||
log = logging.getLogger(__name__)
|
||||
self.send_presence()
|
||||
self.get_roster()
|
||||
# Sending a test message
|
||||
self.send_message(mto="azurediamond@example.com", mbody="Hello, this is dog.", mtype="chat")
|
||||
log.info('Message sent')
|
||||
|
||||
# Test http upload (XEP_0363)
|
||||
def timeout_callback(arg):
|
||||
log.error("ERROR: Cannot upload file. XEP_0363 seems broken")
|
||||
sys.exit(1)
|
||||
url = await self['xep_0363'].upload_file("${dummyFile}",timeout=10, timeout_callback=timeout_callback)
|
||||
log.info('Upload success!')
|
||||
# Test MUC
|
||||
self.plugin['xep_0045'].join_muc('testMucRoom', 'cthon98', wait=True)
|
||||
log.info('MUC join success!')
|
||||
log.info('XMPP SCRIPT TEST SUCCESS')
|
||||
self.disconnect(wait=True)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
logging.basicConfig(level=logging.DEBUG,
|
||||
format='%(levelname)-8s %(message)s')
|
||||
|
||||
ct = CthonTest('cthon98@example.com', 'nothunter2')
|
||||
ct.register_plugin('xep_0071')
|
||||
ct.register_plugin('xep_0128')
|
||||
# HTTP Upload
|
||||
ct.register_plugin('xep_0363')
|
||||
# MUC
|
||||
ct.register_plugin('xep_0045')
|
||||
ct.connect(("server", 5222))
|
||||
ct.process(forever=False)
|
||||
''
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
{ stdenv, fetchurl, libidn, openssl, makeWrapper, fetchhg
|
||||
{ stdenv, fetchurl, lib, libidn, openssl, makeWrapper, fetchhg
|
||||
, lua5, luasocket, luasec, luaexpat, luafilesystem, luabitop
|
||||
, withLibevent ? true, luaevent ? null
|
||||
, withDBI ? true, luadbi ? null
|
||||
|
@ -16,7 +16,16 @@ with stdenv.lib;
|
|||
stdenv.mkDerivation rec {
|
||||
version = "0.11.5"; # also update communityModules
|
||||
pname = "prosody";
|
||||
|
||||
# The following community modules are necessary for the nixos module
|
||||
# prosody module to comply with XEP-0423 and provide a working
|
||||
# default setup.
|
||||
nixosModuleDeps = [
|
||||
"bookmarks"
|
||||
"cloud_notify"
|
||||
"vcard_muc"
|
||||
"smacks"
|
||||
"http_upload"
|
||||
];
|
||||
src = fetchurl {
|
||||
url = "https://prosody.im/downloads/source/${pname}-${version}.tar.gz";
|
||||
sha256 = "12s0hn6hvjbi61cdw3165l6iw0878971dmlvfg663byjsmjvvy2m";
|
||||
|
@ -52,7 +61,7 @@ stdenv.mkDerivation rec {
|
|||
postInstall = ''
|
||||
${concatMapStringsSep "\n" (module: ''
|
||||
cp -r $communityModules/mod_${module} $out/lib/prosody/modules/
|
||||
'') (withCommunityModules ++ withOnlyInstalledCommunityModules)}
|
||||
'') (lib.lists.unique(nixosModuleDeps ++ withCommunityModules ++ withOnlyInstalledCommunityModules))}
|
||||
wrapProgram $out/bin/prosody \
|
||||
--prefix LUA_PATH ';' "$LUA_PATH" \
|
||||
--prefix LUA_CPATH ';' "$LUA_CPATH"
|
||||
|
|
Loading…
Reference in a new issue