• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

visavi / rotor / 26723576697

31 May 2026 08:27PM UTC coverage: 14.172% (-0.4%) from 14.618%
26723576697

push

github

visavi
Перенес файлы обновлений бд в отдельную папку

785 of 5539 relevant lines covered (14.17%)

1.26 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/app/Http/Controllers/User/UserController.php
1
<?php
2

3
declare(strict_types=1);
4

5
namespace App\Http\Controllers\User;
6

7
use App\Classes\Validator;
8
use App\Http\Controllers\Controller;
9
use App\Models\BlackList;
10
use App\Models\Flood;
11
use App\Models\User;
12
use App\Models\UserField;
13
use Illuminate\Database\Query\JoinClause;
14
use Illuminate\Http\JsonResponse;
15
use Illuminate\Http\RedirectResponse;
16
use Illuminate\Http\Request;
17
use Illuminate\Support\Facades\Auth;
18
use Illuminate\Support\Facades\Hash;
19
use Illuminate\Support\Str;
20
use Illuminate\View\View;
21

22
class UserController extends Controller
23
{
24
    /**
25
     * User profile
26
     */
27
    public function index(string $login): View
×
28
    {
29
        if (! $user = getUserByLogin($login)) {
×
30
            abort(404, __('validator.user'));
×
31
        }
32

33
        $user->load('lastBan');
×
34
        $adminGroups = User::ADMIN_GROUPS;
×
35

36
        $fields = UserField::query()->withUserData($user->id)->whereNotNull('user_data.value')->get();
×
37

38
        return view('users/user', compact('user', 'adminGroups', 'fields'));
×
39
    }
40

41
    /**
42
     * Registration
43
     */
44
    public function register(Request $request, Validator $validator): View|RedirectResponse
×
45
    {
46
        if (getUser()) {
×
47
            abort(403, __('users.already_registered'));
×
48
        }
49

50
        if (! setting('openreg')) {
×
51
            abort(200, __('users.registration_suspended'));
×
52
        }
53

54
        if ($request->isMethod('post')) {
×
55
            if ($request->has(['login', 'password'])) {
×
56
                $login = (string) $request->input('login');
×
57
                $password = $request->input('password');
×
58
                $password2 = $request->input('password2');
×
59
                $email = strtolower((string) $request->input('email'));
×
60
                $domain = Str::substr(strrchr($email, '@'), 1);
×
61
                $gender = $request->input('gender') === User::MALE ? User::MALE : User::FEMALE;
×
62

63
                $validator->true(captchaVerify(), ['protect' => __('validator.captcha')])
×
64
                    ->regex($login, '|^[a-z0-9\-]+$|i', ['login' => __('validator.login')])
×
65
                    ->regex(Str::substr($login, 0, 1), '|^[a-z0-9]+$|i', ['login' => __('users.login_begin_requirements')])
×
66
                    ->email($email, ['email' => __('validator.email')])
×
67
                    ->length($login, 3, 20, ['login' => __('users.login_length_requirements')])
×
68
                    ->length($password, 6, 20, ['password' => __('users.password_length_requirements')])
×
69
                    ->equal($password, $password2, ['password2' => __('users.passwords_different')])
×
70
                    ->false(ctype_digit($login), ['login' => __('users.field_characters_requirements')])
×
71
                    ->false(ctype_digit($password), ['password' => __('users.field_characters_requirements')])
×
72
                    ->false(substr_count($login, '-') > 2, ['login' => __('users.login_hyphens_requirements')]);
×
73

74
                if (! empty($login)) {
×
75
                    // Проверка логина на существование
76
                    $checkLogin = User::query()->where('login', $login)->exists();
×
77
                    $validator->false($checkLogin, ['login' => __('users.login_already_exists')]);
×
78

79
                    // Проверка логина в черном списке
80
                    $validator->false(BlackList::isBlacklisted('login', strtolower($login)), ['login' => __('users.login_is_blacklisted')]);
×
81
                }
82

83
                // Проверка email на существование
84
                $checkMail = User::query()->where('email', $email)->exists();
×
85
                $validator->false($checkMail, ['email' => __('users.email_already_exists')]);
×
86

87
                // Проверка домена от email и email в черном списке
88
                $validator
×
89
                    ->false(BlackList::isBlacklisted('domain', $domain), ['email' => __('users.domain_is_blacklisted')])
×
90
                    ->false(BlackList::isBlacklisted('email', $email), ['email' => __('users.email_is_blacklisted')]);
×
91

92
                // Подтверждение регистрации
93
                $confirmToken = null;
×
94
                $confirmUrl = null;
×
95
                if (setting('regkeys')) {
×
96
                    $confirmToken = Str::random(32);
×
97
                    $confirmUrl = route('confirm', ['token' => $confirmToken]);
×
98
                }
99

100
                // Регистрация аккаунта
101
                if ($validator->isValid()) {
×
102
                    $user = User::query()->create([
×
103
                        'login'         => $login,
×
104
                        'password'      => Hash::make($password),
×
105
                        'email'         => $email,
×
106
                        'level'         => setting('regkeys') ? User::PENDED : User::USER,
×
107
                        'gender'        => $gender,
×
108
                        'themes'        => setting('themes'),
×
109
                        'point'         => 0,
×
110
                        'language'      => setting('language'),
×
111
                        'money'         => setting('registermoney'),
×
112
                        'subscribe'     => Str::random(32),
×
113
                        'confirm_token' => $confirmToken,
×
114
                        'updated_at'    => SITETIME,
×
115
                        'created_at'    => SITETIME,
×
116
                    ]);
×
117

118
                    // ----- Уведомление в приват ----//
119
                    $textNotice = textNotice('register', ['username' => $login]);
×
120
                    $user->sendMessage(null, $textNotice);
×
121

122
                    // --- Уведомление о регистрации на email ---//
123
                    $subject = 'Регистрация на ' . setting('title');
×
124
                    $data = [
×
125
                        'to'         => $email,
×
126
                        'subject'    => $subject,
×
127
                        'login'      => $login,
×
128
                        'password'   => $password,
×
129
                        'confirmUrl' => $confirmUrl,
×
130
                    ];
×
131

132
                    sendMail('mailer.register', $data);
×
133

134
                    Auth::login($user, true);
×
135

136
                    setFlash('success', __('users.welcome', ['login' => $login]));
×
137

138
                    return redirect('/');
×
139
                }
140

141
                setInput($request->all());
×
142
                setFlash('danger', $validator->getErrors());
×
143
            }
144
        }
145

146
        return view('users/register');
×
147
    }
148

149
    /**
150
     * Login
151
     */
152
    public function login(Request $request, Validator $validator, Flood $flood): View|RedirectResponse
×
153
    {
154
        if (Auth::check()) {
×
155
            return redirect('/')->with('danger', __('main.already_authorized'));
×
156
        }
157

158
        $isFlood = $flood->isFlood();
×
159

160
        if ($request->isMethod('post')) {
×
161
            if ($request->has(['login', 'password'])) {
×
162
                if ($isFlood) {
×
163
                    $validator->true(captchaVerify(), ['protect' => __('validator.captcha')]);
×
164
                }
165

166
                if ($validator->isValid()) {
×
167
                    $login = Str::lower((string) $request->input('login'));
×
168
                    $password = $request->input('password');
×
169
                    $remember = $request->boolean('remember');
×
170

171
                    $field = strpos($request->input('login'), '@') ? 'email' : 'login';
×
172

173
                    $credentials = [
×
174
                        $field     => $login,
×
175
                        'password' => $password,
×
176
                    ];
×
177

178
                    try {
179
                        $authorized = Auth::attempt($credentials, $remember);
×
180
                    } catch (\RuntimeException) {
×
181
                        setInput($request->all());
×
182
                        setFlash('danger', __('users.password_reset_required'));
×
183

184
                        return redirect('recovery');
×
185
                    }
186

187
                    if ($authorized) {
×
188
                        $request->session()->regenerate();
×
189
                        $user = Auth::user();
×
190

191
                        return redirect($request->input('return', '/'))
×
192
                            ->with('success', __('users.welcome', ['login' => $user->getName()], $user->language));
×
193
                    }
194

195
                    $flood->saveState(300);
×
196
                    setInput($request->all());
×
197
                    setFlash('danger', __('users.incorrect_login_or_password'));
×
198
                } else {
199
                    setInput($request->all());
×
200
                    setFlash('danger', $validator->getErrors());
×
201
                }
202

203
                return redirect('login');
×
204
            }
205
        }
206

207
        return view('users/login', compact('isFlood'));
×
208
    }
209

210
    /**
211
     * Exit
212
     */
213
    public function logout(Request $request): RedirectResponse
×
214
    {
215
        Auth::logout();
×
216

217
        $request->session()->invalidate();
×
218
        $request->session()->regenerateToken();
×
219

220
        return redirect('/');
×
221
    }
222

223
    /**
224
     * Profile editing
225
     */
226
    public function profile(Request $request, Validator $validator): View|RedirectResponse
×
227
    {
228
        if (! $user = getUser()) {
×
229
            abort(403, __('main.not_authorized'));
×
230
        }
231

232
        $fields = UserField::query()
×
233
            ->select('uf.*', 'ud.value')
×
234
            ->from('user_fields as uf')
×
235
            ->leftJoin('user_data as ud', static function (JoinClause $join) use ($user) {
×
236
                $join->on('uf.id', 'ud.field_id')
×
237
                    ->where('ud.user_id', $user->id);
×
238
            })
×
239
            ->orderBy('uf.sort')
×
240
            ->get();
×
241

242
        if ($request->isMethod('post')) {
×
243
            $info = $request->input('info');
×
244
            $name = $request->input('name');
×
245
            $country = $request->input('country');
×
246
            $city = $request->input('city');
×
247
            $phone = preg_replace('/[^\d+]/', '', $request->input('phone') ?? '');
×
248
            $site = $request->input('site');
×
249
            $birthday = $request->input('birthday');
×
250
            $gender = $request->input('gender') === User::MALE ? User::MALE : User::FEMALE;
×
251

252
            $validator
×
253
                ->url($site, ['site' => __('validator.site')], false)
×
254
                ->regex($birthday, '#^[0-9]{2}+\.[0-9]{2}+\.[0-9]{4}$#', ['birthday' => __('validator.date')], false)
×
255
                ->phone($phone, ['phone' => __('validator.phone')], false)
×
256
                ->length($info, 0, 1000, ['info' => __('users.info_yourself_long')])
×
257
                ->length($name, 3, 20, ['name' => __('users.name_short_or_long')], false);
×
258

259
            foreach ($fields as $field) {
×
260
                $validator->length(
×
261
                    $request->input('field' . $field->id),
×
262
                    $field->min,
×
263
                    $field->max,
×
264
                    ['field' . $field->id => __('validator.text')],
×
265
                    $field->required
×
266
                );
×
267
            }
268

269
            if ($validator->isValid()) {
×
270
                $country = Str::substr($country, 0, 30);
×
271
                $city = Str::substr($city, 0, 50);
×
272

273
                $user->update([
×
274
                    'name'     => $name,
×
275
                    'gender'   => $gender,
×
276
                    'country'  => $country,
×
277
                    'city'     => $city,
×
278
                    'phone'    => $phone,
×
279
                    'site'     => $site,
×
280
                    'birthday' => $birthday,
×
281
                    'info'     => $info,
×
282
                ]);
×
283

284
                foreach ($fields as $field) {
×
285
                    $user->data()
×
286
                        ->updateOrCreate([
×
287
                            'field_id' => $field->id,
×
288
                        ], [
×
289
                            'value' => $field->sanitizeValue($request->input('field' . $field->id)),
×
290
                        ]);
×
291
                }
292

293
                setFlash('success', __('users.profile_success_changed'));
×
294

295
                return redirect('profile');
×
296
            }
297

298
            setInput($request->all());
×
299
            setFlash('danger', $validator->getErrors());
×
300
        }
301

302
        return view('users/profile', compact('user', 'fields'));
×
303
    }
304

305
    /**
306
     * Verify registration
307
     */
308
    public function verify(Request $request, Validator $validator): View|RedirectResponse
×
309
    {
310
        if (! $user = $request->user()) {
×
311
            abort(403, __('main.not_authorized'));
×
312
        }
313

314
        if (! setting('regkeys')) {
×
315
            abort(200, __('users.confirm_registration_disabled'));
×
316
        }
317

318
        if ($user->level !== User::PENDED) {
×
319
            abort(403, __('users.profile_not_confirmation'));
×
320
        }
321

322
        /* Повторная отправка */
323
        if ($request->has('email') && $request->isMethod('post')) {
×
324
            $email = strtolower((string) $request->input('email'));
×
325
            $domain = Str::substr(strrchr($email, '@'), 1);
×
326

327
            $validator
×
328
                ->true(captchaVerify(), ['protect' => __('validator.captcha')])
×
329
                ->email($email, ['email' => __('validator.email')]);
×
330

331
            $validator
×
332
                ->false(User::query()->where('login', '<>', $user->login)->where('email', $email)->exists(), ['email' => __('users.email_already_exists')])
×
333
                ->false(BlackList::isBlacklisted('email', $email), ['email' => __('users.email_is_blacklisted')])
×
334
                ->false(BlackList::isBlacklisted('domain', $domain), ['email' => __('users.domain_is_blacklisted')]);
×
335

336
            if ($validator->isValid()) {
×
337
                $token = Str::random(32);
×
338
                $confirmUrl = route('confirm', ['token' => $token]);
×
339

340
                $user->update([
×
341
                    'email'         => $email,
×
342
                    'confirm_token' => $token,
×
343
                ]);
×
344

345
                /* Уведомление о регистрации на email */
346
                $subject = 'Регистрация на ' . setting('title');
×
347
                $data = [
×
348
                    'to'         => $email,
×
349
                    'subject'    => $subject,
×
350
                    'login'      => $user->login,
×
351
                    'password'   => '*****',
×
352
                    'confirmUrl' => $confirmUrl,
×
353
                ];
×
354

355
                sendMail('mailer.register', $data);
×
356
                setFlash('success', __('users.confirm_code_success_sent'));
×
357

358
                return redirect()->route('verify');
×
359
            }
360

361
            setInput($request->all());
×
362
            setFlash('danger', $validator->getErrors());
×
363
        }
364

365
        return view('users/verify', compact('user'));
×
366
    }
367

368
    /**
369
     * Confirm registration
370
     */
371
    public function confirm(string $token): RedirectResponse
×
372
    {
373
        $user = User::query()->where('confirm_token', $token)->first();
×
374
        if (! $user) {
×
375
            abort(200, __('users.confirm_code_invalid'));
×
376
        }
377

378
        $user->update([
×
379
            'level'         => User::USER,
×
380
            'confirm_token' => null,
×
381
        ]);
×
382

383
        return redirect('/')->with('success', __('users.account_success_activated'));
×
384
    }
385

386
    /**
387
     * Settings
388
     */
389
    public function setting(Request $request, Validator $validator): View|RedirectResponse
×
390
    {
391
        if (! $user = getUser()) {
×
392
            abort(403, __('main.not_authorized'));
×
393
        }
394

395
        $setting['themes'] = getAvailableThemes();
×
396
        $setting['languages'] = getAvailableLanguages();
×
397
        $setting['timezones'] = range(-12, 12);
×
398

399
        if ($request->isMethod('post')) {
×
400
            $themes = $request->input('themes');
×
401
            $timezone = $request->input('timezone', 0);
×
402
            $language = $request->input('language');
×
403
            $notifyMention = $request->input('notify_mention') ? 1 : 0;
×
404
            $notifyReply = $request->input('notify_reply') ? 1 : 0;
×
405
            $notifyComment = $request->input('notify_comment') ? 1 : 0;
×
406
            $subscribe = $request->input('subscribe') ? Str::random(32) : null;
×
407

408
            $validator
×
409
                ->regex($themes, '|^[a-z0-9_\-]+$|i', ['themes' => __('users.theme_invalid')])
×
410
                ->true(in_array($themes, $setting['themes'], true) || empty($themes), ['themes' => __('users.theme_not_installed')])
×
411
                ->regex($language, '|^[a-z]+$|', ['language' => __('users.language_invalid')])
×
412
                ->in($language, $setting['languages'], ['language' => __('users.language_not_installed')])
×
413
                ->regex($timezone, '|^[\-\+]{0,1}[0-9]{1,2}$|', ['timezone' => __('users.timezone_invalid')]);
×
414

415
            if ($validator->isValid()) {
×
416
                $user->update([
×
417
                    'themes'         => $themes,
×
418
                    'timezone'       => $timezone,
×
419
                    'notify_mention' => $notifyMention,
×
420
                    'notify_reply'   => $notifyReply,
×
421
                    'notify_comment' => $notifyComment,
×
422
                    'subscribe'      => $subscribe,
×
423
                    'language'       => $language,
×
424
                ]);
×
425

426
                if (now()->month === 4 && now()->day === 1 && ! empty($themes)) {
×
427
                    $request->session()->put('april_fools_theme', $themes);
×
428
                }
429

430
                setFlash('success', __('users.settings_success_changed'));
×
431

432
                return redirect('settings');
×
433
            }
434

435
            setInput($request->all());
×
436
            setFlash('danger', $validator->getErrors());
×
437
        }
438

439
        return view('users/settings', compact('user', 'setting'));
×
440
    }
441

442
    /**
443
     * Проверка доступности логина
444
     */
445
    public function checkLogin(Request $request, Validator $validator): JsonResponse
×
446
    {
447
        $login = (string) $request->input('login');
×
448

449
        $validator
×
450
            ->true($request->ajax(), __('validator.not_ajax'))
×
451
            ->regex($login, '|^[a-z0-9\-]+$|i', __('validator.login'))
×
452
            ->regex(Str::substr($login, 0, 1), '|^[a-z0-9]+$|i', __('users.login_begin_requirements'))
×
453
            ->length($login, 3, 20, __('users.login_length_requirements'))
×
454
            ->false(ctype_digit($login), __('users.field_characters_requirements'))
×
455
            ->false(substr_count($login, '-') > 2, __('users.login_hyphens_requirements'));
×
456

457
        if ($validator->isValid()) {
×
458
            $existLogin = User::query()
×
459
                ->where('login', $login)
×
460
                ->exists();
×
461

462
            $validator
×
463
                ->false($existLogin, __('users.login_already_exists'))
×
464
                ->false(BlackList::isBlacklisted('login', strtolower($login)), __('users.login_is_blacklisted'));
×
465
        }
466

467
        if ($validator->isValid()) {
×
468
            return response()->json(['success' => true]);
×
469
        }
470

471
        return response()->json([
×
472
            'success' => false,
×
473
            'message' => current($validator->getErrors()),
×
474
        ]);
×
475
    }
476

477
    /**
478
     * Поиск пользователей для упоминаний
479
     */
480
    public function searchUsers(Request $request): JsonResponse
×
481
    {
482
        $query = (string) $request->input('query', '');
×
483

484
        if (mb_strlen($query) < 2) {
×
485
            return response()->json();
×
486
        }
487

488
        $users = User::query()
×
489
            ->where(function ($q) use ($query) {
×
490
                $q->where('login', 'like', $query . '%')
×
491
                    ->orWhere('name', 'like', $query . '%');
×
492
            })
×
493
            ->orderByDesc('point')
×
494
            ->limit(10)
×
495
            ->get(['login', 'name']);
×
496

497
        return response()->json($users);
×
498
    }
499
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc