From 13767cc69697b7eaf4be6e47788efe636b56b6fd Mon Sep 17 00:00:00 2001
From: Lunar <lunar@anargeek.net>
Date: Sun, 2 Jun 2013 00:26:35 +0200
Subject: [PATCH] Finish implenting update-ag-subscribers

---
 README                                     | 11 +++++++++++
 bin/update-ag-subscribers                  |  8 ++++++++
 features/step_definitions/subscriptions.rb | 11 +++++++++++
 features/support/mock_mailman/sudo         | 10 ++++++++++
 features/update-ag-subscribers.feature     | 17 ++++++++++++++++-
 lib/nos_oignons/mailman.rb                 | 21 ++++++++++++++++++---
 6 files changed, 74 insertions(+), 4 deletions(-)
 create mode 100755 features/support/mock_mailman/sudo

diff --git a/README b/README
index bc73c09..984d914 100644
--- a/README
+++ b/README
@@ -83,6 +83,14 @@ des informations invalides dans la base des membres. Il doit être configuré da
 le dépôt central du wiki du C.A. (via un lien symbolique dans
 `.git/hooks/pre-receive`).
 
+update-ag-subscribers
+---------------------
+
+Met à jour la liste des emails inscrites à la liste ag@ par rapport aux membres
+à jour de cotisation. À exécuter à travers un *cron*. A besoin de pouvoir
+lancer les commandes `list_members`, `add_members` et `remove_members` via
+`sudo` sur le compte `list`.
+
 Développement
 =============
 
@@ -112,3 +120,6 @@ Installer les dépendences :
 
 Il faut ensuite mettre en place le lien symbolique vers le script
 `pre-receive-hooks`. XXX: à détailler
+
+XXX: configuration sudoers
+XXX: crontab pour update-ag-subscribers
diff --git a/bin/update-ag-subscribers b/bin/update-ag-subscribers
index e5580c2..f10978e 100755
--- a/bin/update-ag-subscribers
+++ b/bin/update-ag-subscribers
@@ -7,3 +7,11 @@ Bundler.setup
 
 require 'nos_oignons/mailman'
 require 'nos_oignons/subscriptions'
+
+LIST = 'ag'
+
+current_emails = NosOignons::Mailman.list_members(LIST)
+uptodate_emails = NosOignons::Subscription.all.select(&:up_to_date?).collect(&:email)
+
+NosOignons::Mailman.add_members(LIST, uptodate_emails - current_emails)
+NosOignons::Mailman.remove_members(LIST, current_emails - uptodate_emails)
diff --git a/features/step_definitions/subscriptions.rb b/features/step_definitions/subscriptions.rb
index a4827f5..dd18151 100644
--- a/features/step_definitions/subscriptions.rb
+++ b/features/step_definitions/subscriptions.rb
@@ -23,6 +23,17 @@ Given /^(?:une base )?avec (\w+)(, à jour de cotisation| qui n'a pas payé sa c
   write_file file, render_subscription_file(data)
 end
 
+Given /^une nouvelle adhésion de (\w+)$/ do |name|
+  data = { 'name' => name,
+           'address' => "At #{name}",
+           'email' => "#{name.downcase}@example.org",
+           'membership_fee_paid_on' => Time.now.strftime('%Y-%m-%d')
+         }
+  create_dir 'Membres'
+  file = subscription_filename_for_id(new_id)
+  write_file file, render_subscription_file(data)
+end
+
 When /^j'ajoute une fiche correcte pour une nouvelle adhésion$/ do
   @file = subscription_filename_for_id(new_id)
   write_file @file, render_subscription_file(EXTRA_SUBSCRIPTION)
diff --git a/features/support/mock_mailman/sudo b/features/support/mock_mailman/sudo
new file mode 100755
index 0000000..a0ac546
--- /dev/null
+++ b/features/support/mock_mailman/sudo
@@ -0,0 +1,10 @@
+#!/bin/sh
+
+if ! [ "-u" = "$1" ] && ! [ "list" = "$2" ]; then
+	echo "Bad call" >&2
+	exit 1
+fi
+
+shift 2
+
+exec "$@"
diff --git a/features/update-ag-subscribers.feature b/features/update-ag-subscribers.feature
index 0ca89aa..4ee9725 100644
--- a/features/update-ag-subscribers.feature
+++ b/features/update-ag-subscribers.feature
@@ -54,10 +54,25 @@ Fonctionnalité: mettre à jour les emails inscrites à la liste ag@
     Et une base avec Pierre, à jour de cotisation
     Et avec Jane qui n'a pas payé sa cotisation cette année
     Et avec Fatima, à jour de cotisation
-    Et une nouvelle adhésion de Sean
     Lorsque j'exécute update-ag-subscribers
     Alors la liste ag@ doit avoir comme emails inscrits:
       """
       pierre@example.org
       fatima@example.org
       """
+
+  Scénario: Un ajout et une suppression
+    Soit une liste ag@ avec comme emails inscrits:
+      """
+      pierre@example.org
+      jane@example.org
+      """
+    Et une base avec Pierre, à jour de cotisation
+    Et avec Jane qui n'a pas payé sa cotisation cette année
+    Et une nouvelle adhésion de Sean
+    Lorsque j'exécute update-ag-subscribers
+    Alors la liste ag@ doit avoir comme emails inscrits:
+      """
+      pierre@example.org
+      sean@example.org
+      """
diff --git a/lib/nos_oignons/mailman.rb b/lib/nos_oignons/mailman.rb
index 501b542..9c0d590 100644
--- a/lib/nos_oignons/mailman.rb
+++ b/lib/nos_oignons/mailman.rb
@@ -6,7 +6,7 @@ module NosOignons
   module Mailman
     class << self
       def list_members(list)
-        `list_members #{Shellwords.escape(list)}`.split
+        `sudo -u list list_members #{Shellwords.escape(list)}`.strip.split
       end
 
       def add_member(list, email)
@@ -14,8 +14,23 @@ module NosOignons
       end
 
       def add_members(list, emails)
-        # XXX IO.popen 
-        `add_members #{Shellwords.escape(list)}`.split
+        IO.popen(['sudo', '-u', 'list', 'add_members', '-r', '-', list], 'w') do |io|
+          emails.each do |email|
+            io.puts email
+          end
+        end
+      end
+
+      def remove_member(list, email)
+        remove_members(list, [email])
+      end
+
+      def remove_members(list, emails)
+        IO.popen(['sudo', '-u', 'list', 'remove_members', '-f', '-', list], 'w') do |io|
+          emails.each do |email|
+            io.puts email
+          end
+        end
       end
     end
   end
-- 
2.39.5