--- /dev/null
+PATH
+ remote: .
+ specs:
+ taskwarrior-web (1.1.12)
+ activesupport (~> 3)
+ json (~> 1.8)
+ parseconfig
+ rack-flash3
+ rinku
+ sinatra
+ sinatra-simple-navigation
+ vegas
+ versionomy
+
+GEM
+ remote: http://rubygems.org/
+ specs:
+ activesupport (3.2.22.5)
+ i18n (~> 0.6, >= 0.6.4)
+ multi_json (~> 1.0)
+ blockenspiel (0.5.0)
+ coderay (1.1.2)
+ concurrent-ruby (1.1.4)
+ daemons (1.3.1)
+ diff-lcs (1.3)
+ docile (1.3.1)
+ eventmachine (1.2.7)
+ ffi (1.10.0)
+ formatador (0.2.5)
+ growl (1.0.3)
+ guard (2.15.0)
+ formatador (>= 0.2.4)
+ listen (>= 2.7, < 4.0)
+ lumberjack (>= 1.0.12, < 2.0)
+ nenv (~> 0.1)
+ notiffany (~> 0.0)
+ pry (>= 0.9.12)
+ shellany (~> 0.0)
+ thor (>= 0.18.1)
+ guard-bundler (2.2.1)
+ bundler (>= 1.3.0, < 3)
+ guard (~> 2.2)
+ guard-compat (~> 1.1)
+ guard-compat (1.2.1)
+ guard-rspec (4.7.3)
+ guard (~> 2.1)
+ guard-compat (~> 1.1)
+ rspec (>= 2.99.0, < 4.0)
+ i18n (0.9.5)
+ concurrent-ruby (~> 1.0)
+ json (1.8.6)
+ listen (3.1.5)
+ rb-fsevent (~> 0.9, >= 0.9.4)
+ rb-inotify (~> 0.9, >= 0.9.7)
+ ruby_dep (~> 1.2)
+ lumberjack (1.0.13)
+ method_source (0.9.2)
+ mini_portile2 (2.4.0)
+ multi_json (1.13.1)
+ mustermann (1.0.3)
+ nenv (0.3.0)
+ nokogiri (1.10.1)
+ mini_portile2 (~> 2.4.0)
+ notiffany (0.1.1)
+ nenv (~> 0.1)
+ shellany (~> 0.0)
+ parseconfig (1.0.8)
+ pry (0.12.2)
+ coderay (~> 1.1.0)
+ method_source (~> 0.9.0)
+ rack (2.0.6)
+ rack-flash3 (1.0.5)
+ rack
+ rack-protection (2.0.5)
+ rack
+ rack-test (1.1.0)
+ rack (>= 1.0, < 3)
+ rake (10.5.0)
+ rb-fsevent (0.10.3)
+ rb-inotify (0.10.0)
+ ffi (~> 1.0)
+ rinku (2.0.5)
+ rspec (2.99.0)
+ rspec-core (~> 2.99.0)
+ rspec-expectations (~> 2.99.0)
+ rspec-mocks (~> 2.99.0)
+ rspec-core (2.99.2)
+ rspec-expectations (2.99.2)
+ diff-lcs (>= 1.1.3, < 2.0)
+ rspec-html-matchers (0.5.0)
+ nokogiri (~> 1)
+ rspec (~> 2, >= 2.11.0)
+ rspec-mocks (2.99.4)
+ ruby_dep (1.5.0)
+ shellany (0.0.1)
+ simple-navigation (4.0.5)
+ activesupport (>= 2.3.2)
+ simplecov (0.16.1)
+ docile (~> 1.1)
+ json (>= 1.8, < 3)
+ simplecov-html (~> 0.10.0)
+ simplecov-html (0.10.2)
+ sinatra (2.0.5)
+ mustermann (~> 1.0)
+ rack (~> 2.0)
+ rack-protection (= 2.0.5)
+ tilt (~> 2.0)
+ sinatra-simple-navigation (4.1.0)
+ simple-navigation (~> 4.0)
+ sinatra (>= 1.0, < 3.0)
+ thin (1.7.2)
+ daemons (~> 1.0, >= 1.0.9)
+ eventmachine (~> 1.0, >= 1.0.4)
+ rack (>= 1, < 3)
+ thor (0.20.3)
+ tilt (2.0.9)
+ vegas (0.1.11)
+ rack (>= 1.0.0)
+ versionomy (0.5.0)
+ blockenspiel (~> 0.5)
+
+PLATFORMS
+ ruby
+
+DEPENDENCIES
+ growl
+ guard-bundler
+ guard-rspec
+ rack-test
+ rake (< 11)
+ rb-fsevent
+ rspec (~> 2)
+ rspec-html-matchers
+ simplecov
+ taskwarrior-web!
+ thin
+
+BUNDLED WITH
+ 1.16.2
user = config.services.taskserver.user;
env = myconfig.env.tools.task;
group = config.services.taskserver.group;
+ taskserver-user-certs = pkgs.runCommand "taskserver-user-certs" {} ''
+ mkdir -p $out/bin
+ cat > $out/bin/taskserver-user-certs <<"EOF"
+ #!/usr/bin/env bash
+
+ user=$1
+
+ silent_certtool() {
+ if ! output="$("${pkgs.gnutls.bin}/bin/certtool" "$@" 2>&1)"; then
+ echo "GNUTLS certtool invocation failed with output:" >&2
+ echo "$output" >&2
+ fi
+ }
+
+ silent_certtool -p \
+ --bits 4096 \
+ --outfile "${vardir}/userkeys/$user.key.pem"
+ ${pkgs.gnused}/bin/sed -i -n -e '/^-----BEGIN RSA PRIVATE KEY-----$/,$p' "${vardir}/userkeys/$user.key.pem"
+
+ silent_certtool -c \
+ --template "${pkgs.writeText "taskserver-ca.template" ''
+ tls_www_client
+ encryption_key
+ signing_key
+ expiration_days = 3650
+ ''}" \
+ --load-ca-certificate "${vardir}/keys/ca.cert" \
+ --load-ca-privkey "${vardir}/keys/ca.key" \
+ --load-privkey "${vardir}/userkeys/$user.key.pem" \
+ --outfile "${vardir}/userkeys/$user.cert.pem"
+ EOF
+ chmod a+x $out/bin/taskserver-user-certs
+ patchShebangs $out/bin/taskserver-user-certs
+ '';
+ taskwarrior-web = pkgs.callPackage ./taskwarrior-web.nix {
+ inherit (mylibs) fetchedGithub;
+ inherit env;
+ };
+ taskwebPages = let
+ uidPages = lib.attrsets.zipAttrs (
+ lib.lists.flatten
+ (lib.attrsets.mapAttrsToList (k: c: map (v: { "${v}" = k; }) c.uid) env.taskwarrior-web)
+ );
+ pages = lib.attrsets.mapAttrs (uid: items:
+ if lib.lists.length items == 1 then
+ ''
+ <html>
+ <head>
+ <meta http-equiv="refresh" content="0; url=/taskweb/${lib.lists.head items}/" />
+ </head>
+ <body></body>
+ </html>
+ ''
+ else
+ ''
+ <html>
+ <head>
+ <title>To-do list disponibles</title>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
+ </head>
+ <body>
+ <ul>
+ ${builtins.concatStringsSep "\n" (map (item: "<li><a href='/taskweb/${item}'>${item}</a></li>") items)}
+ </ul>
+ </body>
+ </html>
+ ''
+ ) uidPages;
+ in
+ pkgs.runCommand "taskwerver-pages" {} ''
+ mkdir -p $out/
+ ${builtins.concatStringsSep "\n" (lib.attrsets.mapAttrsToList (k: v: "cp ${pkgs.writeText k v} $out/${k}.html") pages)}
+ echo "Please login" > $out/index.html
+ '';
in {
options.services.myTasks = {
enable = lib.mkEnableOption "my tasks service";
config = lib.mkIf cfg.enable {
security.acme.certs."eldiron".extraDomains.${fqdn} = null;
- services.myWebsites.tools.modules = [ "proxy_fcgi" ];
+ services.myWebsites.tools.modules = [ "proxy_fcgi" "sed" ];
services.myWebsites.tools.vhostConfs.task = {
certName = "eldiron";
hosts = [ "task.immae.eu" ];
SetEnv TASKD_LDAP_BASE "${env.ldap.base}"
SetEnv TASKD_LDAP_FILTER "${env.ldap.search}"
</Directory>
- '' ];
+ ''
+ ''
+ <Macro Taskwarrior %{folderName}>
+ ProxyPass "unix://${taskwarrior-web.socketsDir}/%{folderName}.sock|http://localhost-%{folderName}/"
+ ProxyPassReverse "unix://${taskwarrior-web.socketsDir}/%{folderName}.sock|http://localhost-%{folderName}/"
+ ProxyPassReverse http://${fqdn}/
+
+ SetOutputFilter Sed
+ OutputSed "s|/ajax|/taskweb/%{folderName}/ajax|g"
+ OutputSed "s|\([^x]\)/tasks|\1/taskweb/%{folderName}/tasks|g"
+ OutputSed "s|\([^x]\)/projects|\1/taskweb/%{folderName}/projects|g"
+ OutputSed "s|http://${fqdn}/|/taskweb/%{folderName}/|g"
+ OutputSed "s|/img/relax.jpg|/taskweb/%{folderName}/img/relax.jpg|g"
+ </Macro>
+ ''
+ ''
+ Alias /taskweb ${taskwebPages}
+ <Directory "${taskwebPages}">
+ DirectoryIndex index.html
+ Require all granted
+ </Directory>
+
+ RewriteEngine on
+ RewriteRule ^/taskweb$ /taskweb/ [R=301,L]
+ RedirectMatch permanent ^/taskweb/([^/]+)$ /taskweb/$1/
+
+ RewriteCond %{LA-U:REMOTE_USER} !=""
+ RewriteCond ${taskwebPages}/%{LA-U:REMOTE_USER}.html -f
+ RewriteRule ^/taskweb/?$ ${taskwebPages}/%{LA-U:REMOTE_USER}.html [L]
+
+ <Location /taskweb/>
+ Use LDAPConnect
+ Require ldap-group cn=users,cn=taskwarrior,ou=services,dc=immae,dc=eu
+ </Location>
+ ''
+ ] ++ (lib.attrsets.mapAttrsToList (k: v: ''
+ <Location /taskweb/${k}/>
+ ${builtins.concatStringsSep "\n" (map (uid: "Require ldap-attribute uid=${uid}") v.uid)}
+
+ Use Taskwarrior ${k}
+ </Location>
+ '') env.taskwarrior-web);
};
services.myPhpfpm.poolConfigs = {
tasks = ''
'';
};
- users.users.${user}.packages = [
- (pkgs.runCommand "taskserver-user-certs" {} ''
- mkdir -p $out/bin
- cat > $out/bin/taskserver-user-certs <<"EOF"
- #!/usr/bin/env bash
-
- user=$1
-
- silent_certtool() {
- if ! output="$("${pkgs.gnutls.bin}/bin/certtool" "$@" 2>&1)"; then
- echo "GNUTLS certtool invocation failed with output:" >&2
- echo "$output" >&2
- fi
- }
-
- silent_certtool -p \
- --bits 4096 \
- --outfile "${vardir}/userkeys/$user.key.pem"
- ${pkgs.gnused}/bin/sed -i -n -e '/^-----BEGIN RSA PRIVATE KEY-----$/,$p' "${vardir}/userkeys/$user.key.pem"
-
- silent_certtool -c \
- --template "${pkgs.writeText "taskserver-ca.template" ''
- tls_www_client
- encryption_key
- signing_key
- expiration_days = 3650
- ''}" \
- --load-ca-certificate "${vardir}/keys/ca.cert" \
- --load-ca-privkey "${vardir}/keys/ca.key" \
- --load-privkey "${vardir}/userkeys/$user.key.pem" \
- --outfile "${vardir}/userkeys/$user.cert.pem"
- EOF
- chmod a+x $out/bin/taskserver-user-certs
- patchShebangs $out/bin/taskserver-user-certs
- '')
- ];
-
- systemd.services.taskserver-ca.postStart = ''
- chown :${group} "${vardir}/keys/ca.key"
- chmod g+r "${vardir}/keys/ca.key"
- '';
+ users.users.${user}.packages = [ taskserver-user-certs ];
system.activationScripts.taskserver = {
deps = [ "users" ];
listenHost = "::";
requestLimit = 104857600;
};
+
+ system.activationScripts.taskwarrior-web = {
+ deps = [ "users" ];
+ text = ''
+ install -m 0755 -o ${user} -g ${group} -d ${taskwarrior-web.socketsDir}
+ install -m 0750 -o ${user} -g ${group} -d ${taskwarrior-web.varDir}
+ ${builtins.concatStringsSep "\n" (lib.attrsets.mapAttrsToList
+ (k: v: "install -m 0750 -o ${user} -g ${group} -d ${taskwarrior-web.varDir}/${k}")
+ env.taskwarrior-web
+ )}
+ if [ ! -f ${vardir}/userkeys/taskwarrior-web.cert.pem ]; then
+ ${taskserver-user-certs}/bin/taskserver-user-certs taskwarrior-web
+ chown taskd:taskd ${vardir}/userkeys/taskwarrior-web.cert.pem ${vardir}/userkeys/taskwarrior-web.key.pem
+ fi
+ '';
+ };
+
+ systemd.services = (lib.attrsets.mapAttrs' (name: userConfig:
+ let
+ credentials = "${userConfig.org}/${name}/${userConfig.key}";
+ dateFormat = userConfig.date;
+ taskrc = pkgs.writeText "taskrc" ''
+ data.location=${taskwarrior-web.varDir}/${name}
+ taskd.certificate=${vardir}/userkeys/taskwarrior-web.cert.pem
+ taskd.key=${vardir}/userkeys/taskwarrior-web.key.pem
+ taskd.ca=${vardir}/keys/server.cert
+ taskd.server=${fqdn}:${toString config.services.taskserver.listenPort}
+ taskd.credentials=${credentials}
+ dateformat=${dateFormat}
+ '';
+ in lib.attrsets.nameValuePair "taskwarrior-web-${name}" {
+ description = "Taskwarrior webapp for ${name}";
+ wantedBy = [ "multi-user.target" ];
+ after = [ "network.target" ];
+ path = [ pkgs.taskwarrior ];
+
+ environment.TASKRC = taskrc;
+ environment.BUNDLE_PATH = "${taskwarrior-web.gems}/lib/ruby/gems/2.5.0";
+ environment.BUNDLE_GEMFILE = "${taskwarrior-web.gems.confFiles}/Gemfile";
+ environment.LC_ALL = "fr_FR.UTF-8";
+
+ script = ''
+ exec ${taskwarrior-web.gems}/lib/ruby/gems/2.5.0/bin/bundle exec thin start -R config.ru -S ${taskwarrior-web.socketsDir}/${name}.sock
+ '';
+
+ serviceConfig = {
+ User = user;
+ PrivateTmp = true;
+ Restart = "always";
+ TimeoutSec = 60;
+ Type = "simple";
+ WorkingDirectory = taskwarrior-web.rubyRoot;
+ };
+
+ unitConfig.RequiresMountsFor = taskwarrior-web.varDir;
+ }) env.taskwarrior-web) // {
+ taskserver-ca.postStart = ''
+ chown :${group} "${vardir}/keys/ca.key"
+ chmod g+r "${vardir}/keys/ca.key"
+ '';
+ };
+
};
}
--- /dev/null
+diff --git a/lib/taskwarrior-web/helpers.rb b/lib/taskwarrior-web/helpers.rb
+index 212aed7..94c57df 100644
+--- a/lib/taskwarrior-web/helpers.rb
++++ b/lib/taskwarrior-web/helpers.rb
+@@ -1,6 +1,8 @@
+ require 'active_support/core_ext/date/calculations'
+
+ module TaskwarriorWeb::App::Helpers
++ include ERB::Util
++
+ def format_date(timestamp)
+ format = TaskwarriorWeb::Config.dateformat || '%-m/%-d/%Y'
+ Time.parse(timestamp).localtime.strftime(format)
+diff --git a/lib/taskwarrior-web/services/builder/base.rb b/lib/taskwarrior-web/services/builder/base.rb
+index 58d246e..8f716ac 100644
+--- a/lib/taskwarrior-web/services/builder/base.rb
++++ b/lib/taskwarrior-web/services/builder/base.rb
+@@ -10,7 +10,7 @@ module TaskwarriorWeb::CommandBuilder::Base
+ :complete => ':id done',
+ :annotate => ':id annotate',
+ :denotate => ':id denotate',
+- :projects => '_projects',
++ :projects => '_unique project',
+ :tags => '_tags',
+ :sync => 'sync'
+ }
+diff --git a/lib/taskwarrior-web/views/tasks/_form.erb b/lib/taskwarrior-web/views/tasks/_form.erb
+index 789e7a1..fa08698 100644
+--- a/lib/taskwarrior-web/views/tasks/_form.erb
++++ b/lib/taskwarrior-web/views/tasks/_form.erb
+@@ -1,14 +1,14 @@
+ <div class="control-group">
+ <label for="task-description" class="control-label">Description</label>
+ <div class="controls">
+- <input type="text" required="required" id="task-description" name="task[description]" value="<%= @task.description unless @task.nil? %>" />
++ <input type="text" required="required" id="task-description" name="task[description]" value="<%=h @task.description unless @task.nil? %>" />
+ </div>
+ </div>
+
+ <div class="control-group">
+ <label for="task-project" class="control-label">Project</label>
+ <div class="controls">
+- <input type="text" id="task-project" name="task[project]" value="<%= @task.project unless @task.nil? %>" autocomplete="off" />
++ <input type="text" id="task-project" name="task[project]" value="<%=h @task.project unless @task.nil? %>" autocomplete="off" />
+ </div>
+ </div>
+
+@@ -45,7 +45,7 @@
+ <div class="control-group">
+ <label for="task-tags" class="control-label">Tags</label>
+ <div class="controls">
+- <input type="text" id="task-tags" name="task[tags]" value="<%= @task.tags.join(', ') unless @task.nil? %>" autocomplete="off" />
++ <input type="text" id="task-tags" name="task[tags]" value="<%=h @task.tags.join(', ') unless @task.nil? %>" autocomplete="off" />
+ <span class="help-block">Enter tags separated by commas or spaces (e.g. <em>each, word will,be a tag</em>)</span>
+ </div>
+ </div>
--- /dev/null
+{
+ activesupport = {
+ dependencies = ["i18n" "multi_json"];
+ groups = ["default"];
+ platforms = [];
+ source = {
+ remotes = ["http://rubygems.org"];
+ sha256 = "0fyxqkkws4px4lzkbcqzp0bwai7nn7jk4p0bgfy0dny9cwm0qc9r";
+ type = "gem";
+ };
+ version = "3.2.22.5";
+ };
+ blockenspiel = {
+ groups = ["default"];
+ platforms = [];
+ source = {
+ remotes = ["http://rubygems.org"];
+ sha256 = "1h701s45n5qprvcpc7fnr45n88p56x07pznkxqnhz1dbdbhb7xx8";
+ type = "gem";
+ };
+ version = "0.5.0";
+ };
+ coderay = {
+ groups = ["default" "local"];
+ platforms = [];
+ source = {
+ remotes = ["http://rubygems.org"];
+ sha256 = "15vav4bhcc2x3jmi3izb11l4d9f3xv8hp2fszb7iqmpsccv1pz4y";
+ type = "gem";
+ };
+ version = "1.1.2";
+ };
+ concurrent-ruby = {
+ groups = ["default"];
+ platforms = [];
+ source = {
+ remotes = ["http://rubygems.org"];
+ sha256 = "1ixcx9pfissxrga53jbdpza85qd5f6b5nq1sfqa9rnfq82qnlbp1";
+ type = "gem";
+ };
+ version = "1.1.4";
+ };
+ daemons = {
+ groups = ["default"];
+ platforms = [];
+ source = {
+ remotes = ["http://rubygems.org"];
+ sha256 = "0l5gai3vd4g7aqff0k1mp41j9zcsvm2rbwmqn115a325k9r7pf4w";
+ type = "gem";
+ };
+ version = "1.3.1";
+ };
+ diff-lcs = {
+ groups = ["default" "development" "local"];
+ platforms = [];
+ source = {
+ remotes = ["http://rubygems.org"];
+ sha256 = "18w22bjz424gzafv6nzv98h0aqkwz3d9xhm7cbr1wfbyas8zayza";
+ type = "gem";
+ };
+ version = "1.3";
+ };
+ docile = {
+ groups = ["default" "local"];
+ platforms = [];
+ source = {
+ remotes = ["http://rubygems.org"];
+ sha256 = "04d2izkna3ahfn6fwq4xrcafa715d3bbqczxm16fq40fqy87xn17";
+ type = "gem";
+ };
+ version = "1.3.1";
+ };
+ eventmachine = {
+ groups = ["default"];
+ platforms = [];
+ source = {
+ remotes = ["http://rubygems.org"];
+ sha256 = "0wh9aqb0skz80fhfn66lbpr4f86ya2z5rx6gm5xlfhd05bj1ch4r";
+ type = "gem";
+ };
+ version = "1.2.7";
+ };
+ ffi = {
+ groups = ["default" "local"];
+ platforms = [];
+ source = {
+ remotes = ["http://rubygems.org"];
+ sha256 = "0j8pzj8raxbir5w5k6s7a042sb5k02pg0f8s4na1r5lan901j00p";
+ type = "gem";
+ };
+ version = "1.10.0";
+ };
+ formatador = {
+ groups = ["default" "local"];
+ platforms = [];
+ source = {
+ remotes = ["http://rubygems.org"];
+ sha256 = "1gc26phrwlmlqrmz4bagq1wd5b7g64avpx0ghxr9xdxcvmlii0l0";
+ type = "gem";
+ };
+ version = "0.2.5";
+ };
+ growl = {
+ groups = ["local"];
+ platforms = [];
+ source = {
+ remotes = ["http://rubygems.org"];
+ sha256 = "0s0y7maljnalpbv2q1j5j5hvb4wcc31y9af0n7x1q2l0fzxgc9n9";
+ type = "gem";
+ };
+ version = "1.0.3";
+ };
+ guard = {
+ dependencies = ["formatador" "listen" "lumberjack" "nenv" "notiffany" "pry" "shellany" "thor"];
+ groups = ["default" "local"];
+ platforms = [];
+ source = {
+ remotes = ["http://rubygems.org"];
+ sha256 = "0h84ja6qvii3hx86w9l4vjpbgl4m8ma8fbawwp7s8l791cgkdcmk";
+ type = "gem";
+ };
+ version = "2.15.0";
+ };
+ guard-bundler = {
+ dependencies = ["guard" "guard-compat"];
+ groups = ["local"];
+ platforms = [];
+ source = {
+ remotes = ["http://rubygems.org"];
+ sha256 = "0lji8f8w7y4prmpr2lqmlljvkqgkgnlsiwqgwvq7b1y3sxlsvy62";
+ type = "gem";
+ };
+ version = "2.2.1";
+ };
+ guard-compat = {
+ groups = ["default" "local"];
+ platforms = [];
+ source = {
+ remotes = ["http://rubygems.org"];
+ sha256 = "1zj6sr1k8w59mmi27rsii0v8xyy2rnsi09nqvwpgj1q10yq1mlis";
+ type = "gem";
+ };
+ version = "1.2.1";
+ };
+ guard-rspec = {
+ dependencies = ["guard" "guard-compat" "rspec"];
+ groups = ["local"];
+ platforms = [];
+ source = {
+ remotes = ["http://rubygems.org"];
+ sha256 = "1jkm5xp90gm4c5s51pmf92i9hc10gslwwic6mvk72g0yplya0yx4";
+ type = "gem";
+ };
+ version = "4.7.3";
+ };
+ i18n = {
+ dependencies = ["concurrent-ruby"];
+ groups = ["default"];
+ platforms = [];
+ source = {
+ remotes = ["http://rubygems.org"];
+ sha256 = "038qvz7kd3cfxk8bvagqhakx68pfbnmghpdkx7573wbf0maqp9a3";
+ type = "gem";
+ };
+ version = "0.9.5";
+ };
+ json = {
+ groups = ["default" "local"];
+ platforms = [];
+ source = {
+ remotes = ["http://rubygems.org"];
+ sha256 = "0qmj7fypgb9vag723w1a49qihxrcf5shzars106ynw2zk352gbv5";
+ type = "gem";
+ };
+ version = "1.8.6";
+ };
+ listen = {
+ dependencies = ["rb-fsevent" "rb-inotify" "ruby_dep"];
+ groups = ["default" "local"];
+ platforms = [];
+ source = {
+ remotes = ["http://rubygems.org"];
+ sha256 = "01v5mrnfqm6sgm8xn2v5swxsn1wlmq7rzh2i48d4jzjsc7qvb6mx";
+ type = "gem";
+ };
+ version = "3.1.5";
+ };
+ lumberjack = {
+ groups = ["default" "local"];
+ platforms = [];
+ source = {
+ remotes = ["http://rubygems.org"];
+ sha256 = "06im7gcg42x77yhz2w5da2ly9xz0n0c36y5ks7xs53v0l9g0vf5n";
+ type = "gem";
+ };
+ version = "1.0.13";
+ };
+ method_source = {
+ groups = ["default" "local"];
+ platforms = [];
+ source = {
+ remotes = ["http://rubygems.org"];
+ sha256 = "1pviwzvdqd90gn6y7illcdd9adapw8fczml933p5vl739dkvl3lq";
+ type = "gem";
+ };
+ version = "0.9.2";
+ };
+ mini_portile2 = {
+ groups = ["default" "development"];
+ platforms = [];
+ source = {
+ remotes = ["http://rubygems.org"];
+ sha256 = "15zplpfw3knqifj9bpf604rb3wc1vhq6363pd6lvhayng8wql5vy";
+ type = "gem";
+ };
+ version = "2.4.0";
+ };
+ multi_json = {
+ groups = ["default"];
+ platforms = [];
+ source = {
+ remotes = ["http://rubygems.org"];
+ sha256 = "1rl0qy4inf1mp8mybfk56dfga0mvx97zwpmq5xmiwl5r770171nv";
+ type = "gem";
+ };
+ version = "1.13.1";
+ };
+ mustermann = {
+ groups = ["default"];
+ platforms = [];
+ source = {
+ remotes = ["http://rubygems.org"];
+ sha256 = "0lycgkmnyy0bf29nnd2zql5a6pcf8sp69g9v4xw0gcfcxgpwp7i1";
+ type = "gem";
+ };
+ version = "1.0.3";
+ };
+ nenv = {
+ groups = ["default" "local"];
+ platforms = [];
+ source = {
+ remotes = ["http://rubygems.org"];
+ sha256 = "0r97jzknll9bhd8yyg2bngnnkj8rjhal667n7d32h8h7ny7nvpnr";
+ type = "gem";
+ };
+ version = "0.3.0";
+ };
+ nokogiri = {
+ dependencies = ["mini_portile2"];
+ groups = ["default" "development"];
+ platforms = [];
+ source = {
+ remotes = ["http://rubygems.org"];
+ sha256 = "09zll7c6j7xr6wyvh5mm5ncj6pkryp70ybcsxdbw1nyphx5dh184";
+ type = "gem";
+ };
+ version = "1.10.1";
+ };
+ notiffany = {
+ dependencies = ["nenv" "shellany"];
+ groups = ["default" "local"];
+ platforms = [];
+ source = {
+ remotes = ["http://rubygems.org"];
+ sha256 = "0x838fa5il0dd9zbm3lxkpbfxcf5fxv9556mayc2mxsdl5ghv8nx";
+ type = "gem";
+ };
+ version = "0.1.1";
+ };
+ parseconfig = {
+ groups = ["default"];
+ platforms = [];
+ source = {
+ remotes = ["http://rubygems.org"];
+ sha256 = "0br2g9k6zc4ygah52aa8cwvpnnkszia29bnvnr8bhpk3rdzi2vmq";
+ type = "gem";
+ };
+ version = "1.0.8";
+ };
+ pry = {
+ dependencies = ["coderay" "method_source"];
+ groups = ["default" "local"];
+ platforms = [];
+ source = {
+ remotes = ["http://rubygems.org"];
+ sha256 = "00rm71x0r1jdycwbs83lf9l6p494m99asakbvqxh8rz7zwnlzg69";
+ type = "gem";
+ };
+ version = "0.12.2";
+ };
+ rack = {
+ groups = ["default" "development"];
+ platforms = [];
+ source = {
+ remotes = ["http://rubygems.org"];
+ sha256 = "1pcgv8dv4vkaczzlix8q3j68capwhk420cddzijwqgi2qb4lm1zm";
+ type = "gem";
+ };
+ version = "2.0.6";
+ };
+ rack-flash3 = {
+ dependencies = ["rack"];
+ groups = ["default"];
+ platforms = [];
+ source = {
+ remotes = ["http://rubygems.org"];
+ sha256 = "0rim9afrns6s8zc4apiymncysyvijpdg18k57kdpz66p55jf4mqz";
+ type = "gem";
+ };
+ version = "1.0.5";
+ };
+ rack-protection = {
+ dependencies = ["rack"];
+ groups = ["default"];
+ platforms = [];
+ source = {
+ remotes = ["http://rubygems.org"];
+ sha256 = "15167q25rmxipqwi6hjqj3i1byi9iwl3xq9b7mdar7qiz39pmjsk";
+ type = "gem";
+ };
+ version = "2.0.5";
+ };
+ rack-test = {
+ dependencies = ["rack"];
+ groups = ["development"];
+ platforms = [];
+ source = {
+ remotes = ["http://rubygems.org"];
+ sha256 = "0rh8h376mx71ci5yklnpqqn118z3bl67nnv5k801qaqn1zs62h8m";
+ type = "gem";
+ };
+ version = "1.1.0";
+ };
+ rake = {
+ groups = ["development"];
+ platforms = [];
+ source = {
+ remotes = ["http://rubygems.org"];
+ sha256 = "0jcabbgnjc788chx31sihc5pgbqnlc1c75wakmqlbjdm8jns2m9b";
+ type = "gem";
+ };
+ version = "10.5.0";
+ };
+ rb-fsevent = {
+ groups = ["local"];
+ platforms = [];
+ source = {
+ remotes = ["http://rubygems.org"];
+ sha256 = "1lm1k7wpz69jx7jrc92w3ggczkjyjbfziq5mg62vjnxmzs383xx8";
+ type = "gem";
+ };
+ version = "0.10.3";
+ };
+ rb-inotify = {
+ dependencies = ["ffi"];
+ groups = ["default" "local"];
+ platforms = [];
+ source = {
+ remotes = ["http://rubygems.org"];
+ sha256 = "1fs7hxm9g6ywv2yih83b879klhc4fs8i0p9166z795qmd77dk0a4";
+ type = "gem";
+ };
+ version = "0.10.0";
+ };
+ rinku = {
+ groups = ["default"];
+ platforms = [];
+ source = {
+ remotes = ["http://rubygems.org"];
+ sha256 = "1smkk299v18brk98gqbdnqrfwm3143kikl30scidqb5j3pzlbz91";
+ type = "gem";
+ };
+ version = "2.0.5";
+ };
+ rspec = {
+ dependencies = ["rspec-core" "rspec-expectations" "rspec-mocks"];
+ groups = ["development" "local"];
+ platforms = [];
+ source = {
+ remotes = ["http://rubygems.org"];
+ sha256 = "14q3hxvngk4ks8h41yw50d5fqbf2dhzwi9rz5ccxvh5a53ak2as3";
+ type = "gem";
+ };
+ version = "2.99.0";
+ };
+ rspec-core = {
+ groups = ["default" "development" "local"];
+ platforms = [];
+ source = {
+ remotes = ["http://rubygems.org"];
+ sha256 = "1wwz21lcz2lwd2jcp2pvq7n1677v23acf7wxsyszp8msb47mw38i";
+ type = "gem";
+ };
+ version = "2.99.2";
+ };
+ rspec-expectations = {
+ dependencies = ["diff-lcs"];
+ groups = ["default" "development" "local"];
+ platforms = [];
+ source = {
+ remotes = ["http://rubygems.org"];
+ sha256 = "11a5pph3anp4xr591dnlcy8xfkdf54qi2lvg4ykpqhxk37si1py3";
+ type = "gem";
+ };
+ version = "2.99.2";
+ };
+ rspec-html-matchers = {
+ dependencies = ["nokogiri" "rspec"];
+ groups = ["development"];
+ platforms = [];
+ source = {
+ remotes = ["http://rubygems.org"];
+ sha256 = "148grzvk0cvh24avhl0shjzz7ldhj138svf48pc5h1fdsb0pnqcv";
+ type = "gem";
+ };
+ version = "0.5.0";
+ };
+ rspec-mocks = {
+ groups = ["default" "development" "local"];
+ platforms = [];
+ source = {
+ remotes = ["http://rubygems.org"];
+ sha256 = "0bzhqahbiswq41nqi6y2dka1k42n0hl14jb6bldb206zp4hikz8r";
+ type = "gem";
+ };
+ version = "2.99.4";
+ };
+ ruby_dep = {
+ groups = ["default" "local"];
+ platforms = [];
+ source = {
+ remotes = ["http://rubygems.org"];
+ sha256 = "1c1bkl97i9mkcvkn1jks346ksnvnnp84cs22gwl0vd7radybrgy5";
+ type = "gem";
+ };
+ version = "1.5.0";
+ };
+ shellany = {
+ groups = ["default" "local"];
+ platforms = [];
+ source = {
+ remotes = ["http://rubygems.org"];
+ sha256 = "1ryyzrj1kxmnpdzhlv4ys3dnl2r5r3d2rs2jwzbnd1v96a8pl4hf";
+ type = "gem";
+ };
+ version = "0.0.1";
+ };
+ simple-navigation = {
+ dependencies = ["activesupport"];
+ groups = ["default"];
+ platforms = [];
+ source = {
+ remotes = ["http://rubygems.org"];
+ sha256 = "08a2s18an3br3xj5j86r33q0hrkai0y157xg67h1khdskb08yylk";
+ type = "gem";
+ };
+ version = "4.0.5";
+ };
+ simplecov = {
+ dependencies = ["docile" "json" "simplecov-html"];
+ groups = ["local"];
+ platforms = [];
+ source = {
+ remotes = ["http://rubygems.org"];
+ sha256 = "1sfyfgf7zrp2n42v7rswkqgk3bbwk1bnsphm24y7laxv3f8z0947";
+ type = "gem";
+ };
+ version = "0.16.1";
+ };
+ simplecov-html = {
+ groups = ["default" "local"];
+ platforms = [];
+ source = {
+ remotes = ["http://rubygems.org"];
+ sha256 = "1lihraa4rgxk8wbfl77fy9sf0ypk31iivly8vl3w04srd7i0clzn";
+ type = "gem";
+ };
+ version = "0.10.2";
+ };
+ sinatra = {
+ dependencies = ["mustermann" "rack" "rack-protection" "tilt"];
+ groups = ["default"];
+ platforms = [];
+ source = {
+ remotes = ["http://rubygems.org"];
+ sha256 = "1gasgn5f15myv08k10i16p326pchxjsy37pgqfw0xm66kcc5d7ry";
+ type = "gem";
+ };
+ version = "2.0.5";
+ };
+ sinatra-simple-navigation = {
+ dependencies = ["simple-navigation" "sinatra"];
+ groups = ["default"];
+ platforms = [];
+ source = {
+ remotes = ["http://rubygems.org"];
+ sha256 = "1gishxd23qw6bwsk7fkagkfc7ihqyvvvb98j9bmwc6wwpsfs4prs";
+ type = "gem";
+ };
+ version = "4.1.0";
+ };
+ taskwarrior-web = {
+ dependencies = ["activesupport" "json" "parseconfig" "rack-flash3" "rinku" "sinatra" "sinatra-simple-navigation" "vegas" "versionomy"];
+ groups = ["default"];
+ platforms = [];
+ bundledByPath = true;
+ path = ./.;
+ source = {
+ path = ./.;
+ type = "path";
+ };
+ version = "1.1.12";
+ };
+ thin = {
+ dependencies = ["daemons" "eventmachine" "rack"];
+ groups = ["default"];
+ platforms = [];
+ source = {
+ remotes = ["http://rubygems.org"];
+ sha256 = "0nagbf9pwy1vg09k6j4xqhbjjzrg5dwzvkn4ffvlj76fsn6vv61f";
+ type = "gem";
+ };
+ version = "1.7.2";
+ };
+ thor = {
+ groups = ["default" "local"];
+ platforms = [];
+ source = {
+ remotes = ["http://rubygems.org"];
+ sha256 = "1yhrnp9x8qcy5vc7g438amd5j9sw83ih7c30dr6g6slgw9zj3g29";
+ type = "gem";
+ };
+ version = "0.20.3";
+ };
+ tilt = {
+ groups = ["default"];
+ platforms = [];
+ source = {
+ remotes = ["http://rubygems.org"];
+ sha256 = "0ca4k0clwf0rkvy7726x4nxpjxkpv67w043i39saxgldxd97zmwz";
+ type = "gem";
+ };
+ version = "2.0.9";
+ };
+ vegas = {
+ dependencies = ["rack"];
+ groups = ["default"];
+ platforms = [];
+ source = {
+ remotes = ["http://rubygems.org"];
+ sha256 = "0kzv0v1zb8vvm188q4pqwahb6468bmiamn6wpsbiq6r5i69s1bs5";
+ type = "gem";
+ };
+ version = "0.1.11";
+ };
+ versionomy = {
+ dependencies = ["blockenspiel"];
+ groups = ["default"];
+ platforms = [];
+ source = {
+ remotes = ["http://rubygems.org"];
+ sha256 = "0i0l4pzrl1vyp4lpg2cxhgkk56spki3lld943d6h7168fj8qyv33";
+ type = "gem";
+ };
+ version = "0.5.0";
+ };
+}
--- /dev/null
+{
+ "tag": "a79cfe2-master",
+ "meta": {
+ "name": "taskwarrior-web",
+ "url": "https://github.com/theunraveler/taskwarrior-web",
+ "branch": "master"
+ },
+ "github": {
+ "owner": "theunraveler",
+ "repo": "taskwarrior-web",
+ "rev": "a79cfe2b42791b62364118e58b21b892fff6ded8",
+ "sha256": "028rb4wry2an19707bvy4n305f3s0hipg214224p1m0mb61c3cq4",
+ "fetchSubmodules": true
+ }
+}
--- /dev/null
+{ env, ruby_2_5, bundlerEnv, defaultGemConfig, fetchedGithub, stdenv, writeText, pkgs }:
+let
+ varDir = "/var/lib/taskwarrior-web";
+ socketsDir = "/run/taskwarrior-web";
+ rubyRoot = stdenv.mkDerivation (fetchedGithub ./taskwarrior-web.json // rec {
+ phases = [ "unpackPhase" "patchPhase" "installPhase" ];
+ patches = [ ./fixes.patch ./thin.patch ];
+ installPhase = ''
+ cp -a . $out
+ cp ${./Gemfile.lock} $out/Gemfile.lock
+ '';
+ });
+ gems = bundlerEnv {
+ name = "taskwarrior-web-env";
+ ruby = ruby_2_5;
+ pname = "taskwarrior-web";
+ gemset = ./gemset.nix;
+ gemdir = rubyRoot.out;
+ groups = [ "default" "local" "development" ];
+ };
+in
+ {
+ inherit gems varDir socketsDir rubyRoot;
+ }
--- /dev/null
+diff --git a/Gemfile b/Gemfile
+index 8544e15..9c4279c 100644
+--- a/Gemfile
++++ b/Gemfile
+@@ -3,6 +3,8 @@ source "http://rubygems.org"
+ # Specify your gem's dependencies in taskwarrior-web.gemspec
+ gemspec
+
++gem 'thin'
++
+ group :local do
+ gem 'rb-fsevent', :require => false
+ gem 'growl', :require => false
+diff --git a/config.ru b/config.ru
+index c3050c6..52387d8 100644
+--- a/config.ru
++++ b/config.ru
+@@ -1,5 +1,4 @@
+ require File.join(File.dirname(__FILE__), 'lib', 'taskwarrior-web')
+
+-disable :run
+ TaskwarriorWeb::App.set({ :environment => :production })
+ run TaskwarriorWeb::App