From 3002ed9e93ea39b7c341b0b3a24f0d4f654ef062 Mon Sep 17 00:00:00 2001
From: Igor Scheller <igor.scheller@igorshp.de>
Date: Tue, 29 Aug 2017 22:22:53 +0200
Subject: Security: Only allow angels with admin_news_html privilege to use
 HTML

---
 db/update.sql | 22 +++++++++++++---------
 1 file changed, 13 insertions(+), 9 deletions(-)

(limited to 'db/update.sql')

diff --git a/db/update.sql b/db/update.sql
index dd203a86..5d93e230 100644
--- a/db/update.sql
+++ b/db/update.sql
@@ -8,19 +8,23 @@ ALTER TABLE `User` ADD COLUMN `email_by_human_allowed` BOOLEAN NOT NULL;
 -- No Self Sign Up for some Angel Types
 ALTER TABLE AngelTypes ADD no_self_signup TINYINT(1) NOT NULL;
 
-ALTER TABLE `AngelTypes`  
-  ADD `contact_user_id` INT NULL,  
-  ADD `contact_name` VARCHAR(250) NULL,  
-  ADD `contact_dect` VARCHAR(5) NULL,  
-  ADD `contact_email` VARCHAR(250) NULL,  
+ALTER TABLE `AngelTypes`
+  ADD `contact_user_id` INT NULL,
+  ADD `contact_name` VARCHAR(250) NULL,
+  ADD `contact_dect` VARCHAR(5) NULL,
+  ADD `contact_email` VARCHAR(250) NULL,
   ADD INDEX  (`contact_user_id`);
-ALTER TABLE `AngelTypes` 
+ALTER TABLE `AngelTypes`
   ADD  FOREIGN KEY (`contact_user_id`) REFERENCES `User`(`UID`) ON DELETE SET NULL ON UPDATE CASCADE;
 
-  
 INSERT INTO `Privileges` (`id`, `name`, `desc`) VALUES (NULL, 'shiftentry_edit_angeltype_supporter', 'If user with this privilege is angeltype supporter, he can put users in shifts for their angeltype');
 
-
 -- DB Performance
 ALTER TABLE `Shifts` ADD INDEX(`start`);
-ALTER TABLE `NeededAngelTypes` ADD INDEX(`count`);
\ No newline at end of file
+ALTER TABLE `NeededAngelTypes` ADD INDEX(`count`);
+
+-- Security
+UPDATE `Groups` SET UID = UID * 10;
+INSERT INTO `Groups` (Name, UID) VALUES ('News Admin', -65);
+INSERT INTO `Privileges` (id, name, `desc`) VALUES (42, 'admin_news_html', 'Use HTML in news');
+INSERT INTO `GroupPrivileges` (group_id, privilege_id) VALUES (-65, 14), (-65, 42);
-- 
cgit v1.2.3-54-g00ecf


From e6ed8a30171b86b452cec21a283373fc14dd5330 Mon Sep 17 00:00:00 2001
From: Igor Scheller <igor.scheller@igorshp.de>
Date: Tue, 19 Sep 2017 19:33:24 +0200
Subject: Changed LogEntries table: Use log level instead of nick name

---
 db/update.sql                         |  3 +++
 includes/model/LogEntries_model.php   | 12 ++++++------
 includes/pages/admin_log.php          |  8 +++-----
 includes/sys_log.php                  |  6 ++++--
 phpunit.xml                           |  3 +++
 src/Logger/EngelsystemLogger.php      |  2 +-
 test/Logger/EngelsystemLoggerTest.php |  7 ++++++-
 test/model/LogEntriesModelTest.php    | 29 ++++++++++++-----------------
 test/model/RoomModelTest.php          | 17 +++++++----------
 9 files changed, 45 insertions(+), 42 deletions(-)

(limited to 'db/update.sql')

diff --git a/db/update.sql b/db/update.sql
index 5d93e230..3ed37ceb 100644
--- a/db/update.sql
+++ b/db/update.sql
@@ -28,3 +28,6 @@ UPDATE `Groups` SET UID = UID * 10;
 INSERT INTO `Groups` (Name, UID) VALUES ('News Admin', -65);
 INSERT INTO `Privileges` (id, name, `desc`) VALUES (42, 'admin_news_html', 'Use HTML in news');
 INSERT INTO `GroupPrivileges` (group_id, privilege_id) VALUES (-65, 14), (-65, 42);
+
+-- Add log level to LogEntries
+ALTER TABLE `LogEntries` CHANGE COLUMN `nick` `level` VARCHAR(20) NOT NULL;
diff --git a/includes/model/LogEntries_model.php b/includes/model/LogEntries_model.php
index 0e11bf8e..f0ee6673 100644
--- a/includes/model/LogEntries_model.php
+++ b/includes/model/LogEntries_model.php
@@ -5,16 +5,16 @@ use Engelsystem\Database\DB;
 /**
  * Creates a log entry.
  *
- * @param string $nick    Username
- * @param string $message Log  Message
+ * @param string $logLevel Log level
+ * @param string $message  Log  Message
  * @return bool
  */
-function LogEntry_create($nick, $message)
+function LogEntry_create($logLevel, $message)
 {
     return DB::insert('
-        INSERT INTO `LogEntries` (`timestamp`, `nick`, `message`)
+        INSERT INTO `LogEntries` (`timestamp`, `level`, `message`)
         VALUES(?, ?, ?)
-    ', [time(), $nick, $message]);
+    ', [time(), $logLevel, $message]);
 }
 
 /**
@@ -43,7 +43,7 @@ function LogEntries_filter($keyword)
     return DB::select('
             SELECT *
             FROM `LogEntries`
-            WHERE `nick` LIKE ?
+            WHERE `level` LIKE ?
             OR `message` LIKE ?
             ORDER BY `timestamp` DESC
         ',
diff --git a/includes/pages/admin_log.php b/includes/pages/admin_log.php
index 03c9abb0..694b1d5a 100644
--- a/includes/pages/admin_log.php
+++ b/includes/pages/admin_log.php
@@ -17,12 +17,10 @@ function admin_log()
     if (request()->has('keyword')) {
         $filter = strip_request_item('keyword');
     }
-    $log_entries_source = LogEntries_filter($filter);
+    $log_entries = LogEntries_filter($filter);
 
-    $log_entries = [];
-    foreach ($log_entries_source as $log_entry) {
+    foreach ($log_entries as &$log_entry) {
         $log_entry['date'] = date('d.m.Y H:i', $log_entry['timestamp']);
-        $log_entries[] = $log_entry;
     }
 
     return page_with_title(admin_log_title(), [
@@ -33,7 +31,7 @@ function admin_log()
         ]),
         table([
             'date'    => 'Time',
-            'nick'    => 'Angel',
+            'level'   => 'Type',
             'message' => 'Log Entry'
         ], $log_entries)
     ]);
diff --git a/includes/sys_log.php b/includes/sys_log.php
index c4ef890e..513586e6 100644
--- a/includes/sys_log.php
+++ b/includes/sys_log.php
@@ -9,10 +9,12 @@
 function engelsystem_log($message)
 {
     global $user;
-
     $nick = "Guest";
+    $logger = app('logger');
+
     if (isset($user)) {
         $nick = User_Nick_render($user);
     }
-    LogEntry_create($nick, $message);
+
+    $logger->info('{nick}: {message}', ['nick' => $nick, 'message' => $message]);
 }
diff --git a/phpunit.xml b/phpunit.xml
index ff6eb120..ee5ae3e8 100644
--- a/phpunit.xml
+++ b/phpunit.xml
@@ -7,6 +7,9 @@
         <testsuite name="Models">
             <directory>./test/model/</directory>
         </testsuite>
+        <testsuite name="Logger">
+            <directory>./test/Logger/</directory>
+        </testsuite>
     </testsuites>
     <filter>
         <whitelist>
diff --git a/src/Logger/EngelsystemLogger.php b/src/Logger/EngelsystemLogger.php
index db46215c..1f255b69 100644
--- a/src/Logger/EngelsystemLogger.php
+++ b/src/Logger/EngelsystemLogger.php
@@ -38,7 +38,7 @@ class EngelsystemLogger extends AbstractLogger
 
         $message = $this->interpolate($message, $context);
 
-        LogEntry_create('Logger: ' . $level, $message);
+        LogEntry_create($level, $message);
     }
 
     /**
diff --git a/test/Logger/EngelsystemLoggerTest.php b/test/Logger/EngelsystemLoggerTest.php
index da10800d..2219cdb2 100644
--- a/test/Logger/EngelsystemLoggerTest.php
+++ b/test/Logger/EngelsystemLoggerTest.php
@@ -66,7 +66,7 @@ class EngelsystemLoggerTest extends TestCase
 
         $entry = $this->getLastEntry();
         $this->assertEquals('My username is Foo', $entry['message']);
-        $this->assertContains(LogLevel::INFO, $entry['nick'], '', true);
+        $this->assertEquals(LogLevel::INFO, $entry['level']);
 
         foreach (
             [
@@ -123,4 +123,9 @@ class EngelsystemLoggerTest extends TestCase
 
         return $entry;
     }
+
+    public function tearDown()
+    {
+        LogEntries_clear_all();
+    }
 }
diff --git a/test/model/LogEntriesModelTest.php b/test/model/LogEntriesModelTest.php
index 25d46fc4..761725c4 100644
--- a/test/model/LogEntriesModelTest.php
+++ b/test/model/LogEntriesModelTest.php
@@ -1,37 +1,32 @@
 <?php
+
 namespace Engelsystem\Test;
 
-use \PHPUnit\Framework\TestCase;
+use PHPUnit\Framework\TestCase;
+use Psr\Log\LogLevel;
 
 class LogEntriesModelTest extends TestCase
 {
-
-    public function create_LogEntry()
-    {
-        LogEntry_create('test', 'test');
-    }
-
-    public function test_LogEntry_create()
+    public function testCreateLogEntry()
     {
+        LogEntries_clear_all();
         $count = count(LogEntries());
-        $this->assertNotFalse(LogEntry_create('test', 'test_LogEntry_create'));
-        
+        $this->assertNotFalse(LogEntry_create(LogLevel::WARNING, 'test_LogEntry_create'));
+
         // There should be one more log entry now
         $this->assertEquals(count(LogEntries()), $count + 1);
     }
 
-    public function test_LogEntries_clear_all()
+    public function testClearAllLogEntries()
     {
-        $this->create_LogEntry();
+        LogEntry_create(LogLevel::WARNING, 'test');
         $this->assertTrue(count(LogEntries()) > 0);
+
         $this->assertNotFalse(LogEntries_clear_all());
-        $this->assertEquals(count(LogEntries()), 0);
+        $this->assertCount(0, LogEntries());
     }
 
-    /**
-     * @after
-     */
-    public function teardown()
+    public function tearDown()
     {
         LogEntries_clear_all();
     }
diff --git a/test/model/RoomModelTest.php b/test/model/RoomModelTest.php
index 135a6108..4205845b 100644
--- a/test/model/RoomModelTest.php
+++ b/test/model/RoomModelTest.php
@@ -1,11 +1,11 @@
 <?php
+
 namespace Engelsystem\Test;
 
-use \PHPUnit\Framework\TestCase;
+use PHPUnit\Framework\TestCase;
 
 class RoomModelTest extends TestCase
 {
-
     private $room_id = null;
 
     public function create_Room()
@@ -16,20 +16,17 @@ class RoomModelTest extends TestCase
     public function test_Room()
     {
         $this->create_Room();
-        
+
         $room = Room($this->room_id);
-        
+
         $this->assertNotFalse($room);
         $this->assertNotNull($room);
         $this->assertEquals($room['Name'], 'test');
-        
-        $this->assertNull(Room(- 1));
+
+        $this->assertNull(Room(-1));
     }
 
-    /**
-     * @after
-     */
-    public function teardown()
+    public function tearDown()
     {
         if ($this->room_id != null) {
             Room_delete($this->room_id);
-- 
cgit v1.2.3-54-g00ecf


From d8476f244dd0ee1bccaab53f123fa12f2a9c9501 Mon Sep 17 00:00:00 2001
From: msquare <msquare@notrademark.de>
Date: Fri, 24 Nov 2017 10:02:52 +0100
Subject: complete feature contact info for angeltypes, fixes #275

---
 db/update.sql                                 |  4 ++
 includes/controller/angeltypes_controller.php |  4 ++
 includes/model/AngelType_model.php            | 69 +++++++--------------------
 includes/sys_template.php                     | 14 ++++++
 includes/view/AngelTypes_view.php             | 33 +++++++++++--
 5 files changed, 68 insertions(+), 56 deletions(-)

(limited to 'db/update.sql')

diff --git a/db/update.sql b/db/update.sql
index 3ed37ceb..c5187675 100644
--- a/db/update.sql
+++ b/db/update.sql
@@ -31,3 +31,7 @@ INSERT INTO `GroupPrivileges` (group_id, privilege_id) VALUES (-65, 14), (-65, 4
 
 -- Add log level to LogEntries
 ALTER TABLE `LogEntries` CHANGE COLUMN `nick` `level` VARCHAR(20) NOT NULL;
+
+-- Angeltype contact update
+ALTER TABLE `AngelTypes` DROP FOREIGN KEY angeltypes_ibfk_1;
+ALTER TABLE `AngelTypes` DROP `contact_user_id`;
\ No newline at end of file
diff --git a/includes/controller/angeltypes_controller.php b/includes/controller/angeltypes_controller.php
index 3e377fb0..eaaa9c0f 100644
--- a/includes/controller/angeltypes_controller.php
+++ b/includes/controller/angeltypes_controller.php
@@ -143,6 +143,10 @@ function angeltype_edit_controller()
 
         $angeltype['description'] = strip_request_item_nl('description', $angeltype['description']);
 
+        $angeltype['contact_name'] = strip_request_item('contact_name', $angeltype['contact_name']);
+        $angeltype['contact_dect'] = strip_request_item('contact_dect', $angeltype['contact_dect']);
+        $angeltype['contact_email'] = strip_request_item('contact_email', $angeltype['contact_email']);
+
         if ($valid) {
             if ($angeltype['id'] != null) {
                 AngelType_update($angeltype);
diff --git a/includes/model/AngelType_model.php b/includes/model/AngelType_model.php
index b51a6838..1f2c8c63 100644
--- a/includes/model/AngelType_model.php
+++ b/includes/model/AngelType_model.php
@@ -16,7 +16,6 @@ function AngelType_new()
         'no_self_signup'          => false,
         'description'             => '',
         'requires_driver_license' => false,
-        'contact_user_id'         => null,
         'contact_name'            => null,
         'contact_dect'            => null,
         'contact_email'           => null
@@ -24,53 +23,15 @@ function AngelType_new()
 }
 
 /**
- * Validates the contact user
- *
- * @param array $angeltype The angeltype
- * @return ValidationResult
+ * Checks if the angeltype has any contact information.
+ * 
+ * @param Angeltype $angeltype
+ * @return bool
  */
-function AngelType_validate_contact_user_id($angeltype)
-{
-    if (!isset($angeltype['contact_user_id'])) {
-        return new ValidationResult(true, null);
-    }
-    if (isset($angeltype['contact_name']) || isset($angeltype['contact_dect']) || isset($angeltype['contact_email'])) {
-        return new ValidationResult(false, $angeltype['contact_user_id']);
-    }
-    if (User($angeltype['contact_user_id']) == null) {
-        return new ValidationResult(false, $angeltype['contact_user_id']);
-    }
-    return new ValidationResult(true, $angeltype['contact_user_id']);
-}
-
-/**
- * Returns contact data (name, dect, email) for given angeltype or null
- *
- * @param array $angeltype The angeltype
- * @return array|null
- */
-function AngelType_contact_info($angeltype)
-{
-    if (isset($angeltype['contact_user_id'])) {
-        $contact_user = User($angeltype['contact_user_id']);
-        $contact_data = [
-            'contact_name' => $contact_user['Nick'],
-            'contact_dect' => $contact_user['DECT']
-        ];
-        if ($contact_user['email_by_human_allowed']) {
-            $contact_data['contact_email'] = $contact_user['email'];
-        }
-        return $contact_data;
-    }
-    if (isset($angeltype['contact_name'])) {
-        return [
-            'contact_name'  => $angeltype['contact_name'],
-            'contact_dect'  => $angeltype['contact_dect'],
-            'contact_email' => $angeltype['contact_email']
-        ];
-    }
-
-    return null;
+function AngelType_has_contact_info($angeltype) {
+    return !empty($angeltype['contact_name']) 
+        || !empty($angeltype['contact_dect']) 
+        || !empty($angeltype['contact_email']);
 }
 
 /**
@@ -102,7 +63,6 @@ function AngelType_update($angeltype)
           `description` = ?,
           `requires_driver_license` = ?,
           `no_self_signup` = ?,
-          `contact_user_id` = ?,
           `contact_name` = ?,
           `contact_dect` = ?,
           `contact_email` = ?
@@ -113,7 +73,6 @@ function AngelType_update($angeltype)
             $angeltype['description'],
             (int)$angeltype['requires_driver_license'],
             (int)$angeltype['no_self_signup'],
-            $angeltype['contact_user_id'],
             $angeltype['contact_name'],
             $angeltype['contact_dect'],
             $angeltype['contact_email'],
@@ -124,7 +83,10 @@ function AngelType_update($angeltype)
     engelsystem_log(
         'Updated angeltype: ' . $angeltype['name'] . ($angeltype['restricted'] ? ', restricted' : '')
         . ($angeltype['no_self_signup'] ? ', no_self_signup' : '')
-        . ($angeltype['requires_driver_license'] ? ', requires driver license' : '')
+        . ($angeltype['requires_driver_license'] ? ', requires driver license' : '') . ', '
+        . $angeltype['contact_name'] . ', '
+        . $angeltype['contact_dect'] . ', '
+        . $angeltype['contact_email']
     );
 }
 
@@ -143,7 +105,6 @@ function AngelType_create($angeltype)
               `description`,
               `requires_driver_license`,
               `no_self_signup`,
-              `contact_user_id`,
               `contact_name`,
               `contact_dect`,
               `contact_email`
@@ -156,7 +117,6 @@ function AngelType_create($angeltype)
             $angeltype['description'],
             (int)$angeltype['requires_driver_license'],
             (int)$angeltype['no_self_signup'],
-            $angeltype['contact_user_id'],
             $angeltype['contact_name'],
             $angeltype['contact_dect'],
             $angeltype['contact_email'],
@@ -167,7 +127,10 @@ function AngelType_create($angeltype)
     engelsystem_log(
         'Created angeltype: ' . $angeltype['name']
         . ($angeltype['restricted'] ? ', restricted' : '')
-        . ($angeltype['requires_driver_license'] ? ', requires driver license' : '')
+        . ($angeltype['requires_driver_license'] ? ', requires driver license' : '') . ', '
+        . $angeltype['contact_name'] . ', '
+        . $angeltype['contact_dect'] . ', '
+        . $angeltype['contact_email']
     );
     return $angeltype;
 }
diff --git a/includes/sys_template.php b/includes/sys_template.php
index a659a7f3..662283b1 100644
--- a/includes/sys_template.php
+++ b/includes/sys_template.php
@@ -211,6 +211,20 @@ function page_with_title($title, $elements)
     return '<div class="col-md-12"><h1>' . $title . '</h1>' . join($elements) . '</div>';
 }
 
+/**
+ * Renders a description based on the data arrays key and values as label an description.
+ * @param array $data
+ */
+function description($data) {
+    $elements = [];
+    foreach($data as $label => $description) {
+        if(!empty($label) && !empty($description)) {
+            $elements[] = '<dt>' . $label . '</dt><dd>' . $description . '</dd>';
+        }
+    }
+    return '<dl class="dl-horizontal">' . join($elements) . '</dl>';
+}
+
 /**
  * Rendert eine Datentabelle
  *
diff --git a/includes/view/AngelTypes_view.php b/includes/view/AngelTypes_view.php
index baf0e04a..6e70b3be 100644
--- a/includes/view/AngelTypes_view.php
+++ b/includes/view/AngelTypes_view.php
@@ -92,15 +92,20 @@ function AngelType_edit_view($angeltype, $supporter_mode)
                 _('Requires driver license'),
                 $angeltype['requires_driver_license']
             ),
-            //form_text('contact_name', _('Name'), $angeltype['contact_name']),
-            //form_text('contact_dect', _('DECT'), $angeltype['contact_dect']),
-            //form_text('contact_email', _('E-Mail'), $angeltype['contact_email']),
             form_info(
                 '',
                 _('Restricted angel types can only be used by an angel if enabled by a supporter (double opt-in).')
             ),
             form_textarea('description', _('Description'), $angeltype['description']),
             form_info('', _('Please use markdown for the description.')),
+            heading(_('Contact'), 3),
+            form_info(
+                '',
+                _('Primary contact person/desk for user questions.')
+            ),
+            form_text('contact_name', _('Name'), $angeltype['contact_name']),
+            form_text('contact_dect', _('DECT'), $angeltype['contact_dect']),
+            form_text('contact_email', _('E-Mail'), $angeltype['contact_email']),
             form_submit('submit', _('Save'))
         ])
     ]);
@@ -322,6 +327,10 @@ function AngelType_view(
         msg()
     ];
 
+    if(AngelType_has_contact_info($angeltype)) {
+        $page[] = AngelTypes_render_contact_info($angeltype);
+    }
+    
     $page[] = '<h3>' . _('Description') . '</h3>';
     $parsedown = new Parsedown();
     if ($angeltype['description'] != '') {
@@ -392,6 +401,20 @@ function AngelType_view(
     return page_with_title(sprintf(_('Team %s'), $angeltype['name']), $page);
 }
 
+/**
+ * Renders the contact info
+ * 
+ * @param Anteltype $angeltype
+ * @return string HTML
+ */
+function AngelTypes_render_contact_info($angeltype) {
+    return heading(_('Contact'), 3) . description([
+        _('Name') => $angeltype['contact_name'],
+        _('DECT') => $angeltype['contact_dect'],
+        _('E-Mail') => $angeltype['contact_email']
+    ]);
+}
+
 /**
  * Display the list of angeltypes.
  *
@@ -431,6 +454,10 @@ function AngelTypes_about_view_angeltype($angeltype)
 
     $html = '<h2>' . $angeltype['name'] . '</h2>';
 
+    if(AngelType_has_contact_info($angeltype)) {
+        $html .= AngelTypes_render_contact_info($angeltype);
+    }
+
     if (isset($angeltype['user_angeltype_id'])) {
         $buttons = [];
         if ($angeltype['user_angeltype_id'] != null) {
-- 
cgit v1.2.3-54-g00ecf

