Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

"Writer" for private groups #281

Open
VVD opened this issue Dec 2, 2023 · 6 comments
Open

"Writer" for private groups #281

VVD opened this issue Dec 2, 2023 · 6 comments

Comments

@VVD
Copy link

VVD commented Dec 2, 2023

Private groups: only who have Writer bit can write emails to group.
Public groups: not affected.
checked.png: checked
unchecked.png: unchecked

diff -ur vexim.orig/admingroupchange.php vexim/admingroupchange.php
--- vexim.orig/admingroupchange.php
+++ vexim/admingroupchange.php
@@ -76,7 +76,7 @@
         <tr>
           <td colspan="2">
             <?php
-              $query = "SELECT u.realname, u.localpart, u.enabled, c.member_id
+              $query = "SELECT u.realname, u.localpart, u.enabled, c.member_id, c.writer
                 FROM users u, group_contents c
                 WHERE u.user_id=c.member_id and c.group_id=:group_id
                 ORDER BY u.enabled desc, u.realname asc";
@@ -86,6 +86,7 @@
             ?>
             <table align="center">
               <tr>
+                <th><?php echo _('Writer'); ?></th>
                 <th>&nbsp;</th>
                 <th><?php echo _('Real name'); ?></th>
                 <th><?php echo _('Email Address'); ?></th>
@@ -95,11 +96,42 @@
                 while ($row = $sth->fetch()) {
               ?>
               <tr>
+                <td>
+                  <div align="center">
+                  <?php
+                    if($row['writer']=='1') {
+                  ?>
+                  <a href="admingroupwritersubmit.php?group_id=<?php echo htmlspecialchars($_GET['group_id']);
+                                        ?>&member_id=<?php echo $row['member_id'];
+                                        ?>&localpart=<?php echo $grouplocalpart;
+                                        ?>&writer=0">
+                    <img
+                      title="Disable writer permissions <?php echo $row['realname']
+                      . ' from group ' . $grouplocalpart; ?>"
+                      src="images/checked.png" alt="disable">
+                  </a>
+                  <?php
+                    } else {
+                  ?>
+                  <a href="admingroupwritersubmit.php?group_id=<?php echo htmlspecialchars($_GET['group_id']);
+                                        ?>&member_id=<?php echo $row['member_id'];
+                                        ?>&localpart=<?php echo $grouplocalpart;
+                                        ?>&writer=1">
+                    <img
+                      title="Enable writer permissions <?php echo $row['realname']
+                      . ' from group ' . $grouplocalpart; ?>"
+                      src="images/unchecked.png" alt="enable">
+                  </a>
+                  <?php
+                    }
+                  ?>
+                  </div>
+                </td>
                 <td class="trash">
                   <a href="admingroupcontentdeletesubmit.php?group_id=<?php echo htmlspecialchars($_GET['group_id']);
-                                       ?>&member_id=<?php echo $row['member_id'];
-                                       ?>&localpart=<?php echo $grouplocalpart;
-                                       ?>">
+                                        ?>&member_id=<?php echo $row['member_id'];
+                                        ?>&localpart=<?php echo $grouplocalpart;
+                                        ?>">
                     <img class="trash"
                       title="Remove member <?php echo $row['realname']
                       . ' from group ' . $grouplocalpart; ?>"
@@ -112,7 +144,7 @@
                   <?php
                     if($row['enabled']=='1') {
                   ?>
-                  <img class="check" src="images/check.gif">
+                  <div align="center"><img class="check" src="images/check.gif"></div>
                   <?php
                     }
                   ?>
@@ -135,7 +167,7 @@
           <form method="post" action="admingroupcontentaddsubmit.php"
             name="groupcontentadd">
           <tr>
-            <td><?php echo _('Add Member'); ?></td>
+            <td><?php echo _('Add Member'); ?><br/>&nbsp;</td>
             <td>
               <input name="group_id" type="hidden"
                 value="<?php echo htmlspecialchars($_GET['group_id']); ?>" class="textfield">
@@ -158,6 +190,7 @@
                   }
                 ?>
               </select>
+              <br><?php echo _('Writer'); ?>: <input name="writer" type="checkbox" class="textfield" />
             </td>
           </tr>
           <tr>
diff -ur vexim.orig/admingroupcontentaddsubmit.php vexim/admingroupcontentaddsubmit.php
--- vexim.orig/admingroupcontentaddsubmit.php
+++ vexim/admingroupcontentaddsubmit.php
@@ -17,9 +17,13 @@
     header("Location: admingroup.php?badname={$_POST['usertoadd']}");
     die;
   }
