aboutsummaryrefslogtreecommitdiff
path: root/lib/models/MassMail/MassMailPermission.php
blob: 33af43d6363dc4e6262db777ccb4bf0cf0b8991a (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
<?php

namespace MassMail;

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;
    }

}