Просмотр файла app/Http/Controllers/User/AccountController.php

Размер файла: 11.1Kb
<?php

declare(strict_types=1);

namespace App\Http\Controllers\User;

use App\Classes\Validator;
use App\Http\Controllers\Controller;
use App\Models\BlackList;
use App\Models\EmailChange;
use App\Models\User;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Str;
use Illuminate\View\View;

class AccountController extends Controller
{
    /**
     * User data
     */
    public function account(): View
    {
        if (! $user = getUser()) {
            abort(403, __('main.not_authorized'));
        }

        return view('users/account', compact('user'));
    }

    /**
     * Initialize email change
     */
    public function changeMail(Request $request, Validator $validator): RedirectResponse
    {
        if (! $user = getUser()) {
            abort(403, __('main.not_authorized'));
        }

        $email = strtolower((string) $request->input('email'));
        $password = $request->input('password');

        $validator->equal($request->input('_token'), csrf_token(), __('validator.token'))
            ->notEqual($email, $user->email, ['email' => __('users.email_different')])
            ->email($email, ['email' => __('validator.email')])
            ->true(Hash::check($password, $user->password), ['password' => __('users.password_not_different')]);

        $isEmailExists = User::query()->where('email', $email)->exists();
        $validator->false($isEmailExists, ['email' => __('users.email_already_exists')]);

        $isEmailBlacklisted = BlackList::query()->where('type', 'email')->where('value', $email)->exists();
        $validator->false($isEmailBlacklisted, ['email' => __('users.email_is_blacklisted')]);

        EmailChange::query()
            ->where('created_at', '<', now()->subHour())
            ->delete();

        $emailChange = EmailChange::query()->where('user_id', $user->id)->first();
        $validator->empty($emailChange, __('users.confirm_already_sent'));

        if ($validator->isValid()) {
            $token = Str::random(32);
            $changeUrl = route('accounts.edit-mail', ['token' => $token]);

            $subject = 'Изменение email на ' . setting('title');
            $data = [
                'to'        => $email,
                'subject'   => $subject,
                'username'  => $user->getName(),
                'changeUrl' => $changeUrl,
            ];

            sendMail('mailer.change_mail', $data);

            EmailChange::query()->create([
                'user_id'    => $user->id,
                'email'      => $email,
                'token'      => $token,
                'created_at' => now(),
            ]);

            setFlash('success', __('users.confirm_success_sent'));
        } else {
            setInput($request->all());
            setFlash('danger', $validator->getErrors());
        }

        return redirect('accounts');
    }

    /**
     * Email change
     */
    public function editMail(string $token, Validator $validator): RedirectResponse
    {
        if (! $user = getUser()) {
            abort(403, __('main.not_authorized'));
        }

        EmailChange::query()
            ->where('created_at', '<', now()->subHour())
            ->delete();

        $emailChange = EmailChange::query()
            ->where('token', $token)
            ->where('user_id', $user->id)
            ->first();

        $validator->notEmpty($emailChange, __('users.changed_code_not_found'));

        if ($emailChange) {
            $isEmailExists = User::query()->where('email', $emailChange->email)->exists();
            $validator->false($isEmailExists, __('users.email_already_exists'));

            $isEmailBlacklisted = BlackList::query()->where('type', 'email')->where('value', $emailChange->email)->exists();
            $validator->false($isEmailBlacklisted, __('users.email_is_blacklisted'));
        }

        if ($validator->isValid()) {
            $user->update([
                'email' => $emailChange->email,
            ]);

            $emailChange->delete();

            $flash = ['success', __('users.email_success_changed')];
        } else {
            $flash = ['danger', $validator->getErrors()];
        }

        return redirect()->route('accounts.account')
            ->with(...$flash);
    }

    /**
     * Status change
     */
    public function editStatus(Request $request, Validator $validator): RedirectResponse
    {
        if (! $user = getUser()) {
            abort(403, __('main.not_authorized'));
        }

        $status = $request->input('status');
        $status = ! empty($status) ? $status : null;
        $cost = $status ? setting('editstatusmoney') : 0;

        $validator->equal($request->input('_token'), csrf_token(), __('validator.token'))
            ->empty($user->ban, ['status' => __('users.status_changed_not_ban')])
            ->notEqual($status, $user->status, ['status' => __('users.status_different')])
            ->gte($user->point, setting('editstatuspoint'), ['status' => __('users.status_points')])
            ->gte($user->money, $cost, ['status' => __('users.status_moneys')])
            ->length($status, 3, 25, ['status' => __('users.status_short_or_long')], false);

        if ($validator->isValid()) {
            $user->update([
                'status' => $status,
                'money'  => DB::raw('money - ' . $cost),
            ]);

            clearCache('status');
            setFlash('success', __('users.status_success_changed'));
        } else {
            setInput($request->all());
            setFlash('danger', $validator->getErrors());
        }

        return redirect('accounts');
    }