-  $query = "INSERT INTO group_contents (group_id, member_id) VALUES (:group_id, :usertoadd)";
+  $query = "INSERT INTO group_contents (group_id, member_id, writer) VALUES (:group_id, :usertoadd, :writer)";
   $sth = $dbh->prepare($query);
-  $success = $sth->execute(array(':group_id'=>$_POST['group_id'], ':usertoadd'=>$_POST['usertoadd']));
+  try {
+    $success = $sth->execute(array(':group_id'=>$_POST['group_id'], ':usertoadd'=>$_POST['usertoadd'], ':writer'=>isset($_POST['writer']) ? 1 : 0));
+  } catch (PDOException $e) {
+    $success = 0;
+  }
   if ($success) {
     header ("Location: admingroupchange.php?group_id={$_POST['group_id']}&group_updated={$_POST['localpart']}");
   } else {
Only in vexim/images: checked.png
Only in vexim/images: unchecked.png
diff -ur vexim.orig/locale/ru/LC_MESSAGES/ru.po vexim/locale/ru/LC_MESSAGES/ru.po
--- vexim.orig/locale/ru/LC_MESSAGES/ru.po
+++ vexim/locale/ru/LC_MESSAGES/ru.po
@@ -357,11 +357,15 @@
 msgid "Edit group"
 msgstr "Редактировать группу"

-#: admingroupchange.php:89
+#: admingroupchange.php:89 admingroupchange.php:193
+msgid "Writer"
+msgstr "Писатель"
+
+#: admingroupchange.php:91
 msgid "Real name"
 msgstr "Настоящее имя"

-#: admingroupchange.php:90 adminuserchange.php:79 userchange.php:40
+#: admingroupchange.php:92 adminuserchange.php:79 userchange.php:40
 msgid "Email Address"
 msgstr "Почтвый адрес"

diff -ur vexim.orig/locale/template.pot vexim/locale/template.pot
--- vexim.orig/locale/template.pot
+++ vexim/locale/template.pot
@@ -346,11 +346,15 @@
 msgid "Edit group"
 msgstr ""

-#: admingroupchange.php:89
+#: admingroupchange.php:89 admingroupchange.php:193
+msgid "Writer"
+msgstr ""
+
+#: admingroupchange.php:91
 msgid "Real name"
 msgstr ""

-#: admingroupchange.php:90 adminuserchange.php:79 userchange.php:40
+#: admingroupchange.php:92 adminuserchange.php:79 userchange.php:40
 msgid "Email Address"
 msgstr ""

diff -ur docs.orig/debian-conf.d/router/250_vexim_virtual_domains docs/debian-conf.d/router/250_vexim_virtual_domains
--- docs.orig/debian-conf.d/router/250_vexim_virtual_domains
+++ docs/debian-conf.d/router/250_vexim_virtual_domains
@@ -82,20 +82,30 @@
   allow_fail
   senders = ${if eq{Y}{${lookup mysql{select g.is_public \
                                       from groups g, domains d \
-                                      where d.enabled = '1' and d.domain = '${quote_mysql:$domain}' and \
-                                            d.domain_id = g.domain_id and g.enabled = '1' and \
+                                      where d.enabled = 1 and d.domain = '${quote_mysql:$domain}' and \
+                                            d.domain_id = g.domain_id and g.enabled = 1 and \
                                             g.name = '${quote_mysql:$local_part}'}}} \
                  {$sender_address} \
-                 {${lookup mysql{select concat_ws('@', u.localpart, d.domain) \
+                 {${lookup mysql{select u.username \
                                  from domains d, groups g, group_contents c, users u \
-                                 where d.enabled = '1' and d.domain = '${quote_mysql:$domain}' and \
+                                 where d.enabled = 1 and d.domain = '${quote_mysql:$domain}' and \
                                        d.domain_id = g.domain_id and g.name = '${quote_mysql:$local_part}' and \
-                                       g.enabled = '1' and \
-                                       g.is_public = 'N' and c.member_id = u.user_id and \
-                                       d.domain_id = u.domain_id and u.enabled = '1' \
-                                       and u.username = '${quote_mysql:$sender_address}' limit 1}}}}
+                                       g.enabled = 1 and g.id = c.group_id and \
+                                       g.is_public = 'N' and c.writer = 1 and c.member_id = u.user_id and \
+                                       d.domain_id = u.domain_id and u.enabled = 1 and \
+                                       u.username = '${quote_mysql:$sender_address}' \
+                                 union \
+                                 select a.username \
+                                 from domains d, groups g, group_contents c, users u, users a \
+                                 where d.enabled = 1 and d.domain = '${quote_mysql:$domain}' and \
+                                       d.domain_id = g.domain_id and g.name = '${quote_mysql:$local_part}' and \
+                                       g.enabled = 1 and g.id = c.group_id and \
+                                       g.is_public = 'N' and c.writer = 1 and c.member_id = u.user_id and \
+                                       d.domain_id = u.domain_id and u.enabled = 1 and a.enabled = 1 and \
+                                       a.type = 'alias' and a.username = '${quote_mysql:$sender_address}' and \
+                                       a.smtp = u.username }}}}
   data = ${lookup mysql{ \
-            select concat_ws('@', u.localpart, d.domain) \
+            select u.username \
             from domains d, groups g, group_contents c, users u \
             where d.enabled     = '1'           and \
                   d.domain      = '${quote_mysql:$domain}'   and \
diff -urN setup.orig/migrations/vexim_2.3_to_2.3.1_mysql.sql setup/migrations/vexim_2.3_to_2.3.1_mysql.sql
--- setup.orig/migrations/vexim_2.3_to_2.3.1_mysql.sql
+++ setup/migrations/vexim_2.3_to_2.3.1_mysql.sql
@@ -0,0 +1,5 @@
+--
+-- MySQL script to upgrade Vexim database schema from Vexim 2.3 to Vexim 2.3.1
+--
+
+ALTER TABLE `group_contents` ADD COLUMN `writer` tinyint(1) NOT NULL DEFAULT '1';
diff -urN setup.orig/mysql.sql setup/mysql.sql
--- setup.orig/mysql.sql
+++ setup/mysql.sql
@@ -177,6 +177,7 @@
 CREATE TABLE `group_contents` (
   `group_id` int(10) unsigned NOT NULL,
   `member_id` int(10) unsigned NOT NULL,
+  `writer` tinyint(1) NOT NULL DEFAULT '1',
   PRIMARY KEY (`group_id`, `member_id`),
   INDEX `fk_group_contents_group_id_idx` (`group_id`),
   INDEX `fk_group_contents_member_id_idx` (`member_id`),
diff -urN setup.orig/pgsql.sql setup/pgsql.sql
--- setup.orig/pgsql.sql
+++ setup/pgsql.sql
@@ -189,6 +189,7 @@
 CREATE TABLE "group_contents" (
   "group_id" int NOT NULL,
   "member_id" int NOT NULL,
+  "writer" smallint NOT NULL DEFAULT '1' CHECK("smallint" BETWEEN 0 AND 1),
   PRIMARY KEY ("group_id","member_id"));
 CREATE INDEX "fk_group_contents_group_id_idx" ON "group_contents" ("group_id");
 CREATE INDEX "fk_group_contents_member_id_idx" ON "group_contents" ("member_id");
@Udera
Copy link
Collaborator

Udera commented Jan 7, 2024

Not sure about this feature, why not using a mailinglist (we have all the transports for mailman). It has much more options and integrates error handling (user gets a response about message status), ...

@VVD
Copy link
Author

VVD commented Jan 8, 2024

why not using a mailinglist

What "mailinglist"? Integration with mailman?

@rimas-kudelis
Copy link
Collaborator

why not using a mailinglist

What "mailinglist"? Integration with mailman?

That's what Udera's comment says, no?

@VVD
Copy link
Author

VVD commented Jan 8, 2024

I didn't understand his comment.
My english is poor.

@runout-at
Copy link
Contributor

runout-at commented Jan 8, 2024

Actually I did never use the group feature of vexim.

Mailman is a full blown real Mailing List System, not just a feature to address some mail addresses which are in a grouping.

Mailman2 was a good choice for mailing lists and not quite small. This has changed a lot in Mailman3 which needs a lot more resources and is overblown for my needs. When I tested it some years ago there were no easy migration path from MM2 to MM3 for existing lists.

Another good piece of software is mlmmj which is minimalistic and good choice if you don't need too many features. It integrates easily with Exim. Since I switched from MM2 to mlmmj I wrote a small API to manage mlmmj as I had the need to feed it automatically from a database: https://gitlab.com/runout/mlmmjapi

@VVD
Copy link
Author

VVD commented Jan 8, 2024

For more than a decade, the built-in group capabilities of vexim were enough for me. But a year ago I needed groups in which most of the participants were read-only. I don't need anything else from groups.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants