Issues (76)

Security Analysis    no request data  

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

  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.
  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.
  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.
  Code Injection
Code Injection enables an attacker to execute arbitrary code on the server.
  Response Splitting
Response Splitting can be used to send arbitrary responses.
  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.
  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.
  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.
  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.
  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.
  Header Injection
  Other Vulnerability
This category comprises other attack vectors such as manipulating the PHP runtime, loading custom extensions, freezing the runtime, or similar.
  Regex Injection
Regex Injection enables an attacker to execute arbitrary code in your PHP process.
  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.
  Variable Injection
Variable Injection enables an attacker to overwrite program variables with custom data, and can lead to further vulnerabilities.
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.

src/Http/Controllers/MessagesController.php (28 issues)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
3
namespace ReliQArts\Mardin\Http\Controllers;
4
5
use Carbon\Carbon;
6
use League\Fractal;
7
use Illuminate\Http\Request;
8
use ReliQArts\Mardin\Contracts\User;
9
use ReliQArts\Mardin\Contracts\Thread;
10
use ReliQArts\Mardin\Contracts\Message;
11
use ReliQArts\Mardin\Events\NewMessage;
12
// use ReliQArts\Mardin\Events\NewMessage;
13
use ReliQArts\Mardin\Contracts\Participant;
14
use Illuminate\Routing\Controller as BaseController;
15
use ReliQArts\Mardin\Transformers\ThreadTransformer;
16
use ReliQArts\Mardin\Transformers\MessageTransformer;
17
use Illuminate\Foundation\Validation\ValidatesRequests;
18
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
19
20
class MessagesController extends BaseController
21
{
22
    use AuthorizesRequests, ValidatesRequests;
23
24
    /**
25
     * Thread model.
26
     * @var Thread
27
     */
28
    protected $threads;
29
30
    /**
31
     * Message model.
32
     * @var Message
33
     */
34
    protected $messages;
35
36
    /**
37
     * Participant model.
38
     * @var Participant
39
     */
40
    protected $participants;
41
42
    /**
43
     * User model.
44
     * @var User
45
     */
46
    protected $users;
47
48
    /**
49
     * Fractal manager instance.
50
     * @var Fractal\Manager
51
     */
52
    protected $fractal;
53
54
    /**
55
     * Constructor.
56
     */
57
    public function __construct(Thread $threads, Message $messages, User $users, Participant $participants)
58
    {
59
        $this->threads = $threads;
60
        $this->messages = $messages;
61
        $this->users = $users;
62
        $this->participants = $participants;
63
        $this->fractal = new Fractal\Manager;
64
    }
65
66
    /**
67
     * Show all of the message threads to the user.
68
     *
69
     * @return mixed
70
     */
71
    public function index()
72
    {
73
        $this->authorize('receive', resolve(Message::class));
74
75
        $currentUserId = auth()->user()->id;
76
        $title = 'Inbox';
77
78
        // All threads that user is participating in
79
        $threads = $this->threads->forUser($currentUserId)->get();
0 ignored issues
show
The method forUser() does not seem to exist on object<ReliQArts\Mardin\Contracts\Thread>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
80
81
        return view(config('mardin.views.wrappers.index'), compact('threads', 'currentUserId', 'title'));
82
    }
83
84
    /**
85
     * Shows a message thread.
86
     *
87
     * @param Thread $thread
88
     * @return mixed
89
     */
90
    public function show(Thread $thread)
91
    {
92
        $this->authorize('receive', resolve(Message::class));
93
94
        // don't show the current user in list
95
        $userId = auth()->user()->id;
96
        $otherUsersIds = array_except($thread->participantsUserIds(), [$userId]);
97
        $users = $this->users->whereIn('id', $otherUsersIds)->get();
0 ignored issues
show
The method whereIn() does not seem to exist on object<ReliQArts\Mardin\Contracts\User>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
98
        $title = "{$thread->subject} &mdash; Inbox";
0 ignored issues
show
Accessing subject on the interface ReliQArts\Mardin\Contracts\Thread suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
99
100
        if (! $users->count()) {
101
            $errorMessage = 'Could not load thread. Participants error.';
102
103
            return redirect()->back()->with([
104
                'message' => $errorMessage,
105
                'error' => $errorMessage,
106
                'status' => $errorMessage,
107
            ]);
108
        }
109
110
        $thread->markAsRead($userId);
111
        unset($thread->deleted_at);
112
113
        return view(config('mardin.views.wrappers.show'), compact('thread', 'users', 'title'));
114
    }
115
116
    /**
117
     * Creates a new message thread.
118
     *
119
     * @return mixed
120
     */
121
    public function create(Request $request)
122
    {
123
        $this->authorize('send', resolve(Message::class));
124
125
        $users = $this->users->where('id', '!=', auth()->id())->get();
0 ignored issues
show
The method where() does not seem to exist on object<ReliQArts\Mardin\Contracts\User>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
126
        $title = $request->subject ?: 'New Conversation';
127
        $subject = $request->subject ?: 'New Conversation';
128
        $recipients = $request->recipients ?: [];
129
        $infoLine = 'New Conversation';
130
131
        if (count($recipients)) {
132
            $recipientNames = $this->users->whereIn('id', $recipients)->get()->map(function ($r) {
0 ignored issues
show
The method whereIn() does not seem to exist on object<ReliQArts\Mardin\Contracts\User>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
133
                return $r->name;
134
            })->toArray();
135
            $recipientNames = implode(', ', $recipientNames);
136
137
            if ($request->isOffer) {
138
                $infoLine = "Offer to $recipientNames";
139
            } else {
140
                $infoLine = "Between $recipientNames and You";
141
            }
142
        }
143
144
        return view(config('mardin.views.wrappers.show'), compact('users', 'title', 'recipients', 'subject', 'infoLine'));
0 ignored issues
show
This line exceeds maximum limit of 120 characters; contains 122 characters

Overly long lines are hard to read on any screen. Most code styles therefor impose a maximum limit on the number of characters in a line.

Loading history...
145
    }
146
147
    /**
148
     * Stores a new message thread.
149
     *
150
     * @param  Illuminate\Http\Request $request
0 ignored issues
show
Should the type for parameter $request not be Request?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
151
     * @return mixed
152
     */
153
    public function store(Request $request)
154
    {
155
        if (! $request->ajax()) {
156
            abort(404);
157
        }
158
159
        $this->authorize('send', resolve(Message::class));
160
161
        $thread = $this->threads->create([
0 ignored issues
show
The method create() does not seem to exist on object<ReliQArts\Mardin\Contracts\Thread>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
162
            'subject' => $request->subject,
163
        ]);
164
165
        // Message
166
        $message = $this->messages->create(
0 ignored issues
show
The method create() does not seem to exist on object<ReliQArts\Mardin\Contracts\Message>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
167
            [
168
                'thread_id' => $thread->id,
169
                'user_id'   => auth()->user()->id,
170
                'body'      => $request->message,
171
            ]
172
        );
173
174
        // Sender
175
        $this->participants->create([
0 ignored issues
show
The method create() does not seem to exist on object<ReliQArts\Mardin\Contracts\Participant>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
176
            'thread_id' => $thread->id,
177
            'user_id'   => auth()->user()->id,
178
            'last_read' => new Carbon,
179
        ]);
180
181
        // Recipients
182
        if ($request->has('recipients')) {
183
            $thread->addParticipant($request->recipients);
184
        }
185
186
        event(new NewMessage($message));
187
        $resource = new Fractal\Resource\Item($message, new MessageTransformer);
188
        $this->fractal->parseIncludes('thread');
189
190
        return $this->fractal->createData($resource)->toArray();
191
    }
192
193
    /**
194
     * Adds a new message to a current thread.
195
     *
196
     * @param  Illuminate\Http\Request $request
0 ignored issues
show
Should the type for parameter $request not be Request?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
197
     * @param $id
198
     * @return mixed
199
     */
200
    public function update(Request $request, Thread $thread)
201
    {
202
        if (! $request->ajax()) {
203
            abort(404);
204
        }
205
206
        $this->authorize('send', resolve(Message::class));
207
208
        $thread->activateAllParticipants();
209
210
        // Message
211
        $message = $this->messages->create([
0 ignored issues
show
The method create() does not seem to exist on object<ReliQArts\Mardin\Contracts\Message>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
212
            'thread_id' => $thread->id,
0 ignored issues
show
Accessing id on the interface ReliQArts\Mardin\Contracts\Thread suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
213
            'user_id'   => auth()->id(),
214
            'body'      => $request->message,
215
        ]);
216
217
        // Add replier as a participant
218
        $participant = $this->participants->firstOrCreate([
0 ignored issues
show
The method firstOrCreate() does not seem to exist on object<ReliQArts\Mardin\Contracts\Participant>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
219
            'thread_id' => $thread->id,
0 ignored issues
show
Accessing id on the interface ReliQArts\Mardin\Contracts\Thread suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
220
            'user_id'   => auth()->user()->id,
221
        ]);
222
        $participant->last_read = new Carbon;
223
        $participant->save();
224
225
        // Recipients
226
        if ($request->has('recipients')) {
227
            $thread->addParticipant($request->recipients);
228
        }
229
230
        event(new NewMessage($message));
231
        $resource = new Fractal\Resource\Item($message, new MessageTransformer);
232
        $this->fractal->parseIncludes('thread');
233
234
        return $this->fractal->createData($resource)->toArray();
235
    }
236
237
    /**
238
     * Mark a specific thread as read, for ajax use.
239
     *
240
     * @param $id
241
     */
242 View Code Duplication
    public function read(Request $request)
0 ignored issues
show
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
243
    {
244
        if (! $request->ajax()) {
245
            abort(404);
246
        }
247
248
        if ($threadIds = $request->threads) {
249
            $threads = $this->threads->whereIn('id', $threadIds)->get();
0 ignored issues
show
The method whereIn() does not seem to exist on object<ReliQArts\Mardin\Contracts\Thread>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
250
            foreach ($threads as $thread) {
251
                $thread->markAsRead(auth()->id());
252
            }
253
            $collection = new Fractal\Resource\Collection($threads, new ThreadTransformer);
254
255
            return $this->fractal->createData($collection)->toArray();
256
        }
257
    }
258
259
    /**
260
     * Mark a specific thread as unread, for ajax use.
261
     *
262
     * @param $id
263
     */
264 View Code Duplication
    public function unread(Request $request)
0 ignored issues
show
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
265
    {
266
        if (! $request->ajax()) {
267
            abort(404);
268
        }
269
270
        if ($threadIds = $request->threads) {
271
            $threads = $this->threads->whereIn('id', $threadIds)->get();
0 ignored issues
show
The method whereIn() does not seem to exist on object<ReliQArts\Mardin\Contracts\Thread>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
272
            foreach ($threads as $thread) {
273
                $thread->markAsUnread(auth()->id());
274
            }
275
            $collection = new Fractal\Resource\Collection($threads, new ThreadTransformer);
276
277
            return $this->fractal->createData($collection)->toArray();
278
        }
279
    }
280
281
    /**
282
     * Delete a thread, for ajax use.
283
     *
284
     * @param $id
285
     */
286
    public function delete(Request $request)
0 ignored issues
show
The return type could not be reliably inferred; please add a @return annotation.

Our type inference engine in quite powerful, but sometimes the code does not provide enough clues to go by. In these cases we request you to add a @return annotation as described here.

Loading history...
287
    {
288
        if (! $request->ajax()) {
289
            abort(404);
290
        }
291
292
        if ($threadIds = $request->threads) {
293
            return $threads = $this->threads->whereIn('id', $threadIds)->delete();
0 ignored issues
show
The method whereIn() does not seem to exist on object<ReliQArts\Mardin\Contracts\Thread>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
$threads is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
294
        }
295
    }
296
297
    /**
298
     * Get the number of unread threads, for ajax use.
299
     *
300
     * @return array
301
     */
302
    public function unreadCount()
303
    {
304
        $count = auth()->user()->newMessagesCount();
305
306
        return ['msg_count' => $count];
307
    }
308
309
    /**
310
     * Get threads for user. (inbox).
311
     *
312
     * @param Illuminate\Http\Request $request
0 ignored issues
show
Should the type for parameter $request not be Request?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
313
     * @param string $filter Filter messages for inbox.
314
     */
315
    public function inboxData(Request $request, $filter = 'all')
316
    {
317
        if (! $request->ajax()) {
318
            abort(404);
319
        }
320
321
        $userId = $request->user()->id;
322
        $threads = $this->threads;
323
324
        switch ($filter) {
325
            case 'new':
326
            case 'unread':
327
                $threads = $threads->forUserWithNewMessages($userId)->latest('updated_at')->get();
0 ignored issues
show
The method forUserWithNewMessages() does not seem to exist on object<ReliQArts\Mardin\Contracts\Thread>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
328
                break;
329
            default:
330
                $threads = $threads->forUser($userId)->latest('updated_at')->get();
0 ignored issues
show
The method forUser() does not seem to exist on object<ReliQArts\Mardin\Contracts\Thread>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
331
                break;
332
        }
333
334
        $collection = new Fractal\Resource\Collection($threads, new ThreadTransformer);
335
336
        return $this->fractal->createData($collection)->toArray();
337
    }
338
339
    /**
340
     * Get messgges for thread. (inbox).
341
     *
342
     * @param  Illuminate\Http\Request $request
0 ignored issues
show
Should the type for parameter $request not be Request?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
343
     * @param string $thread Thread to get messages for.
0 ignored issues
show
Should the type for parameter $thread not be Thread?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
344
     */
345
    public function threadMessagesData(Request $request, Thread $thread)
346
    {
347
        if (! $request->ajax()) {
348
            abort(404);
349
        }
350
351
        $userId = $request->user()->id;
0 ignored issues
show
$userId is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
352
        $limit = $request->limit ?: 200;
353
        $page = $request->p ?: 1;
354
355
        $messages = $thread->messages()->skip($page - 1)->take($limit)->get();
356
        $thread = new Fractal\Resource\Item($thread, new ThreadTransformer);
357
        $messages = new Fractal\Resource\Collection($messages, new MessageTransformer);
358
359
        return [
360
            'messages' => $this->fractal->createData($messages)->toArray(),
361
            'thread' => $this->fractal->createData($thread)->toArray(),
362
        ];
363
    }
364
}
365