Issues (563)

Security Analysis    not enabled

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.

app/Models/GroupModel.php (3 issues)

1
<?php
2
3
namespace App\Models;
4
5
use App\Models\Rating\GroupRatingCalculator;
6
use Illuminate\Database\Eloquent\Model;
7
use Illuminate\Support\Facades\DB;
8
use Cache;
9
use Auth;
10
use App\Models\ContestModel;
11
12
class GroupModel extends Model
13
{
14
    protected $tableName='group';
15
    protected $table='group';
16
    protected $primaryKey='gid';
17
    const DELETED_AT=null;
18
    const UPDATED_AT=null;
19
    const CREATED_AT=null;
20
21
    /*
22
        join_policy:
23
            0:a user can join this group by both invitation and application // old version default value
24
            1:a user can join this group only by invitation
25
            2:a user can join this group only by application
26
            3:a user can join this group by both invitation and application
27
    */
28
    public $role=[
29
        "-3"=>"None",
30
        "-1"=>"Invited",
31
        "0"=>"Pending",
32
        "1"=>"Member",
33
        "2"=>"Manager",
34
        "3"=>"Leader"
35
    ];
36
    public $role_color=[
37
        "-3"=>"wemd-black",
38
        "-1"=>"wemd-deep-purple",
39
        "0"=>"wemd-red",
40
        "1"=>"wemd-grey",
41
        "2"=>"wemd-light-blue",
42
        "3"=>"wemd-amber"
43
    ];
44
45
    public function trendingGroups()
46
    {
47
        return Cache::tags(['group'])->get('trending');
48
    }
49
50
    public function gid($gcode)
51
    {
52
        return DB::table($this->tableName)->where(["gcode"=>$gcode])->first()["gid"];
53
    }
54
55
    public function cacheTrendingGroups()
56
    {
57
        $trending_groups=DB::table($this->tableName)->where(["public"=>1])->orderBy('created_at', 'desc')->select("gid", "gcode", "img", "name", "verified")->get()->all();
58
        foreach ($trending_groups as &$t) {
59
            $t["members"]=$this->countGroupMembers($t["gid"]);
60
        }
61
        usort($trending_groups, function($a, $b) {
62
            return $b["members"]<=>$a["members"];
63
        });
64
        Cache::tags(['group'])->put('trending', array_slice($trending_groups, 0, 12), 3600 * 24);
65
    }
66
67
    public function userGroups($uid)
68
    {
69
        $user_groups=DB::table("group_member")->join("group", "group_member.gid", "=", "group.gid")->where(["uid"=>$uid])->select("group.gid as gid", "gcode", "img", "name", "verified")->get()->all();
70
        foreach ($user_groups as &$m) {
71
            $m["members"]=$this->countGroupMembers($m["gid"]);
72
        }
73
        return $user_groups;
74
    }
75
76
    public function countGroupMembers($gid)
77
    {
78
        return DB::table("group_member")->where(["gid"=>$gid])->count();
79
    }
80
81
    public function getGroupTags($gid)
82
    {
83
        return DB::table("group_tag")->where(["gid"=>$gid])->select("tag")->get()->all();
84
    }
85
86
    public function countGroupContest($gid)
87
    {
88
        return [
89
            "contest_ahead" => DB::table("contest")->where(["gid"=>$gid])->where("begin_time", ">", DB::raw("now()"))->count(),
90
            "contest_going" => DB::table("contest")->where(["gid"=>$gid])->where("begin_time", "<=", DB::raw("now()"))->where("end_time", ">=", DB::raw("now()"))->count(),
91
            "contest_end" => DB::table("contest")->where(["gid"=>$gid])->where("end_time", "<", DB::raw("now()"))->count()
92
        ];
93
    }
94
95
    public function changeNickName($gid, $uid, $nickName)
96
    {
97
        return DB::table("group_member")->where(["gid"=>$gid, "uid"=>$uid])->update([
98
            "nick_name"=>$nickName
99
        ]);
100
    }
101
102
    public function changeGroupName($gid, $GroupName)
103
    {
104
        return DB::table("group")->where('gid', $gid)->update([
105
            "name"=>$GroupName
106
        ]);
107
    }
108
109
    public function changeJoinPolicy($gid, $JoinPolicy) {
110
        return DB::table("group")->where('gid', $gid)->update([
111
            "join_policy"=>$JoinPolicy
112
        ]);
113
    }
114
115
    public function basic($gid)
116
    {
117
        $basic_info=DB::table($this->tableName)->where(["gid"=>$gid])->first();
118
        return $basic_info;
119
    }
120
121
    public function details($gcode)
122
    {
123
        $basic_info=DB::table($this->tableName)->where(["gcode"=>$gcode])->first();
124
        if (empty($basic_info)) {
125
            return [];
126
        }
127
        $basic_info["members"]=$this->countGroupMembers($basic_info["gid"]);
128
        $basic_info["tags"]=$this->getGroupTags($basic_info["gid"]);
129
        $basic_info["create_time_foramt"]=date_format(date_create($basic_info["created_at"]), 'M jS, Y');
130
        $basic_info["contest_stat"]=$this->countGroupContest($basic_info["gid"]);
131
        return $basic_info;
132
    }
133
134
    public function joinPolicy($gid)
135
    {
136
        $ret=DB::table($this->tableName)->where(["gid"=>$gid])->first();
137
        return empty($ret) ? null : $ret["join_policy"];
138
    }
139
140
    public function userProfile($uid, $gid)
141
    {
142
        $info=DB::table("group_member")
143
        ->join('users', 'users.id', '=', 'group_member.uid')
144
        ->where(["gid"=>$gid, "uid"=>$uid])
145
        ->where("role", ">", 0)
146
        ->select('avatar', 'describes', 'email', 'gid', 'uid', 'name', 'nick_name', 'professional_rate', 'role', 'sub_group')
147
        ->first();
148
        if (!empty($info)) {
149
            $info["role_parsed"]=$this->role[$info["role"]];
150
            $info["role_color"]=$this->role_color[$info["role"]];
151
        }
152
        return $info;
153
    }
154
155
    public function userList($gid)
156
    {
157
        $user_list=DB::table("group_member")->join(
158
            "users",
159
            "users.id",
160
            "=",
161
            "group_member.uid"
162
        )->where(["gid"=>$gid])->orderBy('role', 'desc')->select(
163
            "role",
164
            "uid",
165
            "name",
166
            "nick_name",
167
            "avatar",
168
            "sub_group",
169
            "ranking"
170
        )->get()->all();
171
        foreach ($user_list as &$u) {
172
            $u["role_parsed"]=$this->role[$u["role"]];
173
            $u["role_color"]=$this->role_color[$u["role"]];
174
            if (is_null($u["sub_group"])) {
175
                $u["sub_group"]="None";
176
            }
177
        }
178
        return $user_list;
179
    }
180
181
    public function groupNotice($gid)
182
    {
183
        $notice_item=DB::table("group_notice")->where(["gid"=>$gid])->first();
184
        if (empty($notice_item)) {
185
            return [];
186
        }
187
        $notice_author=DB::table("users")->where(["id"=>$notice_item["uid"]])->first();
188
        $notice_item["name"]=$notice_author["name"];
189
        $notice_item["avatar"]=$notice_author["avatar"];
190
        $notice_item["post_date_parsed"]=formatHumanReadableTime($notice_item["created_at"]);
191
        $notice_item["content_parsed"]=clean(convertMarkdownToHtml($notice_item["content"]));
192
        return $notice_item;
193
    }
194
195
    public function judgeClearance($gid, $uid)
196
    {
197
        $ret=DB::table("group_member")->where(["gid"=>$gid, "uid"=>$uid])->first();
198
        return empty($ret) ? -3 : $ret["role"];
199
    }
200
201
    public function changeClearance($uid, $gid, $clearance)
202
    {
203
        return DB::table("group_member")->where([
204
            "uid"=>$uid,
205
            "gid"=>$gid
206
        ])->update([
207
            "role"=>$clearance
208
        ]);
209
    }
210
211
    public function removeClearance($uid, $gid)
212
    {
213
        return DB::table("group_member")->where([
214
            "uid"=>$uid,
215
            "gid"=>$gid
216
        ])->delete();
217
    }
218
219
    public function addClearance($uid, $gid, $clearance)
220
    {
221
        return DB::table("group_member")->insert([
222
            "uid"=>$uid,
223
            "gid"=>$gid,
224
            "role"=>$clearance,
225
            "created_at"=>date("Y-m-d H:i:s")
226
        ]);
227
    }
228
229
    public function isMember($gid, $uid)
230
    {
231
        return DB::table("group_member")->where([
232
            "gid"=> $gid,
233
            "uid"=> $uid
234
        ])->where("role", ">", 0)->count();
235
    }
236
237
    public function problemTags($gid, $pid=-1)
238
    {
239
        if ($pid==-1) {
240
            $tags=DB::table('group_problem_tag')
241
            ->select('tag')
242
            ->where('gid', $gid)
243
            ->distinct()
244
            ->get()->all();
245
        } else {
246
            $tags=DB::table('group_problem_tag')
247
            ->select('tag')
248
            ->where('gid', $gid)
249
            ->where('pid', $pid)
250
            ->distinct()
251
            ->get()->all();
252
        }
253
254
        $tags_arr=[];
255
        if (!empty($tags)) {
256
            foreach ($tags as $value) {
257
                array_push($tags_arr, $value['tag']);
258
            }
259
        }
260
        return $tags_arr;
261
    }
262
263
    public function problems($gid)
264
    {
265
        $contestModel=new ContestModel();
266
        $problems=DB::table('contest_problem')
267
        ->join('contest', 'contest_problem.cid', '=', 'contest.cid')
268
        ->join('problem', 'contest_problem.pid', '=', 'problem.pid')
269
        ->select('contest_problem.cid as cid', 'problem.pid as pid', 'pcode', 'title')
270
        ->where('contest.gid', $gid)
271
        ->where('contest.practice', 1)
272
        ->orderBy('contest.created_at', 'desc')
273
        ->distinct()
274
        ->get()->all();
275
        $user_id=Auth::user()->id;
0 ignored issues
show
Accessing id on the interface Illuminate\Contracts\Auth\Authenticatable suggest that you code against a concrete implementation. How about adding an instanceof check?
Loading history...
276
        foreach ($problems as $key => $value) {
277
            if ($contestModel->judgeClearance($value['cid'], $user_id)!=3) {
278
                unset($problems[$key]);
279
            } else {
280
                $problems[$key]['tags']=$this->problemTags($gid, $value['pid']);
281
            }
282
        }
283
        return $problems;
284
    }
285
286
    public function problemAddTag($gid, $pid, $tag)
287
    {
288
        return DB::table("group_problem_tag")->insert([
289
            "gid"=>$gid,
290
            "pid"=>$pid,
291
            "tag"=>$tag,
292
        ]);
293
    }
294
295
    public function problemRemoveTag($gid, $pid, $tag)
296
    {
297
        return DB::table("group_problem_tag")->where([
298
            "gid"=>$gid,
299
            "pid"=>$pid,
300
            "tag"=>$tag
301
        ])->delete();
302
    }
303
304
    public function judgeEmailClearance($gid, $email)
305
    {
306
        $user=DB::table("users")->where(["email"=>$email])->first();
307
        if (empty($user)) {
308
            return -4;
309
        }
310
        $ret=DB::table("group_member")->where([
311
            "gid"=>$gid,
312
            "uid"=>$user["id"],
313
        ])->first();
314
        return empty($ret) ? -3 : $ret["role"];
315
    }
316
317
    public function inviteMember($gid, $email)
318
    {
319
        $uid=DB::table("users")->where(["email"=>$email])->first();
320
        return DB::table("group_member")->insert([
321
            "uid"=>$uid["id"],
322
            "gid"=>$gid,
323
            "role"=>-1,
324
            "created_at"=>date("Y-m-d H:i:s")
325
        ]);
326
    }
327
328
    public function changeGroup($uid, $gid, $sub)
329
    {
330
        return DB::table("group_member")->where([
331
            "uid"=>$uid,
332
            "gid"=>$gid
333
        ])->update([
334
            "sub_group"=>$sub
335
        ]);
336
    }
337
338
    public function isUser($email)
339
    {
340
        return DB::table("users")->where([
341
            "email"=>$email
342
        ])->count();
343
    }
344
345
    public function isGroup($gcode)
346
    {
347
        return DB::table("group")->where([
348
            "gcode"=>$gcode,
349
        ])->count();
350
    }
351
352
    public function createGroup($uid, $gcode, $img, $name, $public, $description, $join_policy)
353
    {
354
        $gid=DB::table("group")->insertGetId([
355
            "gcode"=>$gcode,
356
            "img"=>$img,
357
            "name"=>$name,
358
            "public"=>$public,
359
            "verified"=>0,
360
            "description"=>$description,
361
            "join_policy"=>$join_policy,
362
            "custom_icon"=>null,
363
            "custom_title"=>null,
364
            "created_at"=>date("Y-m-d H:i:s")
365
        ]);
366
        return DB::table("group_member")->insert([
367
            "uid"=>$uid,
368
            "gid"=>$gid,
369
            "role"=>3,
370
            "created_at"=>date("Y-m-d H:i:s")
371
        ]);
372
    }
373
374
    public function detailNotice($gcode)
375
    {
376
        $group=DB::table("group")->where([
377
            "gcode"=>$gcode,
378
        ])->first();
379
        return $group_notice=DB::table("group_notice")->where([
0 ignored issues
show
The assignment to $group_notice is dead and can be removed.
Loading history...
380
            "gid"=>$group["gid"],
381
        ])->first();
382
    }
383
384
    public function createNotice($gid, $uid, $title, $content)
385
    {
386
        return DB::table("group_notice")->updateOrInsert(
387
            [
388
                "gid"=>$gid
389
            ],
390
            [
391
                "uid"=>$uid,
392
                "title"=>$title,
393
                "content"=>$content,
394
                "created_at"=>date("Y-m-d H:i:s"),
395
            ]);
396
    }
397
398
    public function groupMemberPracticeContestStat($gid)
399
    {
400
        $contestModel=new ContestModel();
401
402
        $allPracticeContest=DB::table('contest')
403
            ->where([
404
                'gid' => $gid,
405
                'practice' => 1,
406
            ])
407
            ->select('cid', 'name')
408
            ->get()->all();
409
        $user_list=$this->userList($gid);
410
411
        $memberData=[];
412
        foreach ($user_list as $u) {
413
            $memberData[$u['uid']]=[
414
                'name' => $u['name'],
415
                'nick_name' => $u['nick_name'],
416
                'elo' => $u['ranking'],
417
                'solved_all' => 0,
418
                'problem_all' => 0,
419
                'penalty' => 0,
420
                'contest_detial' => []
421
            ];
422
        }
423
        foreach ($allPracticeContest as $c) {
424
            $contestRankRaw=$contestModel->contestRank($c['cid']);
425
            foreach ($contestRankRaw as $key => $contestRank) {
426
                if (isset($contestRank['remote']) && $contestRank['remote']) {
427
                    unset($contestRankRaw[$key]);
428
                }
429
            }
430
            $contestRank=array_values($contestRankRaw);
431
            $problemsCount=DB::table('contest_problem')
432
                ->where('cid', $c['cid'])
433
                ->count();
434
            $index=1;
435
            $rank=1;
436
            $last_cr=[];
437
            $last_rank=1;
438
            foreach ($contestRank as $cr) {
439
                $last_rank=$index;
440
                if (!empty($last_cr)) {
441
                    if ($cr['solved']==$last_cr['solved'] && $cr['penalty']==$last_cr['penalty']) {
442
                        $rank=$last_rank;
443
                    } else {
444
                        $rank=$index;
445
                        $last_rank=$rank;
0 ignored issues
show
The assignment to $last_rank is dead and can be removed.
Loading history...
446
                    }
447
                }
448
                if (in_array($cr['uid'], array_keys($memberData))) {
449
                    $memberData[$cr['uid']]['solved_all']+=$cr['solved'];
450
                    $memberData[$cr['uid']]['problem_all']+=$problemsCount;
451
                    $memberData[$cr['uid']]['penalty']+=$cr['penalty'];
452
                    $memberData[$cr['uid']]['contest_detial'][$c['cid']]=[
453
                        'rank' => $rank,
454
                        'solved' => $cr['solved'],
455
                        'problems' => $problemsCount,
456
                        'penalty' => $cr['penalty']
457
                    ];
458
                }
459
                $last_cr=$cr;
460
                $index++;
461
            }
462
        }
463
        $new_memberData=[];
464
        foreach ($memberData as $uid => $data) {
465
            $contest_count=0;
466
            $rank_sum=0;
467
            foreach ($data['contest_detial'] as $cid => $c) {
468
                $rank_sum+=$c['rank'];
469
                $contest_count+=1;
470
            }
471
            $temp=$data;
472
            $temp['uid']=$uid;
473
            if ($contest_count!=0) {
474
                $temp['rank_ave']=$rank_sum / $contest_count;
475
            }
476
            array_push($new_memberData, $temp);
477
        }
478
        $ret=[
479
            'contest_list' => $allPracticeContest,
480
            'member_data' => $new_memberData
481
        ];
482
        return $ret;
483
    }
484
485
    public function groupMemberPracticeTagStat($gid)
486
    {
487
        $tags=$this->problemTags($gid);
488
        $tag_problems=[];
489
490
        $user_list=$this->userList($gid);
491
        foreach ($tags as $tag) {
492
            $tag_problems[$tag]=DB::table('problem')
493
                ->join('group_problem_tag', 'problem.pid', '=', 'group_problem_tag.pid')
494
                ->where([
495
                    'group_problem_tag.gid' => $gid,
496
                    'tag' => $tag
497
                ])
498
                ->select('group_problem_tag.pid as pid', 'pcode', 'title')
499
                ->get()->all();
500
        }
501
        $all_problems=[];
502
        foreach ($tag_problems as &$tag_problem_set) {
503
            foreach ($tag_problem_set as $problem) {
504
                $all_problems[$problem['pid']]=$problem;
505
            }
506
            $tag_problem_set=array_column($tag_problem_set, 'pid');
507
        }
508
        $submission_data=DB::table('submission')
509
            ->whereIn('pid', array_keys($all_problems))
510
            ->whereIn('uid', array_column($user_list, 'uid'))
511
            ->where('verdict', 'Accepted')
512
            ->select('pid', 'uid')
513
            ->get()->all();
514
515
        $memberData=[];
516
        foreach ($user_list as $member) {
517
            $completion=[];
518
            foreach ($tag_problems as $tag => $problems) {
519
                $completion[$tag]=[];
520
                foreach ($problems as $problem) {
521
                    $is_accepted=0;
522
                    foreach ($submission_data as $sd) {
523
                        if ($sd['pid']==$problem && $sd['uid']==$member['uid']) {
524
                            $is_accepted=1;
525
                            break;
526
                        }
527
                    }
528
                    $completion[$tag][$problem]=$is_accepted;
529
                }
530
            }
531
            array_push($memberData, [
532
                'uid' => $member['uid'],
533
                'name' => $member['name'],
534
                'nick_name' => $member['nick_name'],
535
                'completion' => $completion,
536
            ]);
537
        }
538
        $ret=[
539
            'all_problems' => $all_problems,
540
            'tag_problems' => $tag_problems,
541
            'member_data' => $memberData
542
        ];
543
        return $ret;
544
    }
545
546
    public function refreshAllElo()
547
    {
548
        $result=[];
549
        $gids=DB::table('group')->select('gid', 'name')->get()->all();
550
        foreach ($gids as $gid) {
551
            $result[$gid['gid']]=[
552
                'name' => $gid['name'],
553
                'result' => $this->refreshElo($gid['gid']),
554
            ];
555
        }
556
        return $result;
557
    }
558
559
    public function refreshElo($gid)
560
    {
561
        DB::table('group_rated_change_log')
562
            ->where('gid', $gid)
563
            ->delete();
564
        DB::table('group_member')
565
            ->where('gid', $gid)
566
            ->update([
567
                'ranking' => 1500
568
            ]);
569
        $contests=DB::table('contest')
570
            ->where([
571
                'gid' => $gid,
572
                'practice' => 1
573
            ])
574
            ->where('end_time', '<', date("Y-m-d H:i:s"))
575
            ->select('cid', 'name')
576
            ->orderBy('end_time')
577
            ->get()->all();
578
579
        if (empty($contests)) {
580
            return [];
581
        }
582
        $result=[];
583
        $contestModel=new ContestModel();
584
        foreach ($contests as $contest) {
585
            $judge_status=$contestModel->judgeOver($contest['cid']);
586
            if ($judge_status['result']==true) {
587
                $calc=new GroupRatingCalculator($contest['cid']);
588
                $calc->calculate();
589
                $calc->storage();
590
                $result[]=[
591
                    'ret' => 'success',
592
                    'cid' => $contest['cid'],
593
                    'name' => $contest['name']
594
                ];
595
            } else {
596
                $result[]=[
597
                    'ret' => 'judging',
598
                    'cid' => $contest['cid'],
599
                    'name' => $contest['name'],
600
                    'submissions' => $judge_status['sid']
601
                ];
602
            }
603
        }
604
605
        return $result;
606
    }
607
608
    public function getEloChangeLog($gid, $uid)
609
    {
610
        $ret=DB::table('group_rated_change_log')
611
            ->join('contest', 'group_rated_change_log.cid', '=', 'contest.cid')
612
            ->where([
613
                'group_rated_change_log.gid' => $gid,
614
                'group_rated_change_log.uid' => $uid
615
            ])->select('group_rated_change_log.cid as cid', 'contest.name as name', 'ranking', 'end_time')
616
            ->orderBy('contest.end_time')
617
            ->get()->all();
618
        $begin=[
619
            'cid' => -1,
620
            'name' => '',
621
            'ranking' => '1500',
622
            'end_time' => date("Y-m-d H:i:s", (strtotime($ret[0]['end_time'] ?? time())-3600 * 24)),
623
        ];
624
        array_unshift($ret, $begin);
625
        return $ret;
626
    }
627
}
628