aboutsummaryrefslogtreecommitdiff
path: root/virtual/modules
diff options
context:
space:
mode:
authorIsmaël Bouya <ismael.bouya@normalesup.org>2019-01-12 12:41:23 +0100
committerIsmaël Bouya <ismael.bouya@normalesup.org>2019-01-12 21:59:41 +0100
commit108891744eaa7410e305871212d5b81c1b67a095 (patch)
tree90e3f1a87573532ed1c14e233ad7348904ce47f8 /virtual/modules
parent950ca5ee979ae2467f3471216140de2c1d572f4b (diff)
downloadNix-108891744eaa7410e305871212d5b81c1b67a095.tar.gz
Nix-108891744eaa7410e305871212d5b81c1b67a095.tar.zst
Nix-108891744eaa7410e305871212d5b81c1b67a095.zip
Refactor websites.
This commit refactors websites into module per "vhost".
Diffstat (limited to 'virtual/modules')
-rw-r--r--virtual/modules/databases/default.nix (renamed from virtual/modules/databases.nix)0
-rw-r--r--virtual/modules/databases/postgresql_run_socket_path.patch (renamed from virtual/modules/postgresql_run_socket_path.patch)0
-rw-r--r--virtual/modules/gitolite/default.nix (renamed from virtual/modules/gitolite.nix)4
-rw-r--r--virtual/modules/gitweb/default.nix30
-rw-r--r--virtual/modules/websites/commons/adminer.nix64
-rw-r--r--virtual/modules/websites/default.nix93
-rw-r--r--virtual/modules/websites/tools/cloud/default.nix45
-rw-r--r--virtual/modules/websites/tools/cloud/nextcloud-config/mimetypealiases.json4
-rw-r--r--virtual/modules/websites/tools/cloud/nextcloud-config/mimetypemapping.json4
-rw-r--r--virtual/modules/websites/tools/cloud/nextcloud.nix267
-rw-r--r--virtual/modules/websites/tools/dav/davical.nix164
-rw-r--r--virtual/modules/websites/tools/dav/davical_19eb79ebf9250e5f339675319902458c40ed1755.patch26
-rw-r--r--virtual/modules/websites/tools/dav/default.nix33
-rw-r--r--virtual/modules/websites/tools/dav/infcloud.nix38
-rw-r--r--virtual/modules/websites/tools/dav/infcloud_config.js1446
-rw-r--r--virtual/modules/websites/tools/db/default.nix23
-rw-r--r--virtual/modules/websites/tools/git/default.nix46
-rw-r--r--virtual/modules/websites/tools/git/gitweb/gitweb.nix (renamed from virtual/modules/gitweb/gitweb.nix)0
-rw-r--r--virtual/modules/websites/tools/git/gitweb/theme/git-favicon.png (renamed from virtual/modules/gitweb/theme/git-favicon.png)bin1125 -> 1125 bytes
-rw-r--r--virtual/modules/websites/tools/git/gitweb/theme/git-logo.png (renamed from virtual/modules/gitweb/theme/git-logo.png)bin2412 -> 2412 bytes
-rw-r--r--virtual/modules/websites/tools/git/gitweb/theme/gitweb.css (renamed from virtual/modules/gitweb/theme/gitweb.css)0
-rw-r--r--virtual/modules/websites/tools/git/gitweb/theme/gitweb.js (renamed from virtual/modules/gitweb/theme/gitweb.js)0
-rw-r--r--virtual/modules/websites/tools/git/mantisbt/mantisbt-plugin-slack.json15
-rw-r--r--virtual/modules/websites/tools/git/mantisbt/mantisbt-plugin-source-integration.json15
-rw-r--r--virtual/modules/websites/tools/git/mantisbt/mantisbt-plugin-source-integration_Source.API.php.diff12
-rw-r--r--virtual/modules/websites/tools/git/mantisbt/mantisbt.nix124
-rw-r--r--virtual/modules/websites/tools/git/mantisbt/patches/bug_report.php.diff20
-rw-r--r--virtual/modules/websites/tools/git/mantisbt/patches/bug_report_page.php.diff53
-rw-r--r--virtual/modules/websites/tools/git/mantisbt/patches/bugnote_add.php.diff20
-rw-r--r--virtual/modules/websites/tools/git/mantisbt/patches/bugnote_add_inc.php.diff52
-rw-r--r--virtual/modules/websites/tools/tools/default.nix65
-rw-r--r--virtual/modules/websites/tools/tools/roundcubemail.nix110
-rw-r--r--virtual/modules/websites/tools/tools/tt-rss.json14
-rw-r--r--virtual/modules/websites/tools/tools/ttrss-af-feedmod_type_replace.patch12
-rw-r--r--virtual/modules/websites/tools/tools/ttrss-af_feedmod.json15
-rw-r--r--virtual/modules/websites/tools/tools/ttrss-auth-ldap.json15
-rw-r--r--virtual/modules/websites/tools/tools/ttrss-feediron.json15
-rw-r--r--virtual/modules/websites/tools/tools/ttrss-feediron_json_reformat.patch18
-rw-r--r--virtual/modules/websites/tools/tools/ttrss-ff_instagram.json15
-rw-r--r--virtual/modules/websites/tools/tools/ttrss-tumblr_gdpr_ua.json15
-rw-r--r--virtual/modules/websites/tools/tools/ttrss.nix182
-rw-r--r--virtual/modules/websites/tools/tools/ympd.nix35
42 files changed, 3021 insertions, 88 deletions
diff --git a/virtual/modules/databases.nix b/virtual/modules/databases/default.nix
index de4ace6..de4ace6 100644
--- a/virtual/modules/databases.nix
+++ b/virtual/modules/databases/default.nix
diff --git a/virtual/modules/postgresql_run_socket_path.patch b/virtual/modules/databases/postgresql_run_socket_path.patch
index b558c7b..b558c7b 100644
--- a/virtual/modules/postgresql_run_socket_path.patch
+++ b/virtual/modules/databases/postgresql_run_socket_path.patch
diff --git a/virtual/modules/gitolite.nix b/virtual/modules/gitolite/default.nix
index d6b9c79..78691fa 100644
--- a/virtual/modules/gitolite.nix
+++ b/virtual/modules/gitolite/default.nix
@@ -24,6 +24,8 @@ in {
24 }); 24 });
25 }; 25 };
26 26
27 networking.firewall.allowedTCPPorts = [ 9418 ];
28
27 services.gitDaemon = { 29 services.gitDaemon = {
28 enable = true; 30 enable = true;
29 user = "gitolite"; 31 user = "gitolite";
@@ -36,7 +38,7 @@ in {
36 let 38 let
37 gitolite_ldap_groups = mylibs.wrap { 39 gitolite_ldap_groups = mylibs.wrap {
38 name = "gitolite_ldap_groups.sh"; 40 name = "gitolite_ldap_groups.sh";
39 file = ./gitolite/gitolite_ldap_groups.sh; 41 file = ./gitolite_ldap_groups.sh;
40 vars = { 42 vars = {
41 LDAP_PASS = builtins.getEnv "NIXOPS_GITOLITE_LDAP_PASSWORD"; 43 LDAP_PASS = builtins.getEnv "NIXOPS_GITOLITE_LDAP_PASSWORD";
42 }; 44 };
diff --git a/virtual/modules/gitweb/default.nix b/virtual/modules/gitweb/default.nix
deleted file mode 100644
index 2a860ba..0000000
--- a/virtual/modules/gitweb/default.nix
+++ /dev/null
@@ -1,30 +0,0 @@
1{ lib, pkgs, config, mylibs, ... }:
2let
3 # FIXME: add buildbot
4 gitweb = pkgs.callPackage ./gitweb.nix { gitoliteDir = config.services.myGitolite.gitoliteDir; };
5 cfg = config.services.myGitweb;
6in {
7 options.services.myGitweb = {
8 enable = lib.mkEnableOption "my gitweb service";
9 };
10
11 config = lib.mkIf cfg.enable {
12 security.acme.certs."eldiron".extraDomains."git.immae.eu" = null;
13
14 nixpkgs.config.packageOverrides = oldpkgs: rec {
15 gitweb = oldpkgs.gitweb.overrideAttrs(old: {
16 installPhase = old.installPhase + ''
17 cp -r ${./theme} $out/gitweb-theme;
18 '';
19 });
20 };
21
22 services.myWebsites.tools.modules = gitweb.apache.modules;
23 services.myWebsites.tools.vhostConfs.git = {
24 certName = "eldiron";
25 hosts = ["git.immae.eu" ];
26 root = gitweb.webRoot;
27 extraConfig = [ gitweb.apache.vhostConf ];
28 };
29 };
30}
diff --git a/virtual/modules/websites/commons/adminer.nix b/virtual/modules/websites/commons/adminer.nix
new file mode 100644
index 0000000..7094e45
--- /dev/null
+++ b/virtual/modules/websites/commons/adminer.nix
@@ -0,0 +1,64 @@
1{ stdenv, fetchurl, nginx }:
2let
3 adminer = rec {
4 webRoot = stdenv.mkDerivation rec {
5 version = "4.7.0";
6 name = "adminer-${version}";
7 src = fetchurl {
8 url = "https://www.adminer.org/static/download/${version}/${name}.php";
9 sha256 = "1qq2g7rbfh2vrqfm3g0bz0qs057b049n0mhabnsbd1sgnpvnc5z7";
10 };
11 phases = "installPhase";
12 installPhase = ''
13 mkdir -p $out
14 cp $src $out/index.php
15 '';
16 };
17 phpFpm = rec {
18 socket = "/var/run/phpfpm/adminer.sock";
19 pool = ''
20 listen = ${socket}
21 user = ${apache.user}
22 group = ${apache.group}
23 listen.owner = ${apache.user}
24 listen.group = ${apache.group}
25 pm = ondemand
26 pm.max_children = 5
27 pm.process_idle_timeout = 60
28 ;php_admin_flag[log_errors] = on
29 ; Needed to avoid clashes in browser cookies (same domain)
30 php_value[session.name] = AdminerPHPSESSID
31 php_admin_value[open_basedir] = "${webRoot}:/tmp"
32 php_admin_value[session.save_path] = "/var/lib/php/sessions/adminer"
33 '';
34 };
35 apache = {
36 user = "wwwrun";
37 group = "wwwrun";
38 modules = [ "proxy_fcgi" ];
39 vhostConf = ''
40 Alias /adminer ${webRoot}
41 <Directory ${webRoot}>
42 DirectoryIndex index.php
43 <FilesMatch "\.php$">
44 SetHandler "proxy:unix:${phpFpm.socket}|fcgi://localhost"
45 </FilesMatch>
46 </Directory>
47 '';
48 };
49 nginxConf = {
50 alias = webRoot;
51 index = "index.php";
52 extraConfig = ''
53 include ${nginx}/conf/fastcgi.conf;
54 fastcgi_split_path_info ^(.+?\.php)(/.*)$;
55 fastcgi_param HTTP_PROXY "";
56 fastcgi_param SCRIPT_FILENAME ${webRoot}/index.php;
57 fastcgi_pass unix:${phpFpm.socket};
58 fastcgi_index index.php;
59 fastcgi_intercept_errors on;
60 '';
61 };
62 };
63in
64 adminer
diff --git a/virtual/modules/websites/default.nix b/virtual/modules/websites/default.nix
index b027b81..6b31381 100644
--- a/virtual/modules/websites/default.nix
+++ b/virtual/modules/websites/default.nix
@@ -91,11 +91,18 @@ in
91 ./aten 91 ./aten
92 ./piedsjaloux 92 ./piedsjaloux
93 ./connexionswing 93 ./connexionswing
94 ./tools/db
95 ./tools/tools
96 ./tools/dav
97 ./tools/cloud
98 ./tools/git
94 # built using: 99 # built using:
95 # sed -e "s/services\.httpd/services\.httpdProd/g" .nix-defexpr/channels/nixpkgs/nixos/modules/services/web-servers/apache-httpd/default.nix 100 # sed -e "s/services\.httpd/services\.httpdProd/g" .nix-defexpr/channels/nixpkgs/nixos/modules/services/web-servers/apache-httpd/default.nix
96 # And removed users / groups 101 # And removed users / groups
97 ./apache/httpd_prod.nix 102 ./apache/httpd_prod.nix
98 ./apache/httpd_inte.nix 103 ./apache/httpd_inte.nix
104 # Adapted from base phpfpm
105 ./phpfpm
99 ]; 106 ];
100 107
101 options.services.myWebsites = { 108 options.services.myWebsites = {
@@ -155,6 +162,12 @@ in
155 phpPackages = oldpkgs.php72Packages.override { inherit php; }; 162 phpPackages = oldpkgs.php72Packages.override { inherit php; };
156 }; 163 };
157 164
165 services.myWebsites.tools.databases.enable = true;
166 services.myWebsites.tools.tools.enable = true;
167 services.myWebsites.tools.dav.enable = true;
168 services.myWebsites.tools.cloud.enable = true;
169 services.myWebsites.tools.git.enable = true;
170
158 services.myWebsites.Chloe.production.enable = cfg.production.enable; 171 services.myWebsites.Chloe.production.enable = cfg.production.enable;
159 services.myWebsites.Ludivine.production.enable = cfg.production.enable; 172 services.myWebsites.Ludivine.production.enable = cfg.production.enable;
160 services.myWebsites.Aten.production.enable = cfg.production.enable; 173 services.myWebsites.Aten.production.enable = cfg.production.enable;
@@ -227,6 +240,28 @@ in
227 }; 240 };
228 }; 241 };
229 242
243 system.activationScripts = {
244 httpd = ''
245 install -d -m 0755 /var/lib/acme/acme-challenge
246 install -d -m 0750 -o wwwrun -g wwwrun /var/lib/php/sessions
247 install -d -m 0750 -o wwwrun -g wwwrun /var/lib/php/sessions/adminer
248 install -d -m 0750 -o wwwrun -g wwwrun /var/lib/php/sessions/mantisbt
249 install -d -m 0750 -o wwwrun -g wwwrun /var/lib/php/sessions/davical
250 '';
251 };
252
253 services.myPhpfpm = {
254 phpPackage = pkgs.php;
255 phpOptions = ''
256 session.save_path = "/var/lib/php/sessions"
257 session.gc_maxlifetime = 60*60*24*15
258 session.cache_expire = 60*24*30
259 '';
260 extraConfig = ''
261 log_level = notice
262 '';
263 };
264
230 # FIXME: logrotate 265 # FIXME: logrotate
231 # FIXME: ipv6 266 # FIXME: ipv6
232 services.httpdProd = makeService "production" config.services.myWebsites.production; 267 services.httpdProd = makeService "production" config.services.myWebsites.production;
@@ -238,63 +273,7 @@ in
238 services.myWebsites.integration.extraConfig = (builtins.filter (x: x != null) (pkgs.lib.attrsets.mapAttrsToList (n: v: v.extraConfig or null) cfg.apacheConfig)); 273 services.myWebsites.integration.extraConfig = (builtins.filter (x: x != null) (pkgs.lib.attrsets.mapAttrsToList (n: v: v.extraConfig or null) cfg.apacheConfig));
239 274
240 services.httpd = makeService "tools" config.services.myWebsites.tools; 275 services.httpd = makeService "tools" config.services.myWebsites.tools;
241 services.myWebsites.tools.modules = 276 services.myWebsites.tools.modules = pkgs.lib.lists.flatten (pkgs.lib.attrsets.mapAttrsToList (n: v: v.modules or []) cfg.apacheConfig);
242 mypkgs.adminer.apache.modules ++
243 mypkgs.nextcloud.apache.modules ++
244 mypkgs.ympd.apache.modules ++
245 mypkgs.mantisbt.apache.modules ++
246 mypkgs.ttrss.apache.modules ++
247 mypkgs.roundcubemail.apache.modules ++
248 pkgs.lib.lists.flatten (pkgs.lib.attrsets.mapAttrsToList (n: v: v.modules or []) cfg.apacheConfig);
249 services.myWebsites.tools.extraConfig = (builtins.filter (x: x != null) (pkgs.lib.attrsets.mapAttrsToList (n: v: v.extraConfig or null) cfg.apacheConfig)); 277 services.myWebsites.tools.extraConfig = (builtins.filter (x: x != null) (pkgs.lib.attrsets.mapAttrsToList (n: v: v.extraConfig or null) cfg.apacheConfig));
250 # FIXME: move them all to separate modules
251 services.myWebsites.tools.vhostConfs.eldiron = {
252 certName = "eldiron";
253 hosts = ["eldiron.immae.eu" ];
254 root = ../../www;
255 extraConfig = [ "DirectoryIndex index.htm" ];
256 };
257 services.myWebsites.tools.vhostConfs.db-1 = {
258 certName = "eldiron";
259 hosts = ["db-1.immae.eu" ];
260 root = null;
261 extraConfig = [ mypkgs.adminer.apache.vhostConf ];
262 };
263 services.myWebsites.tools.vhostConfs.tools = {
264 certName = "eldiron";
265 hosts = ["tools.immae.eu" ];
266 root = null;
267 extraConfig = [
268 mypkgs.adminer.apache.vhostConf
269 mypkgs.ympd.apache.vhostConf
270 mypkgs.ttrss.apache.vhostConf
271 mypkgs.roundcubemail.apache.vhostConf
272 ];
273 };
274 services.myWebsites.tools.vhostConfs.dav = {
275 certName = "eldiron";
276 hosts = ["dav.immae.eu" ];
277 root = null;
278 extraConfig = [
279 mypkgs.infcloud.apache.vhostConf
280 mypkgs.davical.apache.vhostConf
281 ];
282 };
283 services.myWebsites.tools.vhostConfs.cloud = {
284 certName = "eldiron";
285 hosts = ["cloud.immae.eu" ];
286 root = mypkgs.nextcloud.webRoot;
287 extraConfig = [
288 mypkgs.nextcloud.apache.vhostConf
289 ];
290 };
291 services.myWebsites.tools.vhostConfs.git.extraConfig = [
292 mypkgs.mantisbt.apache.vhostConf
293 ''
294 RewriteEngine on
295 RewriteCond %{REQUEST_URI} ^/releases
296 RewriteRule /releases(.*) https://release.immae.eu$1 [P,L]
297 ''
298 ];
299 }; 278 };
300} 279}
diff --git a/virtual/modules/websites/tools/cloud/default.nix b/virtual/modules/websites/tools/cloud/default.nix
new file mode 100644
index 0000000..7dd5c6e
--- /dev/null
+++ b/virtual/modules/websites/tools/cloud/default.nix
@@ -0,0 +1,45 @@
1{ lib, pkgs, config, mylibs, ... }:
2let
3 nextcloud = pkgs.callPackage ./nextcloud.nix { inherit (mylibs) checkEnv; };
4
5 cfg = config.services.myWebsites.tools.cloud;
6in {
7 options.services.myWebsites.tools.cloud = {
8 enable = lib.mkEnableOption "enable cloud website";
9 };
10
11 config = lib.mkIf cfg.enable {
12 security.acme.certs."eldiron".extraDomains."cloud.immae.eu" = null;
13
14 services.myWebsites.tools.modules = nextcloud.apache.modules;
15
16 services.myWebsites.tools.vhostConfs.cloud = {
17 certName = "eldiron";
18 hosts = ["cloud.immae.eu" ];
19 root = nextcloud.webRoot;
20 extraConfig = [
21 nextcloud.apache.vhostConf
22 ];
23 };
24
25 environment.systemPackages = let
26 occ = pkgs.writeScriptBin "nextcloud-occ" ''
27 #! ${pkgs.stdenv.shell}
28 cd ${nextcloud.webRoot}
29 NEXTCLOUD_CONFIG_DIR="${nextcloud.webRoot}/config" \
30 exec \
31 ${pkgs.php}/bin/php \
32 -c ${pkgs.php}/etc/php.ini \
33 occ $*
34 '';
35 in [ occ ];
36
37 system.activationScripts.nextcloud = nextcloud.activationScript;
38
39 services.myPhpfpm = {
40 poolPhpConfigs.nextcloud = nextcloud.phpFpm.phpConfig;
41 poolConfigs.nextcloud = nextcloud.phpFpm.pool;
42 };
43
44 };
45}
diff --git a/virtual/modules/websites/tools/cloud/nextcloud-config/mimetypealiases.json b/virtual/modules/websites/tools/cloud/nextcloud-config/mimetypealiases.json
new file mode 100644
index 0000000..3806e53
--- /dev/null
+++ b/virtual/modules/websites/tools/cloud/nextcloud-config/mimetypealiases.json
@@ -0,0 +1,4 @@
1{
2 "application/gpx+xml": "gpx",
3 "x-application/kdbx": "kdbx"
4}
diff --git a/virtual/modules/websites/tools/cloud/nextcloud-config/mimetypemapping.json b/virtual/modules/websites/tools/cloud/nextcloud-config/mimetypemapping.json
new file mode 100644
index 0000000..2db4691
--- /dev/null
+++ b/virtual/modules/websites/tools/cloud/nextcloud-config/mimetypemapping.json
@@ -0,0 +1,4 @@
1{
2 "gpx": ["application/gpx+xml"],
3 "kdbx": ["x-application/kdbx"]
4}
diff --git a/virtual/modules/websites/tools/cloud/nextcloud.nix b/virtual/modules/websites/tools/cloud/nextcloud.nix
new file mode 100644
index 0000000..b8d8e59
--- /dev/null
+++ b/virtual/modules/websites/tools/cloud/nextcloud.nix
@@ -0,0 +1,267 @@
1{ stdenv, fetchurl, checkEnv, writeText, lib, phpPackages, php }:
2let
3 nextcloud = let
4 # FIXME: initial sync
5 # FIXME: backup
6 buildApp = { appName, version, url, sha256, installPhase ? "mkdir -p $out && cp -R . $out/" }:
7 stdenv.mkDerivation rec {
8 name = "nextcloud-app-${appName}-${version}";
9 inherit version;
10 phases = "unpackPhase installPhase";
11 inherit installPhase;
12 src = fetchurl { inherit url sha256; };
13 };
14 apps = {
15 # FIXME: nextcloud complains that he cannot write into config
16 # directory when an app needs upgrade
17 # /!\ Attention, just changing the version number is not
18 # sufficient when the downloaded file doesn’t contain the version
19 # number in it, sha256 needs to be recomputed
20 audioplayer = buildApp rec {
21 appName = "audioplayer";
22 version = "2.5.0";
23 url = "https://github.com/Rello/${appName}/releases/download/${version}/${appName}-${version}.tar.gz";
24 sha256 = "1pg4y51cv3agy28n4gfc8i7x1ya1yijxrmhpblm1n846vhmwdcm8";
25 };
26 bookmarks = buildApp rec {
27 appName = "bookmarks";
28 version = "0.14.3";
29 url = "https://github.com/nextcloud/${appName}/releases/download/v${version}/${appName}-${version}.tar.gz";
30 sha256 = "0s7lkcl70izlkihnml1par0cac0wvckllyyga3jkb7k9vdg7d40c";
31 };
32 calendar = buildApp rec {
33 appName = "calendar";
34 version = "1.6.4";
35 url = "https://github.com/nextcloud/${appName}/releases/download/v${version}/${appName}.tar.gz";
36 sha256 = "00dijvcvy7snsjslfbyzvpp9anhms22zp1f0zkj89ln33jmana63";
37 };
38 contacts = buildApp rec {
39 appName = "contacts";
40 version = "3.0.0";
41 url = "https://github.com/nextcloud/${appName}/releases/download/v${version}/${appName}.tar.gz";
42 sha256 = "0fafy5kgzr5ldr3hxxxgmnw4y3qpjnv5ha1f1dlmqbc65s8frw7s";
43 };
44 deck = buildApp rec {
45 appName = "deck";
46 version = "0.5.2";
47 url = "https://github.com/nextcloud/${appName}/releases/download/v${version}/${appName}.tar.gz";
48 sha256 = "1kygzixxdkp3dbma009p3pw0fj8wgcqcv39n7pay78lh6zi3nic7";
49 };
50 files_markdown = buildApp rec {
51 appName = "files_markdown";
52 version = "2.0.5";
53 url = "https://github.com/icewind1991/${appName}/releases/download/v${version}/${appName}.tar.gz";
54 sha256 = "1dzvy4c6vff2qmkwqw13dx92xdkafaxgnipswjw44mh0ncc2n9ym";
55 };
56 gpxedit = buildApp rec {
57 appName = "gpxedit";
58 version = "0.0.10";
59 url = "https://gitlab.com/eneiluj/gpxedit-oc/wikis/uploads/33d187268c5f6f6a55350d656305701c/${appName}-${version}.tar.gz";
60 sha256 = "0ynpaxm0xhvcj8xax6rm1w0p6j57wbqidhi7bhn268n483gwl2sw";
61 };
62 gpxpod = buildApp rec {
63 appName = "gpxpod";
64 version = "3.0.0";
65 url = "https://gitlab.com/eneiluj/gpxpod-oc/-/archive/v${version}/${appName}-oc-v${version}.tar.gz";
66 sha256 = "0smpi4r3z7zfl1612fb30cwm1xmpiq95c81zzqiwzjf288iys74k";
67 };
68 keeweb = buildApp rec {
69 appName = "keeweb";
70 version = "0.4.0";
71 url = "https://github.com/jhass/nextcloud-keeweb/releases/download/v${version}/${appName}-${version}.tar.gz";
72 sha256 = "0453kkb0a8vfivmibpwpx4bvhyn64jhns6cdfjacmnvbm6d75nj1";
73 };
74 notes = buildApp rec {
75 appName = "notes";
76 version = "2.5.1";
77 url = "https://github.com/nextcloud/${appName}/releases/download/v${version}/${appName}.tar.gz";
78 sha256 = "1albzqqsdirzyw8vhvs7r0qm2wqp8vm9vmxm4crhncd85bk01hmh";
79 };
80 ocsms = buildApp rec {
81 appName = "ocsms";
82 version = "2.1.0";
83 url = "https://github.com/nextcloud/${appName}/releases/download/${version}/${appName}-${version}.tar.gz";
84 sha256 = "19xgs82js4sdf6j9478vg9li7za7csvcaa1hbq9nmrq441sbxk9c";
85 };
86 spreed = buildApp rec {
87 appName = "spreed";
88 version = "5.0.0";
89 url = "https://github.com/nextcloud/${appName}/releases/download/v${version}/${appName}-${version}.tar.gz";
90 sha256 = "1d48mak1fnf1b28r2687yqamm4pxfg3qyxcj9ny31a6xg2cm0xa7";
91 };
92 tasks = buildApp rec {
93 appName = "tasks";
94 version = "0.9.8";
95 url = "https://github.com/nextcloud/${appName}/releases/download/v${version}/${appName}.tar.gz";
96 sha256 = "089m124lfsfk09fqj50x9n7zndq97jp5afgb8s001rpmzym4g6ny";
97 };
98 };
99 in rec {
100 varDir = "/var/lib/nextcloud";
101 config_php =
102 assert checkEnv "NIXOPS_NEXTCLOUD_PASSWORD_SALT";
103 assert checkEnv "NIXOPS_NEXTCLOUD_DB_USER";
104 assert checkEnv "NIXOPS_NEXTCLOUD_DB_PASSWORD";
105 assert checkEnv "NIXOPS_NEXTCLOUD_INSTANCE_ID";
106 assert checkEnv "NIXOPS_NEXTCLOUD_SECRET";
107 assert checkEnv "NIXOPS_NEXTCLOUD_REDIS_DB_INDEX";
108 writeText "config.php" ''
109 <?php
110 $CONFIG = array (
111 'instanceid' => '${builtins.getEnv "NIXOPS_NEXTCLOUD_INSTANCE_ID"}',
112 'datadirectory' => '/var/lib/nextcloud/',
113 'passwordsalt' => '${builtins.getEnv "NIXOPS_NEXTCLOUD_PASSWORD_SALT"}',
114 'debug' => false,
115 'dbtype' => 'pgsql',
116 'version' => '15.0.0.10',
117 'dbname' => 'webapps',
118 'dbhost' => '/run/postgresql',
119 'dbtableprefix' => 'oc_',
120 'dbuser' => '${builtins.getEnv "NIXOPS_NEXTCLOUD_DB_USER"}',
121 'dbpassword' => '${builtins.getEnv "NIXOPS_NEXTCLOUD_DB_PASSWORD"}',
122 'installed' => true,
123 'maxZipInputSize' => 0,
124 'allowZipDownload' => true,
125 'forcessl' => true,
126 'theme' => ${"''"},
127 'maintenance' => false,
128 'trusted_domains' =>
129 array (
130 0 => 'cloud.immae.eu',
131 ),
132 'secret' => '${builtins.getEnv "NIXOPS_NEXTCLOUD_SECRET"}',
133 'appstoreenabled' => false,
134 'appstore.experimental.enabled' => true,
135 'loglevel' => 0,
136 'trashbin_retention_obligation' => 'auto',
137 'htaccess.RewriteBase' => '/',
138 'mail_smtpmode' => 'smtp',
139 'mail_smtphost' => 'mail.immae.eu',
140 'mail_smtpname' => ${"''"},
141 'mail_smtppassword' => ${"''"},
142 'mail_from_address' => 'owncloud',
143 'mail_smtpauth' => false,
144 'mail_domain' => 'immae.eu',
145 'memcache.local' => '\\OC\\Memcache\\APCu',
146 'memcache.locking' => '\\OC\\Memcache\\Redis',
147 'filelocking.enabled' => true,
148 'redis' =>
149 array (
150 'host' => 'localhost',
151 'port' => 6379,
152 'dbindex' => ${builtins.getEnv "NIXOPS_NEXTCLOUD_REDIS_DB_INDEX"},
153 ),
154 'overwrite.cli.url' => 'https://cloud.immae.eu',
155 'ldapIgnoreNamingRules' => false,
156 'ldapProviderFactory' => '\\OCA\\User_LDAP\\LDAPProviderFactory',
157 'config_is_read_only' => true,
158 );
159 '';
160 config = stdenv.mkDerivation rec {
161 name = "nextcloud-config";
162 src = ./nextcloud-config;
163 phases = "installPhase";
164 installPhase = ''
165 mkdir -p $out
166 cp -r $src/* $out
167 cp ${config_php} $out/config.php
168 '';
169 };
170 webRoot = stdenv.mkDerivation rec {
171 name = "nextcloud-${version}";
172 version = "15.0.0";
173
174 src = fetchurl {
175 url = "https://download.nextcloud.com/server/releases/${name}.tar.bz2";
176 sha256 = "0y7bk1588n5rmmranmmrkajh50074460hr4v052ahg9mf60wbc2v";
177 };
178
179 installPhase = ''
180 mkdir -p $out/
181 cp -R . $out/
182 rm -r $out/config
183 ln -sf ${config} $out/config
184 ${builtins.concatStringsSep "\n" (
185 lib.attrsets.mapAttrsToList (name: value: "ln -sf ${value} $out/apps/${name}") apps
186 )}
187 '';
188
189 meta = {
190 description = "Sharing solution for files, calendars, contacts and more";
191 homepage = https://nextcloud.com;
192 maintainers = with lib.maintainers; [ schneefux bachp globin fpletz ];
193 license = lib.licenses.agpl3Plus;
194 platforms = with lib.platforms; unix;
195 };
196 };
197 activationScript = {
198 deps = [ ];
199 text = ''
200 install -m 0755 -o ${apache.user} -g ${apache.group} -d ${varDir}
201 install -m 0750 -o ${apache.user} -g ${apache.group} -d ${varDir}/phpSessions
202 '';
203 };
204 apache = {
205 user = "wwwrun";
206 group = "wwwrun";
207 modules = [ "proxy_fcgi" ];
208 vhostConf = ''
209 SetEnvIf Authorization "(.*)" HTTP_AUTHORIZATION=$1
210 <Directory ${webRoot}>
211 AcceptPathInfo On
212 DirectoryIndex index.php
213 Options FollowSymlinks
214 Require all granted
215 AllowOverride all
216
217 <IfModule mod_headers.c>
218 Header always set Strict-Transport-Security "max-age=15552000; includeSubDomains; preload"
219 </IfModule>
220 <FilesMatch "\.php$">
221 CGIPassAuth on
222 SetHandler "proxy:unix:${phpFpm.socket}|fcgi://localhost"
223 </FilesMatch>
224
225 </Directory>
226
227 '';
228 };
229 phpFpm = rec {
230 basedir = builtins.concatStringsSep ":" (
231 [ webRoot varDir config ]
232 ++ lib.attrsets.mapAttrsToList (name: value: value) apps);
233 socket = "/var/run/phpfpm/nextcloud.sock";
234 phpConfig = ''
235 extension=${phpPackages.redis}/lib/php/extensions/redis.so
236 extension=${phpPackages.apcu}/lib/php/extensions/apcu.so
237 zend_extension=${php}/lib/php/extensions/opcache.so
238 '';
239 pool = ''
240 listen = ${socket}
241 user = ${apache.user}
242 group = ${apache.group}
243 listen.owner = ${apache.user}
244 listen.group = ${apache.group}
245 pm = ondemand
246 pm.max_children = 60
247 pm.process_idle_timeout = 60
248
249 php_admin_value[output_buffering] = 0
250 php_admin_value[max_execution_time] = 1800
251 php_admin_value[zend_extension] = "opcache"
252 php_value[opcache.enable] = 1
253 php_value[opcache.enable_cli] = 1
254 php_value[opcache.interned_strings_buffer] = 8
255 php_value[opcache.max_accelerated_files] = 10000
256 php_value[opcache.memory_consumption] = 128
257 php_value[opcache.save_comments] = 1
258 php_value[opcache.revalidate_freq] = 1
259 php_admin_value[memory_limit] = 512M
260
261 php_admin_value[open_basedir] = "${basedir}:/proc/meminfo:/dev/urandom:/proc/self/fd:/tmp"
262 php_admin_value[session.save_path] = "${varDir}/phpSessions"
263 '';
264 };
265 };
266in
267 nextcloud
diff --git a/virtual/modules/websites/tools/dav/davical.nix b/virtual/modules/websites/tools/dav/davical.nix
new file mode 100644
index 0000000..697bd60
--- /dev/null
+++ b/virtual/modules/websites/tools/dav/davical.nix
@@ -0,0 +1,164 @@
1{ stdenv, fetchurl, gettext, writeText, checkEnv }:
2let
3 awl = stdenv.mkDerivation rec {
4 version = "0.59";
5 name = "awl-${version}";
6 src = fetchurl {
7 url = "https://www.davical.org/downloads/awl_${version}.orig.tar.xz";
8 sha256 = "01b7km7ga3ggbpp8axkc55nizgk5c35fl2z93iydb3hwbxmsvnjp";
9 };
10 unpackCmd = ''
11 tar --one-top-level -xf $curSrc
12 '';
13 installPhase = ''
14 mkdir -p $out
15 cp -ra dba docs inc scripts tests $out
16 '';
17 };
18 # FIXME: e-mail sending
19 davical = rec {
20 config =
21 assert checkEnv "NIXOPS_DAVICAL_DB_PASSWORD";
22 assert checkEnv "NIXOPS_DAVICAL_LDAP_PASSWORD";
23 writeText "davical_config.php" ''
24 <?php
25 $c->pg_connect[] = "dbname=davical user=davical_app host=db-1.immae.eu password=${builtins.getEnv "NIXOPS_DAVICAL_DB_PASSWORD"}";
26
27 $c->readonly_webdav_collections = false;
28
29 $c->admin_email ='davical@immae.eu';
30
31 $c->restrict_setup_to_admin = true;
32
33 $c->collections_always_exist = false;
34
35 $c->external_refresh = 60;
36
37 $c->enable_scheduling = true;
38
39 $c->iMIP = (object) array("send_email" => true);
40
41 $c->authenticate_hook['optional'] = false;
42 $c->authenticate_hook['call'] = 'LDAP_check';
43 $c->authenticate_hook['config'] = array(
44 'host' => 'ldap.immae.eu',
45 'port' => '389',
46 'startTLS' => 'yes',
47 'bindDN'=> 'cn=davical,ou=services,dc=immae,dc=eu',
48 'passDN'=> '${builtins.getEnv "NIXOPS_DAVICAL_LDAP_PASSWORD"}',
49 'protocolVersion' => '3',
50 'baseDNUsers'=> array('ou=users,dc=immae,dc=eu', 'ou=group_users,dc=immae,dc=eu'),
51 'filterUsers' => 'memberOf=cn=users,cn=davical,ou=services,dc=immae,dc=eu',
52 'baseDNGroups' => 'ou=groups,dc=immae,dc=eu',
53 'filterGroups' => 'memberOf=cn=groups,cn=davical,ou=services,dc=immae,dc=eu',
54 'mapping_field' => array(
55 "username" => "uid",
56 "fullname" => "cn",
57 "email" => "mail",
58 "modified" => "modifyTimestamp",
59 ),
60 'format_updated'=> array('Y' => array(0,4),'m' => array(4,2),'d'=> array(6,2),'H' => array(8,2),'M'=>array(10,2),'S' => array(12,2)),
61 /** used to set default value for all users, will be overcharged by ldap if defined also in mapping_field **/
62 // 'default_value' => array("date_format_type" => "E","locale" => "fr_FR"),
63 'group_mapping_field' => array(
64 "username" => "cn",
65 "updated" => "modifyTimestamp",
66 "fullname" => "givenName",
67 "displayname" => "givenName",
68 "members" => "memberUid",
69 "email" => "mail",
70 ),
71 );
72
73 $c->do_not_sync_from_ldap = array('admin' => true);
74 include('drivers_ldap.php');
75 '';
76 webapp = stdenv.mkDerivation rec {
77 version = "1.1.7";
78 name = "davical-${version}";
79 src = fetchurl {
80 url = "https://www.davical.org/downloads/davical_${version}.orig.tar.xz";
81 sha256 = "1ar5m2dxr92b204wkdi8z33ir9vz2jbh5k1p74icpv9ywifvjjp9";
82 };
83 unpackCmd = ''
84 tar --one-top-level -xf $curSrc
85 '';
86 makeFlags = "all";
87 patches = [ ./davical_19eb79ebf9250e5f339675319902458c40ed1755.patch ];
88 installPhase = ''
89 mkdir -p $out
90 cp -ra config dba docs htdocs inc locale po scripts testing zonedb $out
91 ln -s ${config} $out/config/config.php
92 '';
93 buildInputs = [ gettext ];
94 };
95 webRoot = "${webapp}/htdocs";
96 apache = {
97 user = "wwwrun";
98 group = "wwwrun";
99 modules = [ "proxy_fcgi" ];
100 vhostConf = ''
101 Alias /davical "${webRoot}"
102 Alias /caldav.php "${webRoot}/caldav.php"
103 <Directory "${webRoot}">
104 DirectoryIndex index.php index.html
105 AcceptPathInfo On
106 AllowOverride None
107 Require all granted
108
109 <FilesMatch "\.php$">
110 CGIPassAuth on
111 SetHandler "proxy:unix:${phpFpm.socket}|fcgi://localhost"
112 </FilesMatch>
113
114 RewriteEngine On
115 <IfModule mod_headers.c>
116 Header unset Access-Control-Allow-Origin
117 Header unset Access-Control-Allow-Methods
118 Header unset Access-Control-Allow-Headers
119 Header unset Access-Control-Allow-Credentials
120 Header unset Access-Control-Expose-Headers
121
122 Header always set Access-Control-Allow-Origin "*"
123 Header always set Access-Control-Allow-Methods "GET,POST,OPTIONS,PROPFIND,PROPPATCH,REPORT,PUT,MOVE,DELETE,LOCK,UNLOCK"
124 Header always set Access-Control-Allow-Headers "User-Agent,Authorization,Content-type,Depth,If-match,If-None-Match,Lock-Token,Timeout,Destination,Overwrite,Prefer,X-client,X-Requested-With"
125 Header always set Access-Control-Allow-Credentials false
126 Header always set Access-Control-Expose-Headers "Etag,Preference-Applied"
127
128 RewriteCond %{HTTP:Access-Control-Request-Method} !^$
129 RewriteCond %{REQUEST_METHOD} OPTIONS
130 RewriteRule ^(.*)$ $1 [R=200,L]
131 </IfModule>
132 </Directory>
133 '';
134 };
135 phpFpm = rec {
136 basedir = builtins.concatStringsSep ":" [ webapp config awl ];
137 socket = "/var/run/phpfpm/davical.sock";
138 pool = ''
139 listen = ${socket}
140 user = ${apache.user}
141 group = ${apache.group}
142 listen.owner = ${apache.user}
143 listen.group = ${apache.group}
144 pm = dynamic
145 pm.max_children = 60
146 pm.start_servers = 2
147 pm.min_spare_servers = 1
148 pm.max_spare_servers = 10
149
150 ; Needed to avoid clashes in browser cookies (same domain)
151 php_value[session.name] = DavicalPHPSESSID
152 php_admin_value[open_basedir] = "${basedir}:/tmp"
153 php_admin_value[include_path] = "${awl}/inc:${webapp}/inc"
154 php_admin_value[session.save_path] = "/var/lib/php/sessions/davical"
155 php_flag[magic_quotes_gpc] = Off
156 php_flag[register_globals] = Off
157 php_admin_value[error_reporting] = "E_ALL & ~E_NOTICE"
158 php_admin_value[default_charset] = "utf-8"
159 php_flag[magic_quotes_runtime] = Off
160 '';
161 };
162 };
163in
164 davical
diff --git a/virtual/modules/websites/tools/dav/davical_19eb79ebf9250e5f339675319902458c40ed1755.patch b/virtual/modules/websites/tools/dav/davical_19eb79ebf9250e5f339675319902458c40ed1755.patch
new file mode 100644
index 0000000..2a08a5c
--- /dev/null
+++ b/virtual/modules/websites/tools/dav/davical_19eb79ebf9250e5f339675319902458c40ed1755.patch
@@ -0,0 +1,26 @@
1diff --git a/inc/ui/collection-edit.php b/inc/ui/collection-edit.php
2index 3af9edd3b8c4ad9074113273175098841af6a28e..8c1d84012b035f7bc7faedcb24916581a02a5d3e 100644
3--- a/inc/ui/collection-edit.php
4+++ b/inc/ui/collection-edit.php
5@@ -190,7 +190,7 @@ $privilege_xlate = array(
6 * @param dbrow $row The row object we read from the database.
7 * @return string The formatted privileges.
8 */
9-function collection_privilege_format_function( $value, $column, $row ) {
10+function collection_privilege_format_function( $value, $column = NULL, $row = NULL ) {
11 global $privilege_xlate;
12
13 $privs = bits_to_privilege($value, 'calendar');
14diff --git a/inc/ui/principal-edit.php b/inc/ui/principal-edit.php
15index 20dee7fa4ca2235ff2f74be0dfb52cbe937ef822..2e37cd596b597bcce1e59d7c02a1c5fc2a7f88ce 100644
16--- a/inc/ui/principal-edit.php
17+++ b/inc/ui/principal-edit.php
18@@ -454,7 +454,7 @@ EOTEMPLATE;
19 * @param dbrow $row The row object we read from the database.
20 * @return string The formatted privileges.
21 */
22-function principal_privilege_format_function( $value, $column, $row ) {
23+function principal_privilege_format_function( $value, $column = NULL, $row = NULL ) {
24 global $privilege_xlate;
25
26 $privs = bits_to_privilege($value,'*');
diff --git a/virtual/modules/websites/tools/dav/default.nix b/virtual/modules/websites/tools/dav/default.nix
new file mode 100644
index 0000000..201da38
--- /dev/null
+++ b/virtual/modules/websites/tools/dav/default.nix
@@ -0,0 +1,33 @@
1{ lib, pkgs, config, mylibs, ... }:
2let
3 infcloud = pkgs.callPackage ./infcloud.nix {};
4 davical = pkgs.callPackage ./davical.nix { inherit (mylibs) checkEnv; };
5
6 cfg = config.services.myWebsites.tools.dav;
7in {
8 options.services.myWebsites.tools.dav = {
9 enable = lib.mkEnableOption "enable dav website";
10 };
11
12 config = lib.mkIf cfg.enable {
13 security.acme.certs."eldiron".extraDomains."dav.immae.eu" = null;
14
15 services.myWebsites.tools.modules = davical.apache.modules;
16
17 services.myWebsites.tools.vhostConfs.dav = {
18 certName = "eldiron";
19 hosts = ["dav.immae.eu" ];
20 root = null;
21 extraConfig = [
22 infcloud.apache.vhostConf
23 davical.apache.vhostConf
24 ];
25 };
26
27 services.myPhpfpm.poolConfigs = {
28 davical = davical.phpFpm.pool;
29 };
30
31 };
32}
33
diff --git a/virtual/modules/websites/tools/dav/infcloud.nix b/virtual/modules/websites/tools/dav/infcloud.nix
new file mode 100644
index 0000000..876578b
--- /dev/null
+++ b/virtual/modules/websites/tools/dav/infcloud.nix
@@ -0,0 +1,38 @@
1{ stdenv, fetchzip, ed }:
2let
3 infcloud = rec {
4 webRoot = stdenv.mkDerivation rec {
5 version = "0.13.1";
6 name = "InfCloud-${version}";
7 src = fetchzip {
8 url = "https://www.inf-it.com/InfCloud_${version}.zip";
9 sha256 = "1fjhs0cj0b9fhf5ysfz281mknmmg1z551bas143sxfcqlpa5aiiq";
10 };
11 buildPhase = ''
12 ./cache_update.sh
13 rm config.js
14 '';
15 installPhase = ''
16 cp -a . $out
17 ln -s ${./infcloud_config.js} $out/config.js
18 '';
19 buildInputs = [ ed ];
20 };
21 apache = {
22 user = "wwwrun";
23 group = "wwwrun";
24 vhostConf = ''
25 Alias /carddavmate ${webRoot}
26 Alias /caldavzap ${webRoot}
27 Alias /infcloud ${webRoot}
28 <Directory ${webRoot}>
29 AllowOverride All
30 Options FollowSymlinks
31 Require all granted
32 DirectoryIndex index.html
33 </Directory>
34 '';
35 };
36 };
37in
38 infcloud
diff --git a/virtual/modules/websites/tools/dav/infcloud_config.js b/virtual/modules/websites/tools/dav/infcloud_config.js
new file mode 100644
index 0000000..ba73860
--- /dev/null
+++ b/virtual/modules/websites/tools/dav/infcloud_config.js
@@ -0,0 +1,1446 @@
1/*
2InfCloud - the open source CalDAV/CardDAV Web Client
3Copyright (C) 2011-2015
4 Jan Mate <jan.mate@inf-it.com>
5 Andrej Lezo <andrej.lezo@inf-it.com>
6 Matej Mihalik <matej.mihalik@inf-it.com>
7
8This program is free software: you can redistribute it and/or modify
9it under the terms of the GNU Affero General Public License as
10published by the Free Software Foundation, either version 3 of the
11License, or (at your option) any later version.
12
13This program is distributed in the hope that it will be useful,
14but WITHOUT ANY WARRANTY; without even the implied warranty of
15MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16GNU Affero General Public License for more details.
17
18You should have received a copy of the GNU Affero General Public License
19along with this program. If not, see <http://www.gnu.org/licenses/>.
20*/
21
22
23// NOTE: see readme.txt before you start to configure this client!
24
25
26// NOTE: do not forget to execute the cache_update.sh script every time you
27// update this configuration file or any other files (otherwise your browser
28// will use the previous version of files stored in HTML5 cache). Alternatively
29// you can update the cache.manifest manually - edit the second line beginning
30// with "#V 20" to anything else (this file simple needs "some" change)
31
32
33// Supported setup types (use ONE of them):
34// a.) globalAccountSettings => username and password is hardcoded
35// in config.js, automatic login without the login screen
36// - advantages: fast login process = no username/password is required
37// - disadvantages: username/password is visible in your config.js, so
38// this type of setup is recommended ONLY for intranet/home users
39// b.) globalNetworkCheckSettings => standard setup with login screen
40// - advantages: username/password is required (no visible
41// username/password in config.js)
42// - disadvantages: if a user enters wrong username/password then
43// the browser will show authentication popup window (it is NOT
44// possible to disable it in JavaScript; see the next option)
45// c.) globalNetworkAccountSettings => advanced setup with login screen
46// - advantages: no authentication popup if you enter wrong username/
47// password, dynamic XML configuration generator (you can generate
48// different configurations for your users /by modifying the "auth"
49// module configuration or the PHP code itself/)
50// - disadvantages: requires PHP >= 5.3 and additional configuration,
51// only basic http authentication is supported => always use https!
52//
53//
54// What is a "principal URL"? => Check you server documentation!
55// - "principal URL" is NOT "collection URL"
56// - this client automatically detects collections for "principal URL"
57// - PROPER "principal URL" looks like:
58// https://server.com:8443/principals/users/USER/
59// https://server.com:8443/caldav.php/USER/
60// - INVALID principal URL looks like:
61// https://server.com:8443/principals/users/USER/collection/
62// => this is a collection URL
63// https://server.com:8443/caldav.php/USER/collection/
64// => this is a collection URL
65// https://server.com:8443/principals/users/USER
66// => missing trailing '/'
67// https://server.com:8443/caldav.php/USER
68// => missing trailing '/'
69// /caldav.php/USER/
70// => relative URL instead of full URL
71//
72//
73// List of properties used in globalAccountSettings, globalNetworkCheckSettings
74// and globalNetworkAccountSettings variables (+ in the "auth" module):
75// - href
76// Depending on the setup type set the value to:
77// a.) globalAccountSettings: full "principal URL"
78// b.) globalNetworkCheckSettings: "principal URL" WITHOUT the "USER/" part
79// c.) globalNetworkAccountSettings: "full URL" to the "auth" directory
80// This property is supported in:
81// globalAccountSettings
82// globalNetworkCheckSettings
83// globalNetworkAccountSettings
84// - userAuth
85// - userName
86// Set the username you want to login.
87// - userPassword
88// Set the password for the given username.
89// This property is supported in:
90// globalAccountSettings
91// - timeOut
92// This option sets the timeout for jQuery .ajax call (in miliseconds).
93// Example:
94// timeOut: 90000
95// This property is supported in:
96// globalAccountSettings
97// globalNetworkCheckSettings
98// globalNetworkAccountSettings
99// - lockTimeOut
100// NOTE: used only if server supports LOCK requests
101// This option sets the LOCK timeout value if resource locking
102// is used (in miliseconds).
103// Example:
104// lockTimeOut: 10000
105// This property is supported in:
106// globalAccountSettings
107// globalNetworkCheckSettings
108// globalNetworkAccountSettings (available in auth module only)
109// - checkContentType
110// This option enables a content-type checking for server response.
111// If enabled then only objects with proper content-type are inserted
112// into the interface.
113// If you cannot see data in the interface you may try to disable it (useful
114// if your server returns wrong value in "propstat/prop/getcontenttype").
115// If undefined then content-type checking is enabled.
116// Examples:
117// checkContentType: true
118// checkContentType: false
119// This property is supported in:
120// globalAccountSettings
121// globalNetworkCheckSettings
122// globalNetworkAccountSettings (available in auth module only)
123// - settingsAccount
124// NOTE: server support for custom DAV properties is REQUIRED!
125// This option sets the account where the client properties such as:
126// loaded collections, enabled collections, ... are saved during
127// the logout and resource/collection synchronisation
128// NOTE: set it to true ONLY for ONE account!
129// Examples:
130// settingsAccount: true
131// settingsAccount: false
132// This property is supported in:
133// globalAccountSettings
134// globalNetworkCheckSettings
135// globalNetworkAccountSettings (available in auth module only)
136// - delegation
137// NOTE: server support for this functionality is REQUIRED!
138// This option allows you to load delegated (shared) collections.
139// If set to true (default) then delegation functionality is enabled,
140// and the interface allows you to load delegated collections.
141// If false then delegation functionality is completely disabled.
142// Examples:
143// delegation: true
144// delegation: false
145// This property is supported in:
146// globalAccountSettings
147// globalNetworkCheckSettings
148// globalNetworkAccountSettings (available in auth module only)
149// - additionalResources
150// This options sets the list of additional resources (e.g. shared resources
151// accessible by all users). If the server supports delegation (see
152// the delegation option above) there is no reason to use this option!
153// Supported values:
154// - array of URL encoded resource names (not collections), such as:
155// 'company'
156// 'shared_resource'
157// If empty (default) or undefined then shared resources are not loaded
158// using this option, but may be loaded using the delegation option.
159// Examples:
160// additionalResources=[]
161// additionalResources=['public', 'shared_resource']
162// This property is supported in:
163// globalNetworkCheckSettings
164// - hrefLabel
165// This option sets the server name in the resource header (useful if
166// you want to see custom resource header above the collections).
167// You can use the following variables in the value:
168// %H = full hostname (including the port number)
169// %h = full hostname (without the port number)
170// %D = full domain name
171// %d = only the first and second level domain
172// %P = principal name
173// %p = principal name without the @domain.com part (if present)
174// %U = logged user name
175// %u = logged user name without the @domain.com part (if present)
176// If undefined, empty or or null then '%d/%p [%u]' is used.
177// Examples:
178// hrefLabel: '%d/%p [%u]'
179// hrefLabel: '%D/%u'
180// This property is supported in:
181// globalAccountSettings
182// globalNetworkCheckSettings
183// globalNetworkAccountSettings (available in auth module only)
184// - forceReadOnly
185// This option sets the list of collections as "read-only".
186// Supported values:
187// - true
188// all collections will be "read-only"
189// - array of URL encoded
190// - collections, such as:
191// '/caldav.php/user/calendar/'
192// '/caldav.php/user%40domain.com/calendar/'
193// - regexes, such as:
194// new RegExp('^/caldav.php/user/calendar[0-9]/$', 'i')
195// specifies the list of collections marked as "read-only"
196// If null (default) or undefined then server detected privileges are used.
197// Examples:
198// forceReadOnly: null
199// forceReadOnly: true
200// forceReadOnly: ['/caldav.php/user/calendar/',
201// '/caldav.php/user/calendar2/']
202// forceReadOnly: [new RegExp('^/.*/user/calendar[0-9]/$', 'i')]
203// This property is supported in:
204// globalAccountSettings
205// globalNetworkCheckSettings
206// globalNetworkAccountSettings (available in auth module only, with
207// different syntax for regexes)
208// - ignoreAlarms
209// This option sets list of calendar collections with disabled
210// alarm functionality.
211// Supported values:
212// - true
213// alarm functionality is disabled for all collections
214// - array of URL encoded
215// - collections, such as:
216// '/caldav.php/user/calendar/'
217// '/caldav.php/user%40domain.com/calendar/'
218// - regexes, such as:
219// new RegExp('^/caldav.php/user/calendar[0-9]/$', 'i')
220// specifies the list of collections with disabled alarm functionality.
221// If false (default) or undefined then alarm functionality is enabled
222// for all collections.
223// Examples:
224// ignoreAlarms: true
225// ignoreAlarms: ['/caldav.php/user/calendar/',
226// '/caldav.php/user/calendar2/']
227// ignoreAlarms: [new RegExp('^/.*/user/calendar[0-9]/$', 'i')]
228// This property is supported in:
229// globalAccountSettings
230// globalNetworkCheckSettings
231// globalNetworkAccountSettings (available in auth module only, with
232// different syntax for regexes)
233// - backgroundCalendars
234// This options defines a list of background calendars. If there is
235// at least one event defined for the given day in a background calendar,
236// the background color for that day will be pink/light-red.
237// Supported values:
238// - array of URL encoded
239// - collections, such as:
240// '/caldav.php/user/calendar/'
241// '/caldav.php/user%40domain.com/calendar/'
242// - regexes, such as:
243// new RegExp('^/caldav.php/user/calendar[0-9]/$', 'i')
244// specifies the list of background calendar collections.
245// Examples:
246// backgroundCalendars: ['/caldav.php/user/calendar/',
247// '/caldav.php/user/calendar2/']
248// backgroundCalendars: [new RegExp('^/.*/user/calendar[0-9]/$', 'i')]
249// This property is supported in:
250// globalAccountSettings
251// globalNetworkCheckSettings
252// globalNetworkAccountSettings (available in auth module only, with
253// different syntax for regexes)
254// Special options not present in configuration examples:
255// NOTE: use ONLY if you know what are you doing!
256// - crossDomain
257// This option sets the crossDomain for jQuery .ajax call. If null (default)
258// then the value is autodetected /and the result is shown in the console/
259// - withCredentials
260// This option sets the withCredentials for jQuery .ajax call. The default
261// value is false and there is NO REASON to change it to true!
262// NOTE: if true, Access-Control-Allow-Origin "*" (CORS header) not works!
263
264
265// globalAccountSettings
266// Use this option if you want to use automatic login (without a login
267// screen) with hardcoded username/password in config.js. Otherwise use
268// globalNetworkCheckSettings or globalNetworkAccountSettings (see below).
269// NOTE: if this option is used the value must be an array of object(s).
270// List of properties used in globalAccountSettings variable:
271// - href
272// Set this option to the full "principal URL".
273// NOTE: the last character in the value must be '/'
274// - userAuth
275// - userName
276// Set the username you want to login.
277// - userPassword
278// Set the password for the given username.
279// NOTE: for description of other properties see comments at the beginning
280// of this file.
281// NOTE: for minimal/fast setup you need to set only the href and userAuth
282// options. It is safe/recommended to keep the remaining options unchanged!
283// Example:
284//var globalAccountSettings=[
285// {
286// href: 'https://server1.com:8443/caldav.php/USERNAME1/',
287// userAuth:
288// {
289// userName: 'USERNAME1',
290// userPassword: 'PASSWORD1'
291// },
292// timeOut: 90000,
293// lockTimeOut: 10000,
294// checkContentType: true,
295// settingsAccount: true,
296// delegation: true,
297// hrefLabel: null,
298// forceReadOnly: null,
299// ignoreAlarms: false,
300// backgroundCalendars: []
301// },
302// {
303// href: 'https://server2.com:8443/caldav.php/USERNAME2/',
304// ...
305// ...
306// }
307//];
308
309
310// globalNetworkCheckSettings
311// Use this option if you want to use standard login screen without
312// hardcoded username/password in config.js (used by globalAccountSettings).
313// NOTE: if this option is used the value must be an object.
314// List of properties used in globalAccountSettings variable:
315// - href
316// Set this option to the "principal URL" WITHOUT the "USERNAME/"
317// part (this options uses the username from the login screen).
318// NOTE: the last character in the value must be '/'
319// NOTE: for description of other properties see comments at the beginning
320// of this file.
321// NOTE: for minimal/fast setup you need to set only the href option. It is
322// safe/recommended to keep the remaining options unchanged!
323// Example href values:
324// OS X server http example (see misc/readme_osx.txt for server setup):
325// href: 'http://osx.server.com:8008/principals/users/'
326// OS X server https example (see misc/readme_osx.txt for server setup):
327// href: 'https://osx.server.com:8443/principals/users/'
328// Cyrus server https example:
329// href: 'https://cyrus.server.com/dav/principals/user/'
330// Example:
331// Davical example which automatically detects the protocol, server name,
332// port, ... (client installed into Davical "htdocs" subdirectory;
333// works "out of the box", no additional setup required):
334var globalNetworkCheckSettings={
335 href: location.protocol+'//'+location.hostname+
336 (location.port ? ':'+location.port: '')+
337 location.pathname.replace(RegExp('/+[^/]+/*(index\.html)?$'),'')+
338 '/caldav.php/',
339 timeOut: 90000,
340 lockTimeOut: 10000,
341 checkContentType: true,
342 settingsAccount: true,
343 delegation: true,
344 additionalResources: [],
345 hrefLabel: null,
346 forceReadOnly: null,
347 ignoreAlarms: false,
348 backgroundCalendars: []
349}
350
351
352// globalNetworkAccountSettings
353// Try this option ONLY if you have working setup using
354// globalNetworkCheckSettings and want to fix the authentication popup
355// window problem (if invalid username/password is entered)!
356// If you use this option then your browser sends username/password to the PHP
357// "auth" module ("auth" directory) instead of the DAV server itself.
358// The "auth" module then validates your username/password against your server,
359// and if the authentication is successful, then it sends back a configuration
360// XML (requires additional configuration). The resulting XML is handled
361// IDENTICALLY as the globalAccountSettings configuration option.
362// NOTE: for the "auth" module configuration see readme.txt!
363// NOTE: this option invokes a login screen and disallows access until
364// the client gets correct XML configuration file from the server!
365// List of properties used in globalNetworkAccountSettings variable:
366// - href
367// Set this option to the "full URL" of the "auth" directory
368// NOTE: the last character in the value must be '/'
369// NOTE: for description of other properties see comments at the beginning
370// of this file.
371// Example href values:
372// href: 'https://server.com/client/auth/'
373// Example:
374// Use this configuration if the "auth" module is located in the client
375// installation subdirectory (default):
376//var globalNetworkAccountSettings={
377// href: location.protocol+'//'+location.hostname+
378// (location.port ? ':'+location.port : '')+
379// location.pathname.replace(RegExp('index\.html$'),'')+
380// 'auth/',
381// timeOut: 30000
382//};
383
384
385// globalUseJqueryAuth
386// Use jQuery .ajax() auth or custom header for HTTP basic auth (default).
387// Set this option to true if your server uses digest auth (note: you may
388// experience auth popups on some browsers).
389// If undefined (or empty), custom header for HTTP basic auth is used.
390// Example:
391//var globalUseJqueryAuth=false;
392
393
394// globalBackgroundSync
395// Enable background synchronization even if the browser window/tab has no
396// focus.
397// If false, synchronization is performed only if the browser window/tab
398// is focused. If undefined or not false, then background sync is enabled.
399// Example:
400var globalBackgroundSync=true;
401
402
403// globalSyncResourcesInterval
404// This option defines how often (in miliseconds) are resources/collections
405// asynchronously synchronized.
406// Example:
407var globalSyncResourcesInterval=120000;
408
409
410// globalEnableRefresh
411// This option enables or disables the manual synchronization button in
412// the interface. If this option is enabled then users can perform server
413// synchronization manually. Enabling this option may cause high server
414// load (even DDOS) if users will try to manually synchronize data too
415// often (instead of waiting for the automatic synchronization).
416// If undefined or false, the synchronization button is disabled.
417// NOTE: enable this option only if you really know what are you doing!
418// Example:
419var globalEnableRefresh=false;
420
421
422// globalEnableKbNavigation
423// Enable basic keyboard navigation using arrow keys?
424// If undefined or not false, keyboard navigation is enabled.
425// Example:
426var globalEnableKbNavigation=true;
427
428
429// globalSettingsType
430// Where to store user settings such as: active view, enabled/selected
431// collections, ... (the client store them into DAV property on the server).
432// NOTE: not all servers support storing DAV properties (some servers support
433// only subset /or none/ of these URLs).
434// Supported values:
435// - 'principal-URL', '', null or undefined (default) => settings are stored
436// to principal-URL (recommended for most servers)
437// - 'addressbook-home-set' => settings are are stored to addressbook-home-set
438// - 'calendar-home-set' => settings are stored to calendar-home-set
439// Example:
440//var globalSettingsType='';
441
442
443// globalCrossServerSettingsURL
444// Settings such as enabled/selected collections are stored on the server
445// (see the previous option) in form of full URL
446// (e.g.: https://user@server:port/principal/collection/), but even if this
447// approach is "correct" (you can use the same principal URL with multiple
448// different logins, ...) it causes a problem if your server is accessible
449// from multiple URLs (e.g. http://server/ and https://server/). If you want
450// to store only the "principal/collection/" part of the URL (instead of the
451// full URL) then enable this option.
452// Example:
453//var globalCrossServerSettingsURL=false;
454
455
456// globalInterfaceLanguage
457// Default interface language (note: this option is case sensitive):
458// cs_CZ (Čeština [Czech])
459// da_DK (Dansk [Danish]; thanks Niels Bo Andersen)
460// de_DE (Deutsch [German]; thanks Marten Gajda and Thomas Scheel)
461// en_US (English [English/US])
462// es_ES (Español [Spanish]; thanks Damián Vila)
463// fr_FR (Français [French]; thanks John Fischer)
464// it_IT (Italiano [Italian]; thanks Luca Ferrario)
465// ja_JP (日本語 [Japan]; thanks Muimu Nakayama)
466// hu_HU (Magyar [Hungarian])
467// nl_NL (Nederlands [Dutch]; thanks Johan Vromans)
468// sk_SK (Slovenčina [Slovak])
469// tr_TR (Türkçe [Turkish]; thanks Selcuk Pultar)
470// ru_RU (Русский [Russian]; thanks Александр Симонов)
471// uk_UA (Українська [Ukrainian]; thanks Serge Yakimchuck)
472// zh_CN (中国 [Chinese]; thanks Fandy)
473// Example:
474var globalInterfaceLanguage='fr_FR';
475
476
477// globalInterfaceCustomLanguages
478// If defined and not empty then only languages listed here are shown
479// at the login screen, otherwise (default) all languages are shown
480// NOTE: values in the array must refer to an existing localization
481// (see the option above)
482// Example:
483// globalInterfaceCustomLanguages=['en_US', 'sk_SK'];
484var globalInterfaceCustomLanguages=[];
485
486
487// globalSortAlphabet
488// Use JavaScript localeCompare() or custom alphabet for data sorting.
489// Custom alphabet is used by default because JavaScript localeCompare()
490// not supports collation and often returns "wrong" result. If set to null
491// then localeCompare() is used.
492// Example:
493// var globalSortAlphabet=null;
494var globalSortAlphabet=' 0123456789'+
495 'AÀÁÂÄÆÃÅĀBCÇĆČDĎEÈÉÊËĒĖĘĚFGĞHIÌÍÎİÏĪĮJKLŁĹĽMNŃÑŇOÒÓÔÖŐŒØÕŌ'+
496 'PQRŔŘSŚŠȘșŞşẞTŤȚțŢţUÙÚÛÜŰŮŪVWXYÝŸZŹŻŽ'+
497 'aàáâäæãåābcçćčdďeèéêëēėęěfgğhiìíîïīįıjklłĺľmnńñňoòóôöőœøõō'+
498 'pqrŕřsśšßtťuùúûüűůūvwxyýÿzźżžАБВГҐДЕЄЖЗИІЇЙКЛМНОПРСТУФХЦЧШЩЮЯ'+
499 'Ьабвгґдеєжзиіїйклмнопрстуфхцчшщюяь';
500
501
502// globalSearchTransformAlphabet
503// To support search without diacritics (e.g. search for 'd' will find: 'Ď', 'ď')
504// it is required to define something like "character equivalence".
505// key = regex text, value = search character
506// Example:
507var globalSearchTransformAlphabet={
508 '[ÀàÁáÂâÄäÆæÃãÅåĀā]': 'a', '[ÇçĆćČč]': 'c', '[Ďď]': 'd',
509 '[ÈèÉéÊêËëĒēĖėĘęĚě]': 'e', '[Ğğ]': 'g', '[ÌìÍíÎîİıÏïĪīĮį]': 'i',
510 '[ŁłĹ弾]': 'l', '[ŃńÑñŇň]': 'n', '[ÒòÓóÔôÖöŐőŒœØøÕõŌō]': 'o',
511 '[ŔŕŘř]': 'r', '[ŚśŠšȘșŞşẞß]': 's', '[ŤťȚțŢţ]': 't',
512 '[ÙùÚúÛûÜüŰűŮůŪū]': 'u', '[ÝýŸÿ]': 'y', '[ŹźŻżŽž]': 'z'
513};
514
515// globalResourceAlphabetSorting
516// If more than one resource (server account) is configured, sort the
517// resources alphabetically?
518// Example:
519var globalResourceAlphabetSorting=true;
520
521
522// globalNewVersionNotifyUsers
523// Update notification will be shown only to users with login names defined
524// in this array.
525// If undefined (or empty), update notifications will be shown to all users.
526// Example:
527// globalNewVersionNotifyUsers=['admin', 'peter'];
528var globalNewVersionNotifyUsers=[];
529
530
531// globalDatepickerFormat
532// Set the datepicker format (see
533// http://docs.jquery.com/UI/Datepicker/formatDate for valid values).
534// NOTE: date format is predefined for each localization - use this option
535// ONLY if you want to use custom date format (instead of the localization
536// predefined one).
537// Example:
538//var globalDatepickerFormat='dd.mm.yy';
539var globalDatepickerFormat='yy-mm-dd';
540
541
542// globalDatepickerFirstDayOfWeek
543// Set the datepicker first day of the week: Sunday is 0, Monday is 1, etc.
544// Example:
545var globalDatepickerFirstDayOfWeek=1;
546
547
548// globalHideInfoMessageAfter
549// How long are information messages (such as: success, error) displayed
550// (in miliseconds).
551// Example:
552var globalHideInfoMessageAfter=1800;
553
554
555// globalEditorFadeAnimation
556// Set the editor fade in/out animation duration when editing or saving data
557// (in miliseconds).
558// Example:
559var globalEditorFadeAnimation=666;
560
561
562
563
564// ******* CalDAV (CalDavZAP) related settings ******* //
565
566// globalEventStartPastLimit, globalEventStartFutureLimit, globalTodoPastLimit
567// Number of months pre-loaded from past/future in advance for calendars
568// and todo lists (if null then date range synchronization is disabled).
569// NOTE: interval synchronization is used only if your server supports
570// sync-collection REPORT (e.g. DAViCal).
571// NOTE: if you experience problems with data loading and your server has
572// no time-range filtering support set these variables to null.
573// Example:
574var globalEventStartPastLimit=3;
575var globalEventStartFutureLimit=3;
576var globalTodoPastLimit=1;
577
578
579// globalLoadedCalendarCollections
580// This option sets the list of calendar collections (down)loaded after login.
581// If empty then all calendar collections for the currently logged user are
582// loaded.
583// NOTE: settings stored on the server (see settingsAccount) overwrite this
584// option.
585// Example:
586var globalLoadedCalendarCollections=[];
587
588
589// globalLoadedTodoCollections
590// This option sets the list of todo collections (down)loaded after login.
591// If empty then all todo collections for the currently logged user are loaded.
592// NOTE: settings stored on the server (see settingsAccount) overwrite this
593// option.
594// Example:
595var globalLoadedTodoCollections=[];
596
597
598// globalActiveCalendarCollections
599// This options sets the list of calendar collections checked (enabled
600// checkbox => data visible in the interface) by default after login.
601// If empty then all loaded calendar collections for the currently logged
602// user are checked.
603// NOTE: only already (down)loaded collections can be checked (see
604// the globalLoadedCalendarCollections option).
605// NOTE: settings stored on the server (see settingsAccount) overwrite this
606// option.
607// Example:
608var globalActiveCalendarCollections=[];
609
610
611// globalActiveTodoCollections
612// This options sets the list of todo collections checked (enabled
613// checkbox => data visible in the interface) by default after login.
614// If empty then all loaded todo collections for the currently logged
615// user are checked.
616// NOTE: only already (down)loaded collections can be checked (see
617// the globalLoadedTodoCollections option).
618// NOTE: settings stored on the server (see settingsAccount) overwrite this
619// option.
620// Example:
621var globalActiveTodoCollections=[];
622
623
624// globalCalendarSelected
625// This option sets which calendar collection will be pre-selected
626// (if you create a new event) by default after login.
627// The value must be URL encoded path to a calendar collection,
628// for example: 'USER/calendar/'
629// If empty or undefined then the first available calendar collection
630// is selected automatically.
631// NOTE: only already (down)loaded collections can be pre-selected (see
632// the globalLoadedCalendarCollections option).
633// NOTE: settings stored on the server (see settingsAccount) overwrite this
634// option.
635// Example:
636//var globalCalendarSelected='';
637
638
639// globalTodoCalendarSelected
640// This option sets which todo collection will be pre-selected
641// (if you create a new todo) by default after login.
642// The value must be URL encoded path to a todo collection,
643// for example: 'USER/todo_calendar/'
644// If empty or undefined then the first available todo collection
645// is selected automatically.
646// NOTE: only already (down)loaded collections can be pre-selected (see
647// the globalLoadedTodoCollections option).
648// NOTE: settings stored on the server (see settingsAccount) overwrite this
649// option.
650// Example:
651//var globalTodoCalendarSelected='';
652
653
654// globalActiveView
655// This options sets the default fullcalendar view option (the default calendar
656// view after the first login).
657// Supported values:
658// - 'month'
659// - 'multiWeek'
660// - 'agendaWeek'
661// - 'agendaDay'
662// NOTE: we use custom and enhanced version of fullcalendar!
663// Example:
664var globalActiveView='multiWeek';
665
666
667// globalOpenFormMode
668// Open new event form on 'single' or 'double' click.
669// If undefined or not 'double', then 'single' is used.
670// Example:
671var globalOpenFormMode='double';
672
673
674// globalTodoListFilterSelected
675// This options sets the list of filters in todo list that are selected
676// after login.
677// Supported options:
678// - 'filterAction'
679// - 'filterProgress' (available only if globalAppleRemindersMode is disabled)
680// - 'filterCompleted'
681// - 'filterCanceled' (available only if globalAppleRemindersMode is disabled)
682// NOTE: settings stored on the server (see settingsAccount) overwrite this
683// option.
684// Example:
685var globalTodoListFilterSelected=['filterAction', 'filterProgress'];
686
687
688// globalCalendarStartOfBusiness, globalCalendarEndOfBusiness
689// These options set the start and end of business hours with 0.5 hour
690// precision. Non-business hours are faded out in the calendar interface.
691// If both variables are set to the same value then no fade out occurs.
692// Example:
693var globalCalendarStartOfBusiness=8;
694var globalCalendarEndOfBusiness=17;
695
696
697// globalDefaultEventDuration
698// This option sets the default duration (in minutes) for newly created events.
699// If undefined or null, globalCalendarEndOfBusiness value will be taken as
700// a default end time instead.
701// Example:
702var globalDefaultEventDuration=120;
703
704
705// globalAMPMFormat
706// This option enables to use 12 hours format (AM/PM) for displaying time.
707// NOTE: time format is predefined for each localization - use this option
708// ONLY if you want to use custom time format (instead of the localization
709// predefined one).
710// Example:
711//var globalAMPMFormat=false;
712
713
714// globalTimeFormatBasic
715// This option defines the time format information for events in month and
716// multiweek views. If undefined or null then default value is used.
717// If defined as empty string no time information is shown in these views.
718// See http://arshaw.com/fullcalendar/docs/utilities/formatDate/ for exact
719// formating rules.
720// Example:
721//var globalTimeFormatBasic='';
722
723
724// globalTimeFormatAgenda
725// This option defines the time format information for events in day and
726// week views. If undefined or null then default value is used.
727// If defined as empty string no time information is shown in these views.
728// See http://arshaw.com/fullcalendar/docs/utilities/formatDate/ for exact
729// formating rules.
730// Example:
731//var globalTimeFormatAgenda='';
732
733
734// globalDisplayHiddenEvents
735// This option defined whether events from unechecked calendars are displayed
736// with certain transparency (true) or completely hidden (false).
737// Example:
738var globalDisplayHiddenEvents=false;
739
740
741// globalTimeZoneSupport
742// This option enables timezone support in the client.
743// NOTE: timezone cannot be specified for all-day events because these don't
744// have start and end time.
745// If this option is disabled then local time is used.
746// Example:
747var globalTimeZoneSupport=true;
748
749
750// globalTimeZone
751// If timezone support is enabled, this option sets the default timezone.
752// See timezones.js or use the following command to get the list of supported
753// timezones (defined in timezones.js):
754// grep "'[^']\+': {" timezones.js | sed -Ee "s#(\s*'|':\s*\{)##g"
755// Example:
756var globalTimeZone='Europe/Paris';
757
758
759// globalTimeZonesEnabled
760// This option sets the list of available timezones in the interface (for the
761// list of supported timezones see the comment for the previous configuration
762// option).
763// NOTE: if there is at least one event/todo with a certain timezone defined,
764// that timezone is enabled (even if it is not present in this list).
765// Example:
766// var globalTimeZonesEnabled=['America/New_York', 'Europe/Berlin'];
767var globalTimeZonesEnabled=[];
768
769
770// globalRewriteTimezoneComponent
771// This options sets whether the client will enhance/replace (if you edit an
772// event or todo) the timezone information using the official IANA timezone
773// database information (recommended).
774// Example:
775var globalRewriteTimezoneComponent=true;
776
777
778// globalRemoveUnknownTimezone
779// This options sets whether the client will remove all non-standard timezone
780// names from events and todos (if you edit an event or todo)
781// (e.g.: /freeassociation.sourceforge.net/Tzfile/Europe/Vienna)
782// Example:
783var globalRemoveUnknownTimezone=false;
784
785
786// globalShowHiddenAlarms
787// This option sets whether the client will show alarm notifications for
788// unchecked calendars. If this option is enabled and you uncheck a calendar
789// in the calendar list, alarm notifications will be temporary disabled for
790// unchecked calendar(s).
791// Example:
792var globalShowHiddenAlarms=false;
793
794
795// globalIgnoreCompletedOrCancelledAlarms
796// This options sets whether the client will show alarm notifications for
797// already completed or cancelled todos. If enabled then alarm notification
798// for completed and cancelled todos are disabled.
799// Example:
800var globalIgnoreCompletedOrCancelledAlarms=true;
801
802
803// globalMozillaSupport
804// Mozilla automatically treats custom repeating event calculations as if
805// the start day of the week is Monday, despite what day is chosen in settings.
806// Set this variable to true to use the same approach, ensuring compatible
807// event rendering in special cases.
808// Example:
809var globalMozillaSupport=false;
810
811
812// globalCalendarColorPropertyXmlns
813// This options sets the namespace used for storing the "calendar-color"
814// property by the client.
815// If true, undefined (or empty) "http://apple.com/ns/ical/" is used (Apple
816// compatible). If false, then the calendar color modification functionality
817// is completely disabled.
818// Example:
819//var globalCalendarColorPropertyXmlns=true;
820
821
822// globalWeekendDays
823// This option sets the list of days considered as weekend days (these
824// are faded out in the calendar interface). Non-weekend days are automatically
825// considered as business days.
826// Sunday is 0, Monday is 1, etc.
827// Example:
828var globalWeekendDays=[0, 6];
829
830
831// globalAppleRemindersMode
832// If this option is enabled then then client will use the same approach
833// for handling repeating reminders (todos) as Apple. It is STRONGLY
834// recommended to enabled this option if you use any Apple clients for
835// reminders (todos).
836// Supported options:
837// - 'iOS6'
838// - 'iOS7'
839// - true (support of the latest iOS version - 'iOS8')
840// - false
841// If this option is enabled:
842// - RFC todo support is SEVERELY limited and the client mimics the behaviour
843// of Apple Reminders.app (to ensure maximum compatibility)
844// - when a single instance of repeating todo is edited, it becomes an
845// autonomous non-repeating todo with NO relation to the original repeating
846// todo
847// - capabilities of repeating todos are limited - only the first instance
848// is ever visible in the interface
849// - support for todo DTSTART attribute is disabled
850// - support for todo STATUS attribute other than COMPLETED and NEEDS-ACTION
851// is disabled
852// - [iOS6 only] support for LOCATION and URL attributes is disabled
853// Example:
854var globalAppleRemindersMode=true;
855
856
857// globalSubscribedCalendars
858// This option specifies a list of remote URLs to ics files (e.g.: used
859// for distributing holidays information). Subscribed calendars are
860// ALWAYS read-only. Remote servers where ics files are hosted MUST
861// return proper CORS headers (see readme.txt) otherwise this functionality
862// will not work!
863// NOTE: subsribed calendars are NOT "shared" calendars. For "shared"
864// calendars see the delegation option in globalAccountSettings,
865// globalNetworkCheckSettings and globalNetworkAccountSettings.
866// List of properties used in globalSubscribedCalendars variable:
867// - hrefLabel
868// This options defines the header string above the subcsribed calendars.
869// - calendars
870// This option specifies an array of remote calendar objects with the
871// following properties:
872// - href
873// Set this option to the "full URL" of the remote calendar
874// - userAuth
875// NOTE: keep empty if remote authentication is not required!
876// - userName
877// Set the username you want to login.
878// - userPassword
879// Set the password for the given username.
880// - typeList
881// Set the list of objects you want to process from remote calendars;
882// two options are available:
883// - 'vevent' (show remote events in the interface)
884// - 'vtodo' (show remote todos in the interface)
885// - ignoreAlarm
886// Set this option to true if you want to disable alarm notifications
887// from the remote calendar.
888// - displayName
889// Set this option to the name of the calendar you want to see
890// in the interface.
891// - color
892// Set the calendar color you want to see in the interface.
893// Example:
894//var globalSubscribedCalendars={
895// hrefLabel: 'Subscribed',
896// calendars: [
897// {
898// href: 'http://something.com/calendar.ics',
899// userAuth: {
900// userName: '',
901// userPassword: ''
902// },
903// typeList: ['vevent', 'vtodo'],
904// ignoreAlarm: true,
905// displayName: 'Remote Calendar 1',
906// color: '#ff0000'
907// },
908// {
909// href: 'http://calendar.com/calendar2.ics',
910// ...
911// ...
912// }
913// ]
914//};
915
916
917
918// ******* CardDAV (CardDavMATE) related settings ******* //
919
920
921// globalLoadedAddressbookCollections
922// This option sets the list of addressbook collections (down)loaded after
923// login. If empty then all addressbook collections for the currently logged
924// user are loaded.
925// NOTE: settings stored on the server (see settingsAccount) overwrite this
926// option.
927// Example:
928var globalLoadedAddressbookCollections=[];
929
930
931// globalActiveAddressbookCollections
932// This options sets the list of addressbook collections checked (enabled
933// checkbox => data visible in the interface) by default after login.
934// If empty then all loaded addressbook collections for the currently logged
935// user are checked.
936// NOTE: only already (down)loaded collections can be checked (see
937// the globalLoadedAddressbookCollections option).
938// NOTE: settings stored on the server (see settingsAccount) overwrite this
939// option.
940// Example:
941var globalActiveAddressbookCollections=[];
942
943
944// globalAddressbookSelected
945// This option sets which addressbook collection will be pre-selected
946// (if you create a new contact) by default after login.
947// The value must be URL encoded path to an addressbook collection,
948// for example: 'USER/addressbook/'
949// If empty or undefined then the first available addressbook collection
950// is selected automatically.
951// NOTE: only already (down)loaded collections can be pre-selected (see
952// the globalLoadedAddressbookCollections option).
953// NOTE: settings stored on the server (see settingsAccount) overwrite this
954// option.
955// Example:
956//var globalAddressbookSelected='';
957
958
959// globalCompatibility
960// This options is reserved for various compatibility settings.
961// NOTE: if this option is used the value must be an object.
962// Currently there is only one supported option:
963// - anniversaryOutputFormat
964// Different clients use different (and incompatible) approach
965// to store anniversary date in vCards. Apple stores this attribute as:
966// itemX.X-ABDATE;TYPE=pref:2000-01-01\r\n
967// itemX.X-ABLabel:_$!<Anniversary>!$_\r\n'
968// other clients store this attribute as:
969// X-ANNIVERSARY:2000-01-01\r\n
970// Choose 'apple' or 'other' (lower case) for your 3rd party client
971// compatibility. You can chose both: ['apple', 'other'], but it may
972// cause many problems in the future, for example: duplicate anniversary
973// dates, invalid/old anniversary date in your clients, ...)
974// Examples:
975// anniversaryOutputFormat: ['other']
976// anniversaryOutputFormat: ['apple', 'other']
977// Example:
978var globalCompatibility={anniversaryOutputFormat: ['apple']};
979
980
981// globalUriHandler{Tel,Email,Url,Profile}
982// These options set the URI handlers for TEL, EMAIL, URL and X-SOCIALPROFILE
983// vCard attributes. Set them to null (or comment out) to disable.
984// NOTE: for globalUriHandlerTel is recommended to use 'tel:', 'callto:'
985// or 'skype:'. The globalUriHandlerUrl value is used only if no URI handler
986// is defined in the URL.
987// NOTE: it is safe to keep these values unchanged!
988// Example:
989var globalUriHandlerTel='tel:';
990var globalUriHandlerEmail='mailto:';
991var globalUriHandlerUrl='http://';
992var globalUriHandlerProfile={
993 'twitter': 'http://twitter.com/%u',
994 'facebook': 'http://www.facebook.com/%u',
995 'flickr': 'http://www.flickr.com/photos/%u',
996 'linkedin': 'http://www.linkedin.com/in/%u',
997 'myspace': 'http://www.myspace.com/%u',
998 'sinaweibo': 'http://weibo.com/n/%u'
999};
1000
1001
1002// globalDefaultAddressCountry
1003// This option sets the default country for new address fields.
1004// See common.js or use the following command to get the list of
1005// all supported country codes (defined in common.js):
1006// grep -E "'[a-z]{2}':\s+\[" common.js | sed -Ee 's#^\s+|\s+\[\s+# #g'
1007// Example:
1008var globalDefaultAddressCountry='fr';
1009
1010
1011// globalAddressCountryEquivalence
1012// This option sets the processing of the country field specified
1013// in the vCard ADR attribute.
1014// By default the address field in vCard looks like:
1015// ADR;TYPE=WORK:;;1 Waters Edge;Baytown;LA;30314;USA\r\n
1016// what cause a problem, because the country field is a plain
1017// text and can contain any value, e.g.:
1018// USA
1019// United States of America
1020// US
1021// and because the address format can be completely different for
1022// each country, e.g.:
1023// China address example:
1024// [China]
1025// [Province] [City]
1026// [Street]
1027// [Postal]
1028// Japan address example:
1029// [Postal]
1030// [Prefecture] [County/City]
1031// [Further Divisions]
1032// [Japan]
1033// the client needs to correctly detect the country from the ADR
1034// attribute. Apple solved this problem by using:
1035// item1.ADR;TYPE=WORK:;;1 Waters Edge;Baytown;LA;30314;USA\r\n
1036// item1.X-ABADR:us\r\n
1037// where the second "related" attribute defines the country code
1038// for the ADR attribute. This client uses the same approach, but
1039// if the vCard is created by 3rd party clients and the X-ABADR
1040// is missing, it is possible to define additional "rules" for
1041// country matching. These rules are specied by the country code
1042// (for full list of country codes see the comment for pre previous
1043// option) and a case insensitive regular expression (which matches
1044// the plain text value in the country field).
1045// NOTE: if X-ABADR is not present and the country not matches any
1046// country defined in this option, then globalDefaultAddressCountry
1047// is used by default.
1048// Example:
1049var globalAddressCountryEquivalence=[
1050 {country: 'de', regex: '^\\W*Deutschland\\W*$'},
1051 {country: 'sk', regex: '^\\W*Slovensko\\W*$'}
1052];
1053
1054
1055// globalAddressCountryFavorites
1056// This option defines the list of countries which are shown at the top
1057// of the country list in the interface (for full list of country codes
1058// see the comment for pre globalDefaultAddressCountry option).
1059// Example:
1060// var globalAddressCountryFavorites=['de','sk'];
1061var globalAddressCountryFavorites=[];
1062
1063
1064// globalAddrColorPropertyXmlns
1065// This options sets the namespace used for storing the "addressbook-color"
1066// property by the client.
1067// If true, undefined (or empty) "http://inf-it.com/ns/ab/" is used.
1068// If false, then the addressbook color modification functionality
1069// is completely disabled, and addressbook colors in the interface are
1070// generated automatically.
1071// Example:
1072//var globalAddrColorPropertyXmlns=true;
1073
1074
1075// globalContactStoreFN
1076// This option specifies how the FN (formatted name) is stored into vCard.
1077// The value for this options must be an array of strings, that can contain
1078// the following variables:
1079// prefix
1080// last
1081// middle
1082// first
1083// suffix
1084// The string element of the array can contain any other characters (usually
1085// space or colon). Elements are added into FN only if the there is
1086// a variable match, for example if:
1087// last='Lastname'
1088// first='Firstname'
1089// middle='' (empty)
1090// and this option is set to:
1091// ['last', ' middle', ' first'] (space in the second and third element)
1092// the resulting value for FN will be: 'Lastname Firstname' and not
1093// 'Lastname Firstname' (two spaces), because the middle name is empty (so
1094// the second element is completely ignored /not added into FN/).
1095// NOTE: this attribute is NOT used by this client, and it is also NOT
1096// possible to directly edit it in the interface.
1097// Examples:
1098// var globalContactStoreFN=[' last', ' middle', ' first'];
1099// var globalContactStoreFN=['last', ', middle', ' ,first'];
1100var globalContactStoreFN=['prefix',' last',' middle',' first',' suffix'];
1101
1102
1103// globalGroupContactsByCompanies
1104// This options specifies how contacts are grouped in the interface.
1105// By default the interface looks like (very simple example):
1106// A
1107// Adams Adam
1108// Anderson Peter
1109// B
1110// Brown John
1111// Baker Josh
1112// if grouped by company/deparment the result is:
1113// Company A [Department X]
1114// Adams Adam
1115// Brown John
1116// Company B [Department Y]
1117// Anderson Peter
1118// Baker Josh
1119// If this option is set to true contacts are grouped by company/department,
1120// otherwise (default) contacts are grouped by letters of the alphabet.
1121// If undefined or not true, grouping by alphabet letters is used.
1122// NOTE: see also the globalCollectionDisplay option below.
1123var globalGroupContactsByCompanies=false;
1124
1125
1126// globalCollectionDisplay
1127// This options specifies how data columns in the contact list are displayed.
1128//
1129// NOTE: columns are displayed ONLY if there is enought horizontal place in
1130// the browser window (e.g. if you define 5 columns here, but your browser
1131// window is not wide enough, you will see only first 3 columns instead of 5).
1132//
1133// NOTE: see the globalContactDataMinVisiblePercentage option which defines the
1134// width for columns.
1135//
1136// The value must be an array of columns, where each column is represented by
1137// an object with the following properties:
1138// label => the value of this option is a string used as column header
1139// You can use the following localized variables in the label string:
1140// - {Name}
1141// - {FirstName}
1142// - {LastName}
1143// - {MiddleName}
1144// - {NickName}
1145// - {Prefix}
1146// - {Suffix}
1147// - {BirthDay}
1148// - {PhoneticLastName}
1149// - {PhoneticFirstName}
1150// - {JobTitle}
1151// - {Company}
1152// - {Department}
1153// - {Categories}
1154// - {NoteText}
1155// - {Address}, {AddressWork}, {AddressHome}, {AddressOther}
1156// - {Phone}, {PhoneWork}, {PhoneHome}, {PhoneCell}, {PhoneMain},
1157// {PhonePager}, {PhoneFax}, {PhoneIphone}, {PhoneOther}
1158// - {Email}, {EmailWork}, {EmailHome}, {EmailMobileme}, {EmailOther}
1159// - {URL}, {URLWork}, {URLHome}, {URLHomepage}, {URLOther}
1160// - {Dates}, {DatesAnniversary}, {DatesOther}
1161// - {Related}, {RelatedManager}, {RelatedAssistant}, {RelatedFather},
1162// {RelatedMother}, {RelatedParent}, {RelatedBrother}, {RelatedSister},
1163// {RelatedChild}, {RelatedFriend}, {RelatedSpouse}, {RelatedPartner},
1164// {RelatedOther}
1165// - {Profile}, {ProfileTwitter}, {ProfileFacebook}, {ProfileFlickr},
1166// {ProfileLinkedin}, {ProfileMyspace}, {ProfileSinaweibo}
1167// - {IM}, {IMWork}, {IMHome}, {IMMobileme}, {IMOther}, {IMAim}, {IMIcq},
1168// {IMIrc}, {IMJabber}, {IMMsn}, {IMYahoo}, {IMFacebook}, {IMGadugadu},
1169// {IMGoogletalk}, {IMQq}, {IMSkype}
1170// value => the value of this option is an array of format strings, or
1171// an object with the following properties:
1172// - company (used for company contacts)
1173// - personal (used for user contacts)
1174// where the value of these properties is an array of format strings used
1175// for company or user contacts (you can have different values in the same
1176// column for personal and company contacts).
1177// You can use the following simple variables in the format string:
1178// - {FirstName}
1179// - {LastName}
1180// - {MiddleName}
1181// - {NickName}
1182// - {Prefix}
1183// - {Suffix}
1184// - {BirthDay}
1185// - {PhoneticLastName}
1186// - {PhoneticFirstName}
1187// - {JobTitle}
1188// - {Company}
1189// - {Department}
1190// - {Categories}
1191// - {NoteText}
1192// You can also use parametrized variables, where the parameter is enclosed
1193// in square bracket. Paramatrized variables are useful to extract data
1194// such as home phone {Phone[type=home]}, extract the second phone number
1195// {Phone[:1]} (zero based indexing) or extract the third home phone number
1196// {Phone[type=home][:2]} from the vCard.
1197// NOTE: if the parametrized variable matches multiple items, e.g.:
1198// {Phone[type=work]} (if the contact has multiple work phones) then the
1199// first one is used!
1200//
1201// The following parametrized variables are supported (note: you can use
1202// all of them also without parameters /the first one will be used/):
1203// - {Address[type=XXX]} or {Address[:NUM]} or {Address[type=XXX][:NUM]}
1204// where supported values for XXX are:
1205// - work
1206// - home
1207// - other
1208// - any other custom value
1209// - {Phone[type=XXX]} or {Phone[:NUM]} or {Phone[type=XXX][:NUM]}
1210// where supported values for XXX are:
1211// - work
1212// - home
1213// - cell
1214// - main
1215// - pager
1216// - fax
1217// - iphone
1218// - other
1219// - any other custom value
1220// - {Email[type=XXX]} or {Email[:NUM]} or {Email[type=XXX][:NUM]}
1221// where supported values for XXX are:
1222// - work
1223// - home
1224// - mobileme
1225// - other
1226// - any other custom value
1227// - {URL[type=XXX]} or {URL[:NUM]} or {URL[type=XXX][:NUM]}
1228// where supported values for XXX are:
1229// - work
1230// - home
1231// - homepage
1232// - other
1233// - any other custom value
1234// - {Dates[type=XXX]} or {Dates[:NUM]} or {Dates[type=XXX][:NUM]}
1235// where supported values for XXX are:
1236// - anniversary
1237// - other
1238// - any other custom value
1239// - {Related[type=XXX]} or {Related[:NUM]} or {Related[type=XXX][:NUM]}
1240// where supported values for XXX are:
1241// - manager
1242// - assistant
1243// - father
1244// - mother
1245// - parent
1246// - brother
1247// - sister
1248// - child
1249// - friend
1250// - spouse
1251// - partner
1252// - other
1253// - any other custom value
1254// - {Profile[type=XXX]} or {Profile[:NUM]} or {Profile[type=XXX][:NUM]}
1255// where supported values for XXX are:
1256// - twitter
1257// - facebook
1258// - flickr
1259// - linkedin
1260// - myspace
1261// - sinaweibo
1262// - any other custom value
1263// - {IM[type=XXX]} or {IM[service-type=YYY]} or {IM[:NUM]}
1264// where supported values for XXX are:
1265// - work
1266// - home
1267// - mobileme
1268// - other
1269// - any other custom value
1270// and supported values for YYY are:
1271// - aim
1272// - icq
1273// - irc
1274// - jabber
1275// - msn
1276// - yahoo
1277// - facebook
1278// - gadugadu
1279// - googletalk
1280// - qq
1281// - skype
1282// - any other custom value
1283//
1284// NOTE: if you want to use the "any other custom value" option (for XXX
1285// or YYY above) you MUST double escape the following characters:
1286// =[]{}\
1287// for example:
1288// - for profile type "=XXX=" use: '{Profile[type=\\=XXX\\=]}'
1289// - for profile type "\XXX\" use: '{Profile[type=\\\\XXX\\\\]}'
1290//
1291// NOTE: if you want to use curly brackets in the format string you must
1292// double escape it, e.g.: ['{Company}', '\\{{Department}\\}']
1293//
1294// The format string (for the value option) is an array to allow full
1295// customization of the interface. For example if:
1296// value: ['{LastName} {MiddleName} {FirstName}']
1297// and the person has no middle name, then the result in the column
1298// will be (without quotes):
1299// "Parker Peter" (note: two space characters)
1300// but if you use:
1301// value: ['{LastName}', ' {MiddleName}', ' {FirstName}']
1302// then the result will be (without quotes):
1303// "Parker Peter" (note: only one space character)
1304// The reason is that only those elements of the array are appended
1305// into the result where non-empty substitution was performed (so the
1306// ' {MiddleName}' element in this case is ignored, because the person
1307// in the example above has no /more precisely has empty/ middle name).
1308//
1309// Examples:
1310// To specify two columns (named "Company" and "Department / LastName"),
1311// where the first will display the company name, and the second will display
1312// department for company contacts (with "Dep -" prefix), and lastname for
1313// personal contacts (with "Name -" prefix) use:
1314// var globalCollectionDisplay=[
1315// {
1316// label: 'Company',
1317// value: ['{Company}']
1318// },
1319// {
1320// label: 'Department / LastName',
1321// value: {
1322// company: ['Dep - {Department}'],
1323// personal: ['Name - {LastName}']
1324// }
1325// }
1326// ];
1327// To specify 3 columns (named "Categories", "URL" and "IM"), where the first
1328// will display categories, second will display the third work URL, and third
1329// will display ICQ IM use:
1330// var globalCollectionDisplay=[
1331// {
1332// label: 'Categories',
1333// value: ['{Categories}']
1334// },
1335// {
1336// label: 'URL',
1337// value: ['{URL[type=WORK][:2]}']
1338// },
1339// {
1340// label: 'IM',
1341// value: ['{IM[service-type=ICQ]}']
1342// }
1343// ];
1344//
1345// Recommended settings if globalGroupContactsByCompanies
1346// is set to false:
1347// var globalCollectionDisplay=[
1348// {
1349// label: '{Name}',
1350// value: ['{LastName}', ' {MiddleName}', ' {FirstName}']
1351// },
1352// {
1353// label: '{Company} [{Department}]',
1354// value: ['{Company}', ' [{Department}]']
1355// },
1356// {
1357// label: '{JobTitle}',
1358// value: ['{JobTitle}']
1359// },
1360// {
1361// label: '{Email}',
1362// value: ['{Email[:0]}']
1363// },
1364// {
1365// label: '{Phone} 1',
1366// value: ['{Phone[:0]}']
1367// },
1368// {
1369// label: '{Phone} 2',
1370// value: ['{Phone[:1]}']
1371// },
1372// {
1373// label: '{NoteText}',
1374// value: ['{NoteText}']
1375// }
1376// ];
1377//
1378// Recommended settings if globalGroupContactsByCompanies
1379// is set to true:
1380// var globalCollectionDisplay=[
1381// {
1382// label: '{Name}',
1383// value: {
1384// personal: ['{LastName}', ' {MiddleName}', ' {FirstName}'],
1385// company: ['{Company}', ' [{Department}]']
1386// }
1387// },
1388// {
1389// label: '{JobTitle}',
1390// value: ['{JobTitle}']
1391// },
1392// {
1393// label: '{Email}',
1394// value: ['{Email[:0]}']
1395// },
1396// {
1397// label: '{Phone} 1',
1398// value: ['{Phone[:0]}']
1399// },
1400// {
1401// label: '{Phone} 2',
1402// value: ['{Phone[:1]}']
1403// },
1404// {
1405// label: '{NoteText}',
1406// value: ['{NoteText}']
1407// }
1408// ];
1409//
1410// NOTE: if left undefined, the recommended settings will be used.
1411
1412
1413// globalCollectionSort
1414// This options sets the ordering of contacts in the interface. In general
1415// contacts are ordered alphabetically by an internal "sort string" which
1416// is created for each contact. Here you can specify how this internal string
1417// is created. The value is a simple array holding only the values from the
1418// value property defined in the globalCollectionDisplay option.
1419// If undefined, the definition from globalCollectionDisplay is used.
1420// Example:
1421// var globalCollectionSort = [
1422// ['{LastName}'],
1423// ['{FirstName}'],
1424// ['{MiddleName}'],
1425// {
1426// company: ['{Categories}'],
1427// personal: ['{Company}']
1428// }
1429// ];
1430var globalCollectionSort=[
1431 ['{LastName}'],
1432 ['{FirstName}'],
1433 ['{MiddleName}']
1434];
1435
1436
1437// globalContactDataMinVisiblePercentage
1438// This option defines how the width for columns are computed. If you set
1439// it to 1 then 100% of all data in the column will be visible (the column
1440// width is determined by the longest string in the column). If you set it
1441// to 0.95 then 95% of data will fit into the column width, and the remaining
1442// 5% will be truncated (" ...").
1443// Example:
1444var globalContactDataMinVisiblePercentage=0.95;
1445
1446
diff --git a/virtual/modules/websites/tools/db/default.nix b/virtual/modules/websites/tools/db/default.nix
new file mode 100644
index 0000000..20f77c7
--- /dev/null
+++ b/virtual/modules/websites/tools/db/default.nix
@@ -0,0 +1,23 @@
1{ lib, pkgs, config, mylibs, ... }:
2let
3 adminer = pkgs.callPackage ../../commons/adminer.nix {};
4
5 cfg = config.services.myWebsites.tools.databases;
6in {
7 options.services.myWebsites.tools.databases = {
8 enable = lib.mkEnableOption "enable database's website";
9 };
10
11 config = lib.mkIf cfg.enable {
12 # FIXME: include it in vhostConf ?
13 security.acme.certs."eldiron".extraDomains."db-1.immae.eu" = null;
14
15 services.myWebsites.tools.modules = adminer.apache.modules;
16 services.myWebsites.tools.vhostConfs.db-1 = {
17 certName = "eldiron";
18 hosts = ["db-1.immae.eu" ];
19 root = null;
20 extraConfig = [ adminer.apache.vhostConf ];
21 };
22 };
23}
diff --git a/virtual/modules/websites/tools/git/default.nix b/virtual/modules/websites/tools/git/default.nix
new file mode 100644
index 0000000..0a63013
--- /dev/null
+++ b/virtual/modules/websites/tools/git/default.nix
@@ -0,0 +1,46 @@
1{ lib, pkgs, config, mylibs, ... }:
2let
3 mantisbt = pkgs.callPackage ./mantisbt/mantisbt.nix { inherit (mylibs) checkEnv fetchedGithub; };
4 gitweb = pkgs.callPackage ./gitweb/gitweb.nix { gitoliteDir = config.services.myGitolite.gitoliteDir; };
5
6 cfg = config.services.myWebsites.tools.git;
7in {
8 options.services.myWebsites.tools.git = {
9 enable = lib.mkEnableOption "enable git's website";
10 };
11
12 config = lib.mkIf cfg.enable {
13 # FIXME: include it in vhostConf ?
14 security.acme.certs."eldiron".extraDomains."git.immae.eu" = null;
15
16 nixpkgs.config.packageOverrides = oldpkgs: rec {
17 gitweb = oldpkgs.gitweb.overrideAttrs(old: {
18 installPhase = old.installPhase + ''
19 cp -r ${./gitweb/theme} $out/gitweb-theme;
20 '';
21 });
22 };
23
24 services.myWebsites.tools.modules =
25 gitweb.apache.modules ++
26 mantisbt.apache.modules;
27
28 services.myWebsites.tools.vhostConfs.git = {
29 certName = "eldiron";
30 hosts = ["git.immae.eu" ];
31 root = gitweb.webRoot;
32 extraConfig = [
33 gitweb.apache.vhostConf
34 mantisbt.apache.vhostConf
35 ''
36 RewriteEngine on
37 RewriteCond %{REQUEST_URI} ^/releases
38 RewriteRule /releases(.*) https://release.immae.eu$1 [P,L]
39 ''
40 ];
41 };
42 services.myPhpfpm.poolConfigs = {
43 mantisbt = mantisbt.phpFpm.pool;
44 };
45 };
46}
diff --git a/virtual/modules/gitweb/gitweb.nix b/virtual/modules/websites/tools/git/gitweb/gitweb.nix
index 7b4dcac..7b4dcac 100644
--- a/virtual/modules/gitweb/gitweb.nix
+++ b/virtual/modules/websites/tools/git/gitweb/gitweb.nix
diff --git a/virtual/modules/gitweb/theme/git-favicon.png b/virtual/modules/websites/tools/git/gitweb/theme/git-favicon.png
index 4fa44bb..4fa44bb 100644
--- a/virtual/modules/gitweb/theme/git-favicon.png
+++ b/virtual/modules/websites/tools/git/gitweb/theme/git-favicon.png
Binary files differ
diff --git a/virtual/modules/gitweb/theme/git-logo.png b/virtual/modules/websites/tools/git/gitweb/theme/git-logo.png
index fdaf7b7..fdaf7b7 100644
--- a/virtual/modules/gitweb/theme/git-logo.png
+++ b/virtual/modules/websites/tools/git/gitweb/theme/git-logo.png
Binary files differ
diff --git a/virtual/modules/gitweb/theme/gitweb.css b/virtual/modules/websites/tools/git/gitweb/theme/gitweb.css
index 83e0742..83e0742 100644
--- a/virtual/modules/gitweb/theme/gitweb.css
+++ b/virtual/modules/websites/tools/git/gitweb/theme/gitweb.css
diff --git a/virtual/modules/gitweb/theme/gitweb.js b/virtual/modules/websites/tools/git/gitweb/theme/gitweb.js
index 72f3cfa..72f3cfa 100644
--- a/virtual/modules/gitweb/theme/gitweb.js
+++ b/virtual/modules/websites/tools/git/gitweb/theme/gitweb.js
diff --git a/virtual/modules/websites/tools/git/mantisbt/mantisbt-plugin-slack.json b/virtual/modules/websites/tools/git/mantisbt/mantisbt-plugin-slack.json
new file mode 100644
index 0000000..54ea38b
--- /dev/null
+++ b/virtual/modules/websites/tools/git/mantisbt/mantisbt-plugin-slack.json
@@ -0,0 +1,15 @@
1{
2 "tag": "9286d2e-master",
3 "meta": {
4 "name": "mantisbt-plugin-slack",
5 "url": "https://github.com/mantisbt-plugins/Slack",
6 "branch": "master"
7 },
8 "github": {
9 "owner": "mantisbt-plugins",
10 "repo": "Slack",
11 "rev": "9286d2eeeb8a986ed949e378711fef5f0bf182dc",
12 "sha256": "0nn0v4jc967giilkzrppi5svd04m2hnals75xxp0iabcdjnih0mn",
13 "fetchSubmodules": true
14 }
15}
diff --git a/virtual/modules/websites/tools/git/mantisbt/mantisbt-plugin-source-integration.json b/virtual/modules/websites/tools/git/mantisbt/mantisbt-plugin-source-integration.json
new file mode 100644
index 0000000..e36a68c
--- /dev/null
+++ b/virtual/modules/websites/tools/git/mantisbt/mantisbt-plugin-source-integration.json
@@ -0,0 +1,15 @@
1{
2 "tag": "v2.1.5",
3 "meta": {
4 "name": "mantisbt-plugin-source-integration",
5 "url": "https://github.com/mantisbt-plugins/source-integration",
6 "branch": "refs/tags/v2.1.5"
7 },
8 "github": {
9 "owner": "mantisbt-plugins",
10 "repo": "source-integration",
11 "rev": "a48039a20abc50864e0e68c0c843b27058404386",
12 "sha256": "07g6q3hivmnd94r47pp0snk5bv4pa3piwclc9qhj612i4wnsazsk",
13 "fetchSubmodules": true
14 }
15}
diff --git a/virtual/modules/websites/tools/git/mantisbt/mantisbt-plugin-source-integration_Source.API.php.diff b/virtual/modules/websites/tools/git/mantisbt/mantisbt-plugin-source-integration_Source.API.php.diff
new file mode 100644
index 0000000..c355144
--- /dev/null
+++ b/virtual/modules/websites/tools/git/mantisbt/mantisbt-plugin-source-integration_Source.API.php.diff
@@ -0,0 +1,12 @@
1--- b/Source/Source.API.php 2017-09-18 00:50:32.000000000 +0200
2+++ a/Source/Source.API.php 2018-03-04 19:00:25.578889039 +0100
3@@ -452,6 +452,9 @@
4 # Allow other plugins to post-process commit data
5 event_signal( 'EVENT_SOURCE_COMMITS', array( $p_changesets ) );
6 event_signal( 'EVENT_SOURCE_FIXED', array( $t_fixed_bugs ) );
7+ foreach( $t_fixed_bugs as $t_bug_id => $t_changeset ) {
8+ event_signal( 'EVENT_BUG_ACTION', array('RESOLVE', $t_bug_id) );
9+ }
10 }
11
12 /**
diff --git a/virtual/modules/websites/tools/git/mantisbt/mantisbt.nix b/virtual/modules/websites/tools/git/mantisbt/mantisbt.nix
new file mode 100644
index 0000000..009c902
--- /dev/null
+++ b/virtual/modules/websites/tools/git/mantisbt/mantisbt.nix
@@ -0,0 +1,124 @@
1{ lib, checkEnv, writeText, stdenv, fetchurl, fetchedGithub }:
2let
3 # FIXME: check that source-integration and slack still work
4 mantisbt = let
5 plugins = {
6 slack = stdenv.mkDerivation (fetchedGithub ./mantisbt-plugin-slack.json // rec {
7 installPhase = ''
8 sed -i -e "s/return '@' . \\\$username;/return \\\$username;/" Slack.php
9 cp -a . $out
10 '';
11 });
12 source-integration = stdenv.mkDerivation (fetchedGithub ./mantisbt-plugin-source-integration.json // rec {
13 installPhase = ''
14 mkdir $out
15 patch -p1 < ${./mantisbt-plugin-source-integration_Source.API.php.diff}
16 cp -a Source* $out/
17 '';
18 });
19 };
20 in rec {
21 config =
22 assert checkEnv "NIXOPS_MANTISBT_DB_PASSWORD";
23 assert checkEnv "NIXOPS_MANTISBT_MASTER_SALT";
24 assert checkEnv "NIXOPS_MANTISBT_LDAP_PASSWORD";
25 writeText "config_inc.php" ''
26 <?php
27 $g_hostname = 'db-1.immae.eu';
28 $g_db_username = 'mantisbt';
29 $g_db_password = '${builtins.getEnv "NIXOPS_MANTISBT_DB_PASSWORD"}';
30 $g_database_name = 'mantisbt';
31 $g_db_type = 'pgsql';
32 $g_crypto_master_salt = '${builtins.getEnv "NIXOPS_MANTISBT_MASTER_SALT"}';
33 $g_allow_signup = OFF;
34 $g_allow_anonymous_login = ON;
35 $g_anonymous_account = 'anonymous';
36
37 $g_phpMailer_method = PHPMAILER_METHOD_SMTP;
38 $g_smtp_host = 'mail.immae.eu';
39 $g_smtp_username = ''';
40 $g_smtp_password = ''';
41 $g_webmaster_email = 'webmaster@immae.eu';
42 $g_from_email = 'noreply@immae.eu';
43 $g_return_path_email = 'webmaster@immae.eu';
44 $g_from_name = 'Mantis Bug Tracker at immae.eu';
45 $g_email_receive_own = OFF;
46 # --- LDAP ---
47 $g_login_method = LDAP;
48 $g_ldap_protocol_version = 3;
49 $g_ldap_server = 'ldaps://ldap.immae.eu:636';
50 $g_ldap_root_dn = 'ou=users,dc=immae,dc=eu';
51 $g_ldap_bind_dn = 'cn=mantisbt,ou=services,dc=immae,dc=eu';
52 $g_ldap_bind_passwd = '${builtins.getEnv "NIXOPS_MANTISBT_LDAP_PASSWORD"}';
53 $g_use_ldap_email = ON;
54 $g_use_ldap_realname = ON;
55 $g_ldap_uid_field = 'uid';
56 $g_ldap_realname_field = 'cn';
57 $g_ldap_organization = '(memberOf=cn=users,cn=mantisbt,ou=services,dc=immae,dc=eu)';
58 '';
59 webRoot = stdenv.mkDerivation rec {
60 name = "mantisbt-${version}";
61 version = "2.11.1";
62 src = fetchurl {
63 url = "https://downloads.sourceforge.net/project/mantisbt/mantis-stable/${version}/${name}.tar.gz";
64 sha256 = "0jnrqz6r2hf53v0k1lh3il7hlfiphn61r9wgg6mzyywkjxwq07md";
65 };
66 patches = [
67 ./patches/bug_report.php.diff
68 ./patches/bug_report_page.php.diff
69 ./patches/bugnote_add.php.diff
70 ./patches/bugnote_add_inc.php.diff
71 ];
72 installPhase = ''
73 cp -a . $out
74 ln -s ${config} $out/config/config_inc.php
75 ln -s ${plugins.slack} $out/plugins/Slack
76 ln -s ${plugins.source-integration}/Source* $out/plugins/
77 '';
78 };
79 apache = {
80 user = "wwwrun";
81 group = "wwwrun";
82 modules = [ "proxy_fcgi" ];
83 vhostConf = ''
84 Alias /mantisbt "${webRoot}"
85 <Directory "${webRoot}">
86 DirectoryIndex index.php
87 <FilesMatch "\.php$">
88 SetHandler "proxy:unix:${phpFpm.socket}|fcgi://localhost"
89 </FilesMatch>
90
91 AllowOverride All
92 Options FollowSymlinks
93 Require all granted
94 </Directory>
95 <Directory "${webRoot}/admin">
96 #Reenable during upgrade
97 Require all denied
98 </Directory>
99 '';
100 };
101 phpFpm = rec {
102 basedir = builtins.concatStringsSep ":" (
103 [ webRoot config ]
104 ++ lib.attrsets.mapAttrsToList (name: value: value) plugins);
105 socket = "/var/run/phpfpm/mantisbt.sock";
106 pool = ''
107 listen = ${socket}
108 user = ${apache.user}
109 group = ${apache.group}
110 listen.owner = ${apache.user}
111 listen.group = ${apache.group}
112 pm = ondemand
113 pm.max_children = 60
114 pm.process_idle_timeout = 60
115
116 php_admin_value[upload_max_filesize] = 5000000
117
118 php_admin_value[open_basedir] = "${basedir}:/tmp"
119 php_admin_value[session.save_path] = "/var/lib/php/sessions/mantisbt"
120 '';
121 };
122 };
123in
124 mantisbt
diff --git a/virtual/modules/websites/tools/git/mantisbt/patches/bug_report.php.diff b/virtual/modules/websites/tools/git/mantisbt/patches/bug_report.php.diff
new file mode 100644
index 0000000..a520043
--- /dev/null
+++ b/virtual/modules/websites/tools/git/mantisbt/patches/bug_report.php.diff
@@ -0,0 +1,20 @@
1--- a/bug_report.php 2018-02-10 21:29:27.000000000 +0100
2+++ b/bug_report.php 2018-03-03 15:04:19.622499678 +0100
3@@ -149,6 +149,17 @@
4 access_ensure_project_level( config_get( 'update_bug_assign_threshold' ) );
5 }
6
7+# begin captcha check for anon user
8+if ( current_user_is_anonymous() && get_gd_version() > 0 ) {
9+ $f_captcha = gpc_get_string( 'captcha', '' );
10+ $f_captcha = utf8_strtolower( trim( $f_captcha ) );
11+
12+ $t_securimage = new Securimage();
13+ if( $t_securimage->check( $f_captcha ) == false ) {
14+ trigger_error( ERROR_SIGNUP_NOT_MATCHING_CAPTCHA, ERROR );
15+ }
16+}
17+
18 # if a profile was selected then let's use that information
19 if( 0 != $t_bug_data->profile_id ) {
20 if( profile_is_global( $t_bug_data->profile_id ) ) {
diff --git a/virtual/modules/websites/tools/git/mantisbt/patches/bug_report_page.php.diff b/virtual/modules/websites/tools/git/mantisbt/patches/bug_report_page.php.diff
new file mode 100644
index 0000000..80dea91
--- /dev/null
+++ b/virtual/modules/websites/tools/git/mantisbt/patches/bug_report_page.php.diff
@@ -0,0 +1,53 @@
1--- a/bug_report_page.php 2018-02-10 21:29:27.000000000 +0100
2+++ b/bug_report_page.php 2018-03-03 15:04:19.622499678 +0100
3@@ -708,7 +708,50 @@
4 <span class="lbl padding-6"><?php echo lang_get( 'check_report_more_bugs' ) ?></span>
5 </label>
6 </td>
7 </tr>
8+<?php
9+ # captcha image requires GD library and related option to ON
10+ if( current_user_is_anonymous() && get_gd_version() > 0 ) {
11+ $t_securimage_path = 'vendor/dapphp/securimage';
12+ $t_securimage_show = $t_securimage_path . '/securimage_show.php';
13+ $t_securimage_play = $t_securimage_path . '/securimage_play.swf?'
14+ . http_build_query( array(
15+ 'audio_file' => $t_securimage_path . '/securimage_play.php',
16+ 'bgColor1=' => '#fff',
17+ 'bgColor2=' => '#fff',
18+ 'iconColor=' => '#777',
19+ 'borderWidth=' => 1,
20+ 'borderColor=' => '#000',
21+ ) );
22+?>
23+ <tr>
24+ <th class="category">CAPTCHA</th>
25+ <td>
26+
27+ <label for="captcha-field" class="block clearfix">
28+ <strong><?php echo lang_get( 'signup_captcha_request_label' ); ?></strong>
29+ </label>
30+ <span id="captcha-input" class="input">
31+ <?php print_captcha_input( 'captcha' ); ?>
32+
33+ <span id="captcha-image" class="captcha-image" style="padding-right:3px;">
34+ <img src="<?php echo $t_securimage_show; ?>" alt="visual captcha" />
35+ <ul id="captcha-refresh"><li><a href="#"><?php
36+ echo lang_get( 'signup_captcha_refresh' );
37+ ?></a></li></ul>
38+ </span>
39+
40+ <object type="application/x-shockwave-flash" width="19" height="19"
41+ data="<?php echo $t_securimage_play; ?>">
42+ <param name="movie" value="<?php echo $t_securimage_play; ?>" />
43+ </object>
44+ </span>
45+ </td>
46+ </tr>
47+<?php
48+ }
49+?>
50+
51 </table>
52 </div>
53 </div>
diff --git a/virtual/modules/websites/tools/git/mantisbt/patches/bugnote_add.php.diff b/virtual/modules/websites/tools/git/mantisbt/patches/bugnote_add.php.diff
new file mode 100644
index 0000000..4509f0a
--- /dev/null
+++ b/virtual/modules/websites/tools/git/mantisbt/patches/bugnote_add.php.diff
@@ -0,0 +1,20 @@
1--- a/bugnote_add.php 2018-02-10 21:29:27.000000000 +0100
2+++ b/bugnote_add.php 2018-03-03 15:13:12.439919511 +0100
3@@ -44,6 +44,17 @@
4
5 $t_query = array( 'issue_id' => $f_bug_id );
6
7+# begin captcha check for anon user
8+if ( current_user_is_anonymous() && get_gd_version() > 0 ) {
9+ $f_captcha = gpc_get_string( 'captcha', '' );
10+ $f_captcha = utf8_strtolower( trim( $f_captcha ) );
11+
12+ $t_securimage = new Securimage();
13+ if( $t_securimage->check( $f_captcha ) == false ) {
14+ trigger_error( ERROR_SIGNUP_NOT_MATCHING_CAPTCHA, ERROR );
15+ }
16+}
17+
18 if( count( $f_files ) > 0 && is_blank( $f_text ) && helper_duration_to_minutes( $f_duration ) == 0 ) {
19 $t_payload = array(
20 'files' => helper_array_transpose( $f_files )
diff --git a/virtual/modules/websites/tools/git/mantisbt/patches/bugnote_add_inc.php.diff b/virtual/modules/websites/tools/git/mantisbt/patches/bugnote_add_inc.php.diff
new file mode 100644
index 0000000..a8589c7
--- /dev/null
+++ b/virtual/modules/websites/tools/git/mantisbt/patches/bugnote_add_inc.php.diff
@@ -0,0 +1,52 @@
1--- a/bugnote_add_inc.php 2018-02-10 21:29:27.000000000 +0100
2+++ b/bugnote_add_inc.php 2018-03-03 15:14:27.332428557 +0100
3@@ -119,6 +119,49 @@
4 <textarea name="bugnote_text" id="bugnote_text" class="<?php echo $t_bugnote_class ?>" rows="7"></textarea>
5 </td>
6 </tr>
7+<?php
8+ # captcha image requires GD library and related option to ON
9+ if( current_user_is_anonymous() && get_gd_version() > 0 ) {
10+ $t_securimage_path = 'vendor/dapphp/securimage';
11+ $t_securimage_show = $t_securimage_path . '/securimage_show.php';
12+ $t_securimage_play = $t_securimage_path . '/securimage_play.swf?'
13+ . http_build_query( array(
14+ 'audio_file' => $t_securimage_path . '/securimage_play.php',
15+ 'bgColor1=' => '#fff',
16+ 'bgColor2=' => '#fff',
17+ 'iconColor=' => '#777',
18+ 'borderWidth=' => 1,
19+ 'borderColor=' => '#000',
20+ ) );
21+?>
22+ <tr>
23+ <th class="category">CAPTCHA</th>
24+ <td>
25+
26+ <label for="captcha-field" class="block clearfix">
27+ <strong><?php echo lang_get( 'signup_captcha_request_label' ); ?></strong>
28+ </label>
29+ <span id="captcha-input" class="input">
30+ <?php print_captcha_input( 'captcha' ); ?>
31+
32+ <span id="captcha-image" class="captcha-image" style="padding-right:3px;">
33+ <img src="<?php echo $t_securimage_show; ?>" alt="visual captcha" />
34+ <ul id="captcha-refresh"><li><a href="#"><?php
35+ echo lang_get( 'signup_captcha_refresh' );
36+ ?></a></li></ul>
37+ </span>
38+
39+ <object type="application/x-shockwave-flash" width="19" height="19"
40+ data="<?php echo $t_securimage_play; ?>">
41+ <param name="movie" value="<?php echo $t_securimage_play; ?>" />
42+ </object>
43+ </span>
44+ </td>
45+ </tr>
46+<?php
47+ }
48+?>
49+
50
51 <?php
52 if( config_get( 'time_tracking_enabled' ) ) {
diff --git a/virtual/modules/websites/tools/tools/default.nix b/virtual/modules/websites/tools/tools/default.nix
new file mode 100644
index 0000000..f29ac11
--- /dev/null
+++ b/virtual/modules/websites/tools/tools/default.nix
@@ -0,0 +1,65 @@
1{ lib, pkgs, config, mylibs, ... }:
2let
3 adminer = pkgs.callPackage ../../commons/adminer.nix {};
4 ympd = pkgs.callPackage ./ympd.nix {};
5 ttrss = pkgs.callPackage ./ttrss.nix { inherit (mylibs) checkEnv fetchedGithub fetchedGit; };
6 roundcubemail = pkgs.callPackage ./roundcubemail.nix { inherit (mylibs) checkEnv; };
7
8 cfg = config.services.myWebsites.tools.tools;
9in {
10 options.services.myWebsites.tools.tools = {
11 enable = lib.mkEnableOption "enable tools website";
12 };
13
14 config = lib.mkIf cfg.enable {
15 security.acme.certs."eldiron".extraDomains."tools.immae.eu" = null;
16
17 services.myWebsites.tools.modules =
18 adminer.apache.modules
19 ++ ympd.apache.modules
20 ++ ttrss.apache.modules
21 ++ roundcubemail.apache.modules;
22
23 services.ympd = ympd.config // { enable = false; };
24
25 services.myWebsites.tools.vhostConfs.tools = {
26 certName = "eldiron";
27 hosts = ["tools.immae.eu" ];
28 root = null;
29 extraConfig = [
30 adminer.apache.vhostConf
31 ympd.apache.vhostConf
32 ttrss.apache.vhostConf
33 roundcubemail.apache.vhostConf
34 ];
35 };
36
37 services.myPhpfpm.poolConfigs = {
38 adminer = adminer.phpFpm.pool;
39 ttrss = ttrss.phpFpm.pool;
40 roundcubemail = roundcubemail.phpFpm.pool;
41 };
42
43 system.activationScripts = {
44 ttrss = ttrss.activationScript;
45 roundcubemail = roundcubemail.activationScript;
46 };
47
48 systemd.services.tt-rss = {
49 description = "Tiny Tiny RSS feeds update daemon";
50 serviceConfig = {
51 User = "wwwrun";
52 ExecStart = "${pkgs.php}/bin/php ${ttrss.webRoot}/update.php --daemon";
53 StandardOutput = "syslog";
54 StandardError = "syslog";
55 PermissionsStartOnly = true;
56 };
57
58 wantedBy = [ "multi-user.target" ];
59 requires = ["postgresql.service"];
60 after = ["network.target" "postgresql.service"];
61 };
62
63 };
64}
65
diff --git a/virtual/modules/websites/tools/tools/roundcubemail.nix b/virtual/modules/websites/tools/tools/roundcubemail.nix
new file mode 100644
index 0000000..1aa2d87
--- /dev/null
+++ b/virtual/modules/websites/tools/tools/roundcubemail.nix
@@ -0,0 +1,110 @@
1{ lib, checkEnv, writeText, stdenv, fetchurl }:
2let
3 roundcubemail = let
4 plugins = {};
5 in rec {
6 varDir = "/var/lib/roundcubemail";
7 # FIXME: initial sync
8 activationScript = {
9 deps = [ "wrappers" ];
10 text = ''
11 install -m 0755 -o ${apache.user} -g ${apache.group} -d ${varDir} \
12 ${varDir}/cache
13 install -m 0750 -o ${apache.user} -g ${apache.group} -d ${varDir}/phpSessions
14 '';
15 };
16 config =
17 # FIXME: LOG_DESTINATION syslog?
18 assert checkEnv "NIXOPS_ROUNDCUBEMAIL_PSQL_URL";
19 assert checkEnv "NIXOPS_ROUNDCUBEMAIL_SECRET";
20 writeText "config.php" ''
21 <?php
22 $config['db_dsnw'] = '${builtins.getEnv "NIXOPS_ROUNDCUBEMAIL_PSQL_URL"}';
23 $config['default_host'] = 'ssl://mail.immae.eu';
24 $config['imap_conn_options'] = array("ssl" => array("verify_peer" => false));
25 $config['smtp_server'] = 'tls://mail.immae.eu';
26
27 $config['imap_cache'] = 'db';
28 $config['messages_cache'] = 'db';
29
30 $config['support_url'] = ''';
31
32 $config['des_key'] = '${builtins.getEnv "NIXOPS_ROUNDCUBEMAIL_SECRET"}';
33
34 $config['plugins'] = array();
35
36 $config['language'] = 'fr_FR';
37
38 $config['drafts_mbox'] = 'Mail/Drafts';
39 $config['junk_mbox'] = 'Mail/Spam';
40 $config['sent_mbox'] = 'Mail/sent';
41 $config['trash_mbox'] = ''';
42 $config['default_folders'] = array('INBOX', 'Mail/Drafts', 'Mail/sent', 'Mail/Spam', ''');
43 $config['draft_autosave'] = 60;
44 $config['enable_installer'] = false;
45 $config['log_driver'] = 'stdout';
46 $config['temp_dir'] = '${varDir}/cache';
47 $config['debug_level'] = 1;
48 '';
49 webRoot = stdenv.mkDerivation rec {
50 version = "1.3.8";
51 name = "roundcubemail-${version}";
52 src= fetchurl {
53 url = "https://github.com/roundcube/roundcubemail/releases/download/${version}/${name}-complete.tar.gz";
54 sha256 = "018djad7ygfl9c9f2l2j42qkg31ml3hs2f01f0dk361zckwk77n4";
55 };
56 buildPhase = ''
57 sed -i \
58 -e "s|RCUBE_INSTALL_PATH . 'temp.*|'${varDir}/cache';|" \
59 config/defaults.inc.php
60 '';
61 installPhase = ''
62 cp -a . $out
63 ln -s ${config} $out/config/config.inc.php
64 ${builtins.concatStringsSep "\n" (
65 lib.attrsets.mapAttrsToList (name: value: "ln -sf ${value} $out/plugins/${name}") plugins
66 )}
67 '';
68 };
69 apache = {
70 user = "wwwrun";
71 group = "wwwrun";
72 modules = [ "proxy_fcgi" ];
73 vhostConf = ''
74 Alias /roundcube "${webRoot}"
75 <Directory "${webRoot}">
76 DirectoryIndex index.php
77 AllowOverride All
78 Options FollowSymlinks
79 Require all granted
80
81 <FilesMatch "\.php$">
82 SetHandler "proxy:unix:${phpFpm.socket}|fcgi://localhost"
83 </FilesMatch>
84 </Directory>
85 '';
86 };
87 phpFpm = rec {
88 basedir = builtins.concatStringsSep ":" (
89 [ webRoot config varDir ]
90 ++ lib.attrsets.mapAttrsToList (name: value: value) plugins);
91 socket = "/var/run/phpfpm/roundcubemail.sock";
92 pool = ''
93 listen = ${socket}
94 user = ${apache.user}
95 group = ${apache.group}
96 listen.owner = ${apache.user}
97 listen.group = ${apache.group}
98 pm = ondemand
99 pm.max_children = 60
100 pm.process_idle_timeout = 60
101
102 ; Needed to avoid clashes in browser cookies (same domain)
103 php_value[session.name] = RoundcubemailPHPSESSID
104 php_admin_value[open_basedir] = "${basedir}:/tmp"
105 php_admin_value[session.save_path] = "${varDir}/phpSessions"
106 '';
107 };
108 };
109in
110 roundcubemail
diff --git a/virtual/modules/websites/tools/tools/tt-rss.json b/virtual/modules/websites/tools/tools/tt-rss.json
new file mode 100644
index 0000000..e2731b0
--- /dev/null
+++ b/virtual/modules/websites/tools/tools/tt-rss.json
@@ -0,0 +1,14 @@
1{
2 "tag": "986ca25-master",
3 "meta": {
4 "name": "tt-rss",
5 "url": "https://git.tt-rss.org/fox/tt-rss.git",
6 "branch": "master"
7 },
8 "git": {
9 "url": "https://git.tt-rss.org/fox/tt-rss.git",
10 "rev": "986ca251f995f7754a0470d3e0c44538a545081f",
11 "sha256": "0xkafkh7l9zazm5d6snlq03kdfxfhkb4c8fdsb32wn8b9bhdzf5s",
12 "fetchSubmodules": true
13 }
14}
diff --git a/virtual/modules/websites/tools/tools/ttrss-af-feedmod_type_replace.patch b/virtual/modules/websites/tools/tools/ttrss-af-feedmod_type_replace.patch
new file mode 100644
index 0000000..d622577
--- /dev/null
+++ b/virtual/modules/websites/tools/tools/ttrss-af-feedmod_type_replace.patch
@@ -0,0 +1,12 @@
1--- a/init.php 2014-06-16 14:21:06.995480038 +0200
2+++ b/init.php 2014-06-16 14:22:00.151027654 +0200
3@@ -147,6 +147,9 @@
4 }
5 }
6 break;
7+ case 'replace':
8+ $article['content'] = preg_replace("/".$config['pattern']."/",$config['replacement'],$article['content']);
9+ break;
10
11 default:
12 // unknown type or invalid config
diff --git a/virtual/modules/websites/tools/tools/ttrss-af_feedmod.json b/virtual/modules/websites/tools/tools/ttrss-af_feedmod.json
new file mode 100644
index 0000000..e57fcce
--- /dev/null
+++ b/virtual/modules/websites/tools/tools/ttrss-af_feedmod.json
@@ -0,0 +1,15 @@
1{
2 "tag": "0ea2092-master",
3 "meta": {
4 "name": "ttrss-af_feedmod",
5 "url": "https://github.com/mbirth/ttrss_plugin-af_feedmod",
6 "branch": "master"
7 },
8 "github": {
9 "owner": "mbirth",
10 "repo": "ttrss_plugin-af_feedmod",
11 "rev": "0ea2092dd34067ecd898802cfca3570023d1ecfe",
12 "sha256": "02ibf47zcrsc2rr45wsix8gxyyf371davj8n8i0gj1zdq95klvnv",
13 "fetchSubmodules": true
14 }
15}
diff --git a/virtual/modules/websites/tools/tools/ttrss-auth-ldap.json b/virtual/modules/websites/tools/tools/ttrss-auth-ldap.json
new file mode 100644
index 0000000..c8aaab5
--- /dev/null
+++ b/virtual/modules/websites/tools/tools/ttrss-auth-ldap.json
@@ -0,0 +1,15 @@
1{
2 "tag": "4d751b0-master",
3 "meta": {
4 "name": "ttrss-auth-ldap",
5 "url": "https://github.com/hydrian/TTRSS-Auth-LDAP",
6 "branch": "master"
7 },
8 "github": {
9 "owner": "hydrian",
10 "repo": "TTRSS-Auth-LDAP",
11 "rev": "4d751b095c29a8dbe2dc7bb07777742956136e94",
12 "sha256": "0b9fl86acrzpcv41r7pj3bl8b3n72hpkdywzx9zjyfqv5pskxyim",
13 "fetchSubmodules": true
14 }
15}
diff --git a/virtual/modules/websites/tools/tools/ttrss-feediron.json b/virtual/modules/websites/tools/tools/ttrss-feediron.json
new file mode 100644
index 0000000..5dbec92
--- /dev/null
+++ b/virtual/modules/websites/tools/tools/ttrss-feediron.json
@@ -0,0 +1,15 @@
1{
2 "tag": "407168c-master",
3 "meta": {
4 "name": "ttrss-feediron",
5 "url": "https://github.com/m42e/ttrss_plugin-feediron",
6 "branch": "master"
7 },
8 "github": {
9 "owner": "m42e",
10 "repo": "ttrss_plugin-feediron",
11 "rev": "407168c628880b5ced572cc549db6d50e866d3c8",
12 "sha256": "17b95ifpcph6m03hjd1mhi8gi1hw9yd3fnffmw66fqr5c9l3zd9r",
13 "fetchSubmodules": true
14 }
15}
diff --git a/virtual/modules/websites/tools/tools/ttrss-feediron_json_reformat.patch b/virtual/modules/websites/tools/tools/ttrss-feediron_json_reformat.patch
new file mode 100644
index 0000000..e1c44d9
--- /dev/null
+++ b/virtual/modules/websites/tools/tools/ttrss-feediron_json_reformat.patch
@@ -0,0 +1,18 @@
1diff --git a/init.php b/init.php
2index 3c0f2f9..1aad146 100644
3--- a/init.php
4+++ b/init.php
5@@ -600,10 +600,11 @@ class Feediron extends Plugin implements IHandler
6 return false;
7 }
8
9- $this->host->set($this, 'json_conf', Feediron_Json::format($json_conf));
10+ $new_conf = json_encode(json_decode($json_conf), JSON_PRETTY_PRINT);
11+ $this->host->set($this, 'json_conf', $new_conf);
12 $json_reply['success'] = true;
13 $json_reply['message'] = __('Configuration saved.');
14- $json_reply['json_conf'] = Feediron_Json::format($json_conf);
15+ $json_reply['json_conf'] = $new_conf;
16 echo json_encode($json_reply);
17 }
18
diff --git a/virtual/modules/websites/tools/tools/ttrss-ff_instagram.json b/virtual/modules/websites/tools/tools/ttrss-ff_instagram.json
new file mode 100644
index 0000000..1f241b9
--- /dev/null
+++ b/virtual/modules/websites/tools/tools/ttrss-ff_instagram.json
@@ -0,0 +1,15 @@
1{
2 "tag": "0366ffb-master",
3 "meta": {
4 "name": "ttrss-ff_instagram",
5 "url": "https://github.com/wltb/ff_instagram",
6 "branch": "master"
7 },
8 "github": {
9 "owner": "wltb",
10 "repo": "ff_instagram",
11 "rev": "0366ffb18c4d490c8fbfba2f5f3367a5af23cfe8",
12 "sha256": "0vvzl6wi6jmrqknsfddvckjgsgfizz1d923d1nyrpzjfn6bda1vk",
13 "fetchSubmodules": true
14 }
15}
diff --git a/virtual/modules/websites/tools/tools/ttrss-tumblr_gdpr_ua.json b/virtual/modules/websites/tools/tools/ttrss-tumblr_gdpr_ua.json
new file mode 100644
index 0000000..eafbcfe
--- /dev/null
+++ b/virtual/modules/websites/tools/tools/ttrss-tumblr_gdpr_ua.json
@@ -0,0 +1,15 @@
1{
2 "tag": "287c584-master",
3 "meta": {
4 "name": "ttrss-tumblr_gdpr_ua",
5 "url": "https://github.com/hkockerbeck/ttrss-tumblr-gdpr-ua",
6 "branch": "master"
7 },
8 "github": {
9 "owner": "hkockerbeck",
10 "repo": "ttrss-tumblr-gdpr-ua",
11 "rev": "287c584e68845d524f920156bff0b2eaa6f65117",
12 "sha256": "1fviawgcclqky4k4xv1sqzvpb8i74w9f0pclm09m78s8l85wh9py",
13 "fetchSubmodules": true
14 }
15}
diff --git a/virtual/modules/websites/tools/tools/ttrss.nix b/virtual/modules/websites/tools/tools/ttrss.nix
new file mode 100644
index 0000000..f7b0f61
--- /dev/null
+++ b/virtual/modules/websites/tools/tools/ttrss.nix
@@ -0,0 +1,182 @@
1{ lib, php, checkEnv, writeText, stdenv, fetchedGit, fetchedGithub }:
2let
3 ttrss = let
4 plugins = {
5 auth_ldap = stdenv.mkDerivation (fetchedGithub ./ttrss-auth-ldap.json // rec {
6 installPhase = ''
7 mkdir $out
8 cp plugins/auth_ldap/init.php $out
9 '';
10 });
11 af_feedmod = stdenv.mkDerivation (fetchedGithub ./ttrss-af_feedmod.json // rec {
12 patches = [ ./ttrss-af-feedmod_type_replace.patch ];
13 installPhase = ''
14 mkdir $out
15 cp init.php $out
16 '';
17 });
18 feediron = stdenv.mkDerivation (fetchedGithub ./ttrss-feediron.json // rec {
19 patches = [ ./ttrss-feediron_json_reformat.patch ];
20 installPhase = ''
21 mkdir $out
22 cp -a . $out
23 '';
24 });
25 ff_instagram = stdenv.mkDerivation (fetchedGithub ./ttrss-ff_instagram.json // rec {
26 installPhase = ''
27 mkdir $out
28 cp -a . $out
29 '';
30 });
31 tumblr_gdpr_ua = stdenv.mkDerivation (fetchedGithub ./ttrss-tumblr_gdpr_ua.json // rec {
32 installPhase = ''
33 mkdir $out
34 cp -a . $out
35 '';
36 });
37 };
38 in rec {
39 varDir = "/var/lib/ttrss";
40 # FIXME: initial sync
41 activationScript = {
42 deps = [ "wrappers" ];
43 text = ''
44 install -m 0755 -o ${apache.user} -g ${apache.group} -d ${varDir} \
45 ${varDir}/lock ${varDir}/cache ${varDir}/feed-icons
46 install -m 0755 -o ${apache.user} -g ${apache.group} -d ${varDir}/cache/export/ \
47 ${varDir}/cache/feeds/ \
48 ${varDir}/cache/images/ \
49 ${varDir}/cache/js/ \
50 ${varDir}/cache/simplepie/ \
51 ${varDir}/cache/upload/
52 touch ${varDir}/feed-icons/index.html
53 install -m 0750 -o ${apache.user} -g ${apache.group} -d ${varDir}/phpSessions
54 '';
55 };
56 config =
57 # FIXME: LOG_DESTINATION syslog?
58 assert checkEnv "NIXOPS_TTRSS_DB_PASSWORD";
59 assert checkEnv "NIXOPS_TTRSS_LDAP_PASSWORD";
60 writeText "config.php" ''
61 <?php
62
63 define('PHP_EXECUTABLE', '${php}/bin/php');
64
65 define('LOCK_DIRECTORY', 'lock');
66 define('CACHE_DIR', 'cache');
67 define('ICONS_DIR', 'feed-icons');
68 define('ICONS_URL', 'feed-icons');
69 define('SELF_URL_PATH', 'https://tools.immae.eu/ttrss/');
70
71 define('MYSQL_CHARSET', 'UTF8');
72
73 define('DB_TYPE', 'pgsql');
74 define('DB_HOST', 'db-1.immae.eu');
75 define('DB_USER', 'ttrss');
76 define('DB_NAME', 'ttrss');
77 define('DB_PASS', '${builtins.getEnv "NIXOPS_TTRSS_DB_PASSWORD"}');
78 define('DB_PORT', '5432');
79
80 define('AUTH_AUTO_CREATE', true);
81 define('AUTH_AUTO_LOGIN', true);
82
83 define('SINGLE_USER_MODE', false);
84
85 define('SIMPLE_UPDATE_MODE', false);
86 define('CHECK_FOR_UPDATES', true);
87
88 define('FORCE_ARTICLE_PURGE', 0);
89 define('SESSION_COOKIE_LIFETIME', 60*60*24*120);
90 define('ENABLE_GZIP_OUTPUT', false);
91
92 define('PLUGINS', 'auth_ldap, note, instances');
93
94 define('LOG_DESTINATION', ''');
95 define('CONFIG_VERSION', 26);
96
97
98 define('SPHINX_SERVER', 'localhost:9312');
99 define('SPHINX_INDEX', 'ttrss, delta');
100
101 define('ENABLE_REGISTRATION', false);
102 define('REG_NOTIFY_ADDRESS', 'outils@immae.eu');
103 define('REG_MAX_USERS', 10);
104
105 define('SMTP_SERVER', 'mail.immae.eu:25');
106 define('SMTP_LOGIN', ''');
107 define('SMTP_PASSWORD', ''');
108 define('SMTP_SECURE', 'tls');
109
110 define('SMTP_FROM_NAME', 'Tiny Tiny RSS');
111 define('SMTP_FROM_ADDRESS', 'outils@immae.eu');
112 define('DIGEST_SUBJECT', '[tt-rss] New headlines for last 24 hours');
113
114 define('LDAP_AUTH_SERVER_URI', 'ldap://ldap.immae.eu:389/');
115 define('LDAP_AUTH_USETLS', TRUE);
116 define('LDAP_AUTH_ALLOW_UNTRUSTED_CERT', TRUE);
117 define('LDAP_AUTH_BASEDN', 'dc=immae,dc=eu');
118 define('LDAP_AUTH_ANONYMOUSBEFOREBIND', FALSE);
119 define('LDAP_AUTH_SEARCHFILTER', '(&(memberOf=cn=users,cn=ttrss,ou=services,dc=immae,dc=eu)(|(cn=???)(uid=???)(&(uid:dn:=???)(ou=ttrss))))');
120
121 define('LDAP_AUTH_BINDDN', 'cn=ttrss,ou=services,dc=immae,dc=eu');
122 define('LDAP_AUTH_BINDPW', '${builtins.getEnv "NIXOPS_TTRSS_LDAP_PASSWORD"}');
123 define('LDAP_AUTH_LOGIN_ATTRIB', 'immaeTtrssLogin');
124
125 define('LDAP_AUTH_LOG_ATTEMPTS', FALSE);
126 define('LDAP_AUTH_DEBUG', FALSE);
127 '';
128 webRoot = stdenv.mkDerivation (fetchedGit ./tt-rss.json // rec {
129 buildPhase = ''
130 rm -rf lock feed-icons cache
131 ln -sf ../../../../../${varDir}/{lock,feed-icons,cache} .
132 '';
133 installPhase = ''
134 cp -a . $out
135 ln -s ${config} $out/config.php
136 ${builtins.concatStringsSep "\n" (
137 lib.attrsets.mapAttrsToList (name: value: "ln -sf ${value} $out/plugins/${name}") plugins
138 )}
139 '';
140 });
141 apache = {
142 user = "wwwrun";
143 group = "wwwrun";
144 modules = [ "proxy_fcgi" ];
145 vhostConf = ''
146 Alias /ttrss "${webRoot}"
147 <Directory "${webRoot}">
148 DirectoryIndex index.php
149 <FilesMatch "\.php$">
150 SetHandler "proxy:unix:${phpFpm.socket}|fcgi://localhost"
151 </FilesMatch>
152
153 AllowOverride All
154 Options FollowSymlinks
155 Require all granted
156 </Directory>
157 '';
158 };
159 phpFpm = rec {
160 basedir = builtins.concatStringsSep ":" (
161 [ webRoot config varDir ]
162 ++ lib.attrsets.mapAttrsToList (name: value: value) plugins);
163 socket = "/var/run/phpfpm/ttrss.sock";
164 pool = ''
165 listen = ${socket}
166 user = ${apache.user}
167 group = ${apache.group}
168 listen.owner = ${apache.user}
169 listen.group = ${apache.group}
170 pm = ondemand
171 pm.max_children = 60
172 pm.process_idle_timeout = 60
173
174 ; Needed to avoid clashes in browser cookies (same domain)
175 php_value[session.name] = TtrssPHPSESSID
176 php_admin_value[open_basedir] = "${basedir}:/tmp"
177 php_admin_value[session.save_path] = "${varDir}/phpSessions"
178 '';
179 };
180 };
181in
182 ttrss
diff --git a/virtual/modules/websites/tools/tools/ympd.nix b/virtual/modules/websites/tools/tools/ympd.nix
new file mode 100644
index 0000000..74bf2e5
--- /dev/null
+++ b/virtual/modules/websites/tools/tools/ympd.nix
@@ -0,0 +1,35 @@
1{}:
2let
3 ympd = rec {
4 config = {
5 webPort = "localhost:18001";
6 mpd = {
7 host = "malige.home.immae.eu";
8 port = 6600;
9 };
10 };
11 apache = {
12 modules = [
13 "proxy_wstunnel"
14 ];
15 vhostConf = ''
16 <LocationMatch "^/mpd">
17 Use LDAPConnect
18 Require ldap-group cn=users,cn=mpd,ou=services,dc=immae,dc=eu
19 Require local
20 </LocationMatch>
21
22 RedirectMatch permanent "^/mpd$" "/mpd/"
23 <Location "/mpd/">
24 ProxyPass http://${config.webPort}/
25 ProxyPassReverse http://${config.webPort}/
26 ProxyPreserveHost on
27 </Location>
28 <Location "/mpd/ws">
29 ProxyPass ws://${config.webPort}/ws
30 </Location>
31 '';
32 };
33 };
34in
35 ympd