Issues (73)

Security Analysis    no request data  

This project does not seem to handle request data directly as such no vulnerable execution paths were found.

  File Inclusion
File Inclusion enables an attacker to inject custom files into PHP's file loading mechanism, either explicitly passed to include, or for example via PHP's auto-loading mechanism.
  Regex Injection
Regex Injection enables an attacker to execute arbitrary code in your PHP process.
  SQL Injection
SQL Injection enables an attacker to execute arbitrary SQL code on your database server gaining access to user data, or manipulating user data.
  Response Splitting
Response Splitting can be used to send arbitrary responses.
  File Manipulation
File Manipulation enables an attacker to write custom data to files. This potentially leads to injection of arbitrary code on the server.
  Object Injection
Object Injection enables an attacker to inject an object into PHP code, and can lead to arbitrary code execution, file exposure, or file manipulation attacks.
  File Exposure
File Exposure allows an attacker to gain access to local files that he should not be able to access. These files can for example include database credentials, or other configuration files.
  XML Injection
XML Injection enables an attacker to read files on your local filesystem including configuration files, or can be abused to freeze your web-server process.
  Code Injection
Code Injection enables an attacker to execute arbitrary code on the server.
  Variable Injection
Variable Injection enables an attacker to overwrite program variables with custom data, and can lead to further vulnerabilities.
  XPath Injection
XPath Injection enables an attacker to modify the parts of XML document that are read. If that XML document is for example used for authentication, this can lead to further vulnerabilities similar to SQL Injection.
  Other Vulnerability
This category comprises other attack vectors such as manipulating the PHP runtime, loading custom extensions, freezing the runtime, or similar.
  Command Injection
Command Injection enables an attacker to inject a shell command that is execute with the privileges of the web-server. This can be used to expose sensitive data, or gain access of your server.
  LDAP Injection
LDAP Injection enables an attacker to inject LDAP statements potentially granting permission to run unauthorized queries, or modify content inside the LDAP tree.
  Cross-Site Scripting
Cross-Site Scripting enables an attacker to inject code into the response of a web-request that is viewed by other users. It can for example be used to bypass access controls, or even to take over other users' accounts.
  Header Injection
Unfortunately, the security analysis is currently not available for your project. If you are a non-commercial open-source project, please contact support to gain access.

code/models/SlackInvite.php (18 issues)

1
<?php
2
3
4
/**
5
 * Class SlackInvite
6
 *
7
 * @property string $Name
8
 * @property string $Email
9
 * @property boolean $Invited
10
 * @property string $Message
11
 */