    /**
     * Color change
     */
    public function editColor(Request $request, Validator $validator): RedirectResponse
    {
        if (! $user = getUser()) {
            abort(403, __('main.not_authorized'));
        }

        $color = $request->input('color');
        $color = ! empty($color) ? $color : null;
        $cost = $color ? setting('editcolormoney') : 0;

        $validator->equal($request->input('_token'), csrf_token(), __('validator.token'))
            ->notEqual($color, $user->color, ['color' => __('users.color_different')])
            ->gte($user->point, setting('editcolorpoint'), ['color' => __('users.color_points')])
            ->gte($user->money, $cost, ['color' => __('users.color_moneys')])
            ->regex($color, '|^#+[A-f0-9]{6}$|', ['color' => __('validator.color')], false);

        if ($validator->isValid()) {
            $user->update([
                'color' => $color,
                'money' => DB::raw('money - ' . $cost),
            ]);

            setFlash('success', __('users.color_success_changed'));
        } else {
            setInput($request->all());
            setFlash('danger', $validator->getErrors());
        }

        return redirect('accounts');
    }

    /**
     * Password change
     */
    public function editPassword(Request $request, Validator $validator): RedirectResponse
    {
        if (! $user = getUser()) {
            abort(403, __('main.not_authorized'));
        }

        $newPassword = $request->input('new_password');
        $confirmPassword = $request->input('confirm_password');
        $password = $request->input('old_password');

        $validator->equal($request->input('_token'), csrf_token(), __('validator.token'))
            ->true(Hash::check($password, $user->password), ['old_password' => __('users.password_not_different')])
            ->false(Hash::check($newPassword, $user->password), ['old_password' => __('users.password_different')])
            ->length($newPassword, 6, 20, ['new_password' => __('users.password_length_requirements')])
            ->notEqual($user->login, $newPassword, ['new_password' => __('users.login_different')])
            ->equal($newPassword, $confirmPassword, ['confirm_password' => __('users.passwords_different')]);

        if (ctype_digit($newPassword)) {
            $validator->addError(['new_password' => __('users.field_characters_requirements')]);
        }

        if ($validator->isValid()) {
            $user->update([
                'password' => Hash::make($newPassword),
            ]);

            $request->session()->regenerate();

            $subject = 'Изменение пароля на ' . setting('title');
            $data = [
                'to'       => $user->email,
                'subject'  => $subject,
                'username' => $user->getName(),
                'password' => $newPassword,
            ];

            sendMail('mailer.change_password', $data);

            return redirect('/')->with('success', __('users.password_success_changed'));
        }

        return redirect('accounts')
            ->withErrors($validator->getErrors())
            ->withInput();
    }

    /**
     * Key generation
     */
    public function apikey(Request $request): RedirectResponse
    {
        if (! $user = getUser()) {
            abort(403, __('main.not_authorized'));
        }

        if ($request->input('_token') === csrf_token()) {
            $apiKey = Str::random(32);
            $message = __('users.token_success_changed');

            if ($request->input('action') === 'create') {
                $message = __('users.token_success_created');
            }

            if ($request->input('action') === 'delete') {
                $apiKey = '';
                $message = __('users.token_success_deleted');
            }

            $user->update([
                'apikey' => $apiKey,
            ]);

            setFlash('success', $message);
        } else {
            setFlash('danger', __('validator.token'));
        }

        return redirect('accounts');
    }

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

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

        if ($validator->isValid()) {
            $isLoginExists = User::query()
                ->where('login', $login)
                ->exists();

            $isLoginBlacklisted = Blacklist::query()
                ->where('type', 'login')
                ->where('value', strtolower($login))
                ->exists();

            $validator
                ->false($isLoginExists, __('users.login_already_exists'))
                ->false($isLoginBlacklisted, __('users.login_is_blacklisted'));
        }

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

        return response()->json([
            'success' => false,
            'message' => current($validator->getErrors()),
        ]);
    }
}