aboutsummaryrefslogtreecommitdiff
path: root/lib/models/MassMail/MassMailPermission.php
blob: a5edd4a7c14653f4907f1054310dcb48b8a44373 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
<?php

namespace MassMail;

/**
 * @license GPL2 or any later version
 *
 * @property int $id alias column for permission_id
 * @property int $permission_id database column
 * @property string $institute_id database column
 * @property string $min_perm database column
 * @property int $mkdate database column
 * @property int $chdate database column
 * @property \Institute $institute belongs_to \Institute
 * @property \SimpleORMapCollection<\Degree> $allowed_degrees has_and_belongs_to_many \Degree
 * @property \SimpleORMapCollection<\StudyCourse> $allowed_subjects has_and_belongs_to_many \StudyCourse
 * @property \SimpleORMapCollection<\Institute> $allowed_institutes has_and_belongs_to_many \Institute
 * @property-read mixed $institute_name additional field
 */
class MassMailPermission extends \SimpleORMap
{

    public const MASSMAIL_ROOT_ROLE = 'Massenmail-Root';

    protected static function configure($config = [])
    {
        $config['db_table'] = 'massmail_permissions';

        $config['belongs_to']['institute'] = [
            'class_name' => \Institute::class,
            'foreign_key' => 'institute_id',
            'assoc_foreign_key' => 'institut_id'
        ];

        $config['has_and_belongs_to_many']['allowed_degrees'] = [
            'class_name' => \Degree::class,
            'thru_table' => 'massmail_permission_degree',
            'thru_key' => 'permission_id',
            'thru_assoc_key' => 'degree_id',
            'on_store' => 'store',
            'on_delete' => 'delete'
        ];

        $config['has_and_belongs_to_many']['allowed_subjects'] = [
            'class_name' => \StudyCourse::class,
            'thru_table' => 'massmail_permission_subject',
            'thru_key' => 'permission_id',
            'thru_assoc_key' => 'subject_id',
            'on_store' => 'store',
            'on_delete' => 'delete'
        ];

        $config['has_and_belongs_to_many']['allowed_institutes'] = [
            'class_name' => \Institute::class,
            'thru_table' => 'massmail_permission_institute',
            'thru_key' => 'permission_id',
            'thru_assoc_key' => 'institute_id',
            'on_store' => 'store',
            'on_delete' => 'delete'
        ];

        $config['additional_fields']['institute_name']['get'] = function($p) {
            return $p->institute->name;
        };

        parent::configure($config);
    }

    /**
     * Check if the given user has permissions to write mass mails. The result is cached for performance reasons.
     *
     * @param string $user_id user to check
     * @param bool $unrestricted check for unrestricted permissions
     * @return bool
     */
    public static function has(string $user_id, bool $unrestricted = false) : bool
    {
        $cached = \Studip\Cache\Factory::getCache()->read('massmail-permission-' . $user_id);

        if ($cached !== false) {
            $perm = (int) $cached;
        } else {

            $perm = 0;

            // Root and users with the massmeil root role are always allowed to do anything.
            if (
                $GLOBALS['perm']->have_perm('root', $user_id)
                || \RolePersistence::isAssignedRole($user_id, static::MASSMAIL_ROOT_ROLE)
            ) {
                $perm = 2;

                // Everyone else needs at least one institute assignment with existing permissions.
            } else {
                // Institute memberships with existing mass mail permission settings.
                $relevant = static::findBySQL(
                    "JOIN `user_inst` ON (`user_inst`.`institut_id` = `massmail_permissions`.`institute_id`)
                    WHERE `user_inst`.`inst_perms` != 'user' AND `user_inst`.`user_id` = :user",
                    ['user' => $user_id]
                );
                foreach ($relevant as $one) {
                    if ($GLOBALS['perm']->have_studip_perm($one->min_perm, $one->institute_id, $user_id)) {
                        $perm = 1;
                        break;
                    }
                }
            }

            \Studip\Cache\Factory::getCache()->write('massmail-permission-' . $user_id, $perm);
        }

        return $unrestricted ? $perm === 2 : $perm >= 1;
    }

    /**
     * @return array{
     *     allowed_degrees: array,
     *     allowed_subjects: array,
     *     allowed_institutes: array
     * }
     */
    public static function getForUser(\User $user, bool $withNames = false): array
    {
        // Get user's institutes with at least autor permission.
        $institutes = $user->institute_memberships->filter(function ($membership) {
            return in_array($membership->inst_perms, ['autor', 'tutor', 'dozent', 'admin']);
        })->pluck($withNames ? 'institut_id institute_name' : 'institut_id');

        // Get permission configuration for these institutes.
        $permissions = static::findBySQL("`institute_id` IN (:institutes)", ['institutes' => $institutes]);
        $config = [
            'allowed_degrees' => [],
            'allowed_subjects' => [],
            'allowed_institutes' => $institutes
        ];
        foreach ($permissions as $permission) {
            $config['allowed_degrees'] = array_merge(
                $config['allowed_degrees'],
                $permission->allowed_degrees->pluck($withNames ? 'id name' : 'id')
            );
            $config['allowed_subjects'] = array_merge(
                $config['allowed_subjects'],
                $permission->allowed_subjects->pluck($withNames ? 'id name' : 'id')
            );
            $config['allowed_institutes'] = array_merge(
                $config['allowed_institutes'],
                $permission->allowed_institutes->pluck($withNames ? 'id name' : 'id')
            );
        }

        return $config;
    }

}