12
class SlackInvite extends DataObject implements PermissionProvider
0 ignored issues
show
The type DataObject was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
The type PermissionProvider was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
13
{
14
    private static $db = [
15
        'Name'    => 'Varchar(255)',
16
        'Email'   => 'Varchar(255)',
17
        'Invited' => 'Boolean(false)',
18
        'Message' => 'Varchar(255)',
19
    ];
20
21
    private static $summary_fields = [
22
        'Created',
23
        'Name',
24
        'Email',
25
        'Invited.Nice',
26
        'Message'
27
    ];
28
29
    private static $field_labels = [
30
        'Created'      => 'Invite requested on',
31
        'Name'         => 'Name',
32
        'Email'        => 'Email address',
33
        'Invited.Nice' => 'Invite successful'
34
    ];
35
36
    private static $messages = [
37
        'not_authed'        => 'No valid Slack Token provided, please check your settings',
38
        'already_invited'   => 'User has already received an email invitation',
39
        'already_in_team'   => 'User is already part of the team',
40
        'channel_not_found' => 'Provided channel ID does not match an existing channel in your workspace',
41
        'sent_recently'     => 'When using resend=true, the email has been sent recently already',
42
        'user_disabled'     => 'User account has been deactivated',
43
        'missing_scope'     => 'Using an access_token not authorized for "client" scope',
44
        'invalid_email'     => 'Invalid email address (e.g. "qwe"). Note that Slack does not recognize some email addresses even though they are technically valid. This is a known issue.',
45
        'not_allowed'       => 'When SSO is enabeld this method can not be used to invite new users except guests. The SCIM API needs to be used instead to invite new users. '
46
    ];
47
48
    private static $better_buttons_actions = [
0 ignored issues
show
The property $better_buttons_actions is not used and could be removed.

This check marks private properties in classes that are never used. Those properties can be removed.

Loading history...
49
        'resendInvite'
50
    ];
51
52
    public function getCMSFields()
53
    {
54
        $fields = parent::getCMSFields();
55
        $fields->removeByName(['Invited']);
56
        if (!$this->Invited) {
57
            $fields->addFieldToTab(
58
                'Root.Main',
59
                LiteralField::create(
0 ignored issues
show
The type LiteralField was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
60
                    'resend',
61
                    _t('SlackInvite.Resend', '<p>To resend an invite, click the resend button in the overview</p>')
0 ignored issues
show
The function _t was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

61
                    /** @scrutinizer ignore-call */ 
62
                    _t('SlackInvite.Resend', '<p>To resend an invite, click the resend button in the overview</p>')
Loading history...
62
                )
63
            );
64
        }
65
        $fields->addFieldToTab('Root.Main', ReadonlyField::create('Message', 'API Message'));
0 ignored issues
show
The type ReadonlyField was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
66
        $fields->addFieldToTab(
67
            'Root.Main',
68
            ReadonlyField::create('InvitedStatus', 'Invite successful', $this->dbObject('Invited')->Nice())
69
        );
70
71
        return $fields;
72
    }
73
74
    /**
75
     * If BetterButtons is installed, add a button to resend or retry
76
     * @return mixed
77
     */
78
    public function getBetterButtonsActions()
79
    {
80
        $fields = parent::getBetterButtonsActions();
81
        if ($this->Invited) {
82
            $fields->push(
83
                BetterButtonCustomAction::create('resendInvite', 'Resend')
0 ignored issues
show
The type BetterButtonCustomAction was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
84
                ->setRedirectType(BetterButtonCustomAction::REFRESH)
85
            );
86
        } else {
87
            $fields->push(
88
                BetterButtonCustomAction::create('resendInvite', 'Retry')
89
                ->setRedirectType(BetterButtonCustomAction::REFRESH)
90
            );
91
        }
92
93
        return $fields;
94
    }
95
96
    /**
97
     * If the user isn't invited yet, send out the invite
98
     * @throws ValidationException
99
     */
100
    public function onBeforeWrite()
101
    {
102
        parent::onBeforeWrite();
103
        // Only attempt to send when there is no ID
104
        // This prevents retrying from the CMS from ending up in an endless loop
105
        if (!$this->ID) {
106
            $this->inviteUser();
107
        }
108
    }
109
110
111
    /**
112
     * This method is public, so it can be addressed from the CMS.
113
     *
114
     * @param bool $resend
115
     * @throws ValidationException
116
     */
117
    public function inviteUser($resend = false)
118
    {
119
        /** @var SiteConfig $config */
120
        $config = SiteConfig::current_site_config();
0 ignored issues
show
The type SiteConfig was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
121
        // Break if there is a configuration error
122
        if (!$config->SlackURL || !$config->SlackToken || !$config->SlackChannel) {
123
            $this->Invited = false;
124
        } else {
125
            /** @var RestfulService $service with an _uncached_ response */
126
            $params = [
127
                'token'      => $config->SlackToken,
128
                'type'       => 'post',
129
                'email'      => $this->Email,
130
                'set_active' => true,
131
                'channel'    => $config->SlackChannel,
132
                'scope'      => 'identify,read,post,client',
133
            ];
134
135
            if ($resend) {
136
                $params['resend'] = true;
137
            }
138
            if ($this->Name) {
139
                $params['first_name'] = $this->Name;
140
            }
141
142
            $this->doRequestEmail($config, $params);
143
        }
144
    }
145
146
147
    /**
148
     * @param SiteConfig $config
149
     * @param array $params
150
     * @return bool|$this
151
     * @throws \ValidationException
152
     */
153
    private function doRequestEmail($config, $params)
154
    {
155
        $now = time();
156
        $service = RestfulService::create($config->SlackURL, 0);
0 ignored issues
show
The type RestfulService was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
157
158
        $response = $service->request('/api/users.admin.invite?t=' . $now, 'POST', $params);
159
        $result = Convert::json2array($response->getBody());
0 ignored issues
show
The type Convert was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
160
161
        if (isset($result['error'])) {
162
            /** @noinspection PhpParamsInspection */
163
            SS_Log::log($result['error'], SS_Log::ERR);
0 ignored issues
show
The type SS_Log was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
164
            $this->Message = static::$messages[$result['error']];
0 ignored issues
show
Since $messages is declared private, accessing it with static will lead to errors in possible sub-classes; you can either use self, or increase the visibility of $messages to at least protected.
Loading history...
165
166
            if ($result['error'] === 'already_invited' || $result['error'] === 'already_in_team') {
167
                $this->Message .= '; Invite successful';
168
                $this->Invited = true;
169
            }
170
        } else {
171
            $this->Message = 'Invite successful';
172
            $this->Invited = (bool)$result['ok'];
173
        }
174
175
        if ($this->Invited) {
176
            $this->deleteDuplicates();
177
        }
178
179
        $isModelAdmin = Controller::curr() instanceof ModelAdmin;
0 ignored issues
show
The type Controller was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
The type ModelAdmin was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
180
        /*
181
         * Only write here if we're in the CMS, don't write if the invite failed
182
         * As that will cause a possible infinite loop
183
         */
184
        if ((bool)$this->Invited === true && $isModelAdmin) {
185
            $this->write();
186
187
            return $this->Message;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->Message also could return the type string which is incompatible with the documented return type boolean|SlackInvite.
Loading history...
188
        } elseif ($isModelAdmin) {
189
            return $this->Message;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->Message also could return the type string which is incompatible with the documented return type boolean|SlackInvite.
Loading history...
190
        }
191
192
        return $this;
193
    }
194
195
    /**
196
     * Remove duplicates after a successful invite
197
     */
198
    public function deleteDuplicates()
199
    {
200
        /** @var DataList|SlackInvite[] $thisDuplicates */
201
        $thisDuplicates = static::get()
202
            ->filter(['Email' => $this->Email, 'Invited' => false])
203
            ->exclude(['ID' => $this->ID]);
204
205
        if ($this->Invited === true && $thisDuplicates->count() > 0) {
206
            // This user tried multiple times, now that Invited is true, let's delete the others
207
            $thisDuplicates->removeAll();
208
        }
209
    }
210
211
    /**
212
     * Re-send this invite
213
     * @throws ValidationException
214
     */
215
    public function resendInvite()
216
    {
217
        // Resend the invite. If the user has been invited before it should re-send
218
        // The instance is needed so we know if we should write inside the `inviteUser` method
219
        $this->inviteUser((bool)$this->Invited);
220
    }
221
222
    /**
223
     * Permissions
224
     *
225
     * @return array
226
     */
227
    public function providePermissions()
228
    {
229
        return [
230
            'EDIT_SLACKINVITE'   => [
231
                'name'     => _t('SlackInvite.PERMISSION_EDIT_DESCRIPTION', 'Edit Slack invites'),
0 ignored issues
show
The function _t was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

231
                'name'     => /** @scrutinizer ignore-call */ _t('SlackInvite.PERMISSION_EDIT_DESCRIPTION', 'Edit Slack invites'),
Loading history...
232
                'category' => _t('Permissions.SLACK_SLACKINVITE', 'Slack permissions'),
233
                'help'     => _t(
234
                    'SlackInvite.PERMISSION_EDIT_HELP',
235
                    'Permission required to edit existing Slack invites.'
236
                )
237
            ],
238
            'DELETE_SLACKINVITE' => [
239
                'name'     => _t('SlackInvite.PERMISSION_DELETE_DESCRIPTION', 'Delete Slack invites'),
240
                'category' => _t('Permissions.SLACK_SLACKINVITE', 'Slack permissions'),
241
                'help'     => _t(
242
                    'SlackInvite.PERMISSION_DELETE_HELP',
243
                    'Permission required to delete existing Slack invites.'
244
                )
245
            ],
246
            'VIEW_SLACKINVITE'   => [
247
                'name'     => _t('SlackInvite.PERMISSION_VIEW_DESCRIPTION', 'View Slack invites'),
248
                'category' => _t('Permissions.SLACK_SLACKINVITE', 'Slack permissions'),
249
                'help'     => _t(
250
                    'SlackInvite.PERMISSION_VIEW_HELP',
251
                    'Permission required to view existing Slack invites.'
252
                )
253
            ],
254
        ];
255
    }
256
257
258
    /**
259
     * Don't create them from the CMS
260
     * {@inheritdoc}
261
     */
262
    public function canCreate($member = null, $context = [])
263
    {
264
        return false;
265
    }
266
267
    /**
268
     * Edit is useful for if someone mis-typed it's email address
269
     * {@inheritdoc}
270
     */
271
    public function canEdit($member = null)
272
    {
273
        return Permission::checkMember($member, array('EDIT_SLACKINVITE', 'CMS_ACCESS_SlackInviteAdmin'));
0 ignored issues
show
The type Permission was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
274
    }
275
276
    /**
277
     * {@inheritdoc}
278
     */
279
    public function canDelete($member = null)
280
    {
281
        return Permission::checkMember($member, array('DELETE_SLACKINVITE', 'CMS_ACCESS_SlackInviteAdmin'));
282
    }
283
284
    /**
285
     * {@inheritdoc}
286
     */
287
    public function canView($member = null)
288
    {
289
        return Permission::checkMember($member, array('VIEW_SLACKINVITE', 'CMS_ACCESS_SlackInviteAdmin'));
290
    }
291
}
292