madbob/GASdottoNG

View on GitHub
code/app/Services/UsersService.php

Summary

Maintainability
C
1 day
Test Coverage
<?php

namespace App\Services;

use App\Exceptions\AuthException;
use Illuminate\Support\Str;

use Auth;
use Log;
use DB;
use Hash;

use App\Exceptions\IllegalArgumentException;
use App\Notifications\ApprovedMessage;
use App\Notifications\DeclinedMessage;
use App\User;
use App\Role;

class UsersService extends BaseService
{
    public function list($term = '', $all = false)
    {
        /*
            Esiste il caso di un utente che non può vedere l'elenco degli utenti
            ma può effettuare le consegne, e pertanto - per definizione - fare
            prenotazioni anche per conto terzi. Questa autorizzazione serve per
            permettere la ricerca nel pannello "Prenotazioni per Altri Utenti"
        */
        $user = $this->ensureAuth(['users.admin' => 'gas', 'users.movements' => 'gas', 'users.view' => 'gas', 'supplier.shippings' => null]);

        $gas_id = $user->gas['id'];
        $query = User::with('roles')->topLevel()->where('gas_id', '=', $gas_id);

        if (!empty($term)) {
            $query->where(function ($query) use ($term) {
                $query->where('firstname', 'LIKE', "%$term%")->orWhere('lastname', 'LIKE', "%$term%");
            });
        }

        if ($all) {
            $query->filterEnabled();
        }

        $users = $query->sorted()->get();
        return $users;
    }

    public function show($id)
    {
        $searched = User::withTrashed()->findOrFail($id);

        if ($searched->testUserAccess() == false) {
            $this->ensureAuth(['users.admin' => 'gas', 'users.view' => 'gas']);
        }

        return $searched;
    }

    private function setCommonAttributes($user, $request)
    {
        $this->setIfSet($user, $request, 'username');
        $this->setIfSet($user, $request, 'firstname');
        $this->setIfSet($user, $request, 'lastname');
    }

    private function updatePassword($user, $request)
    {
        $user->password = Hash::make($request['password']);
        \Log::debug('Cambio password utente ' . $user->username);

        if (isset($request['enforce_password_change']) && $request['enforce_password_change'] == 'true') {
            $user->enforce_password_change = true;
        }

        $user->save();
    }

    public function store(array $request)
    {
        DB::beginTransaction();

        /*
            Gli utenti col permesso di agire sul multi-gas devono poter creare i
            nuovi utenti amministratori
        */
        $creator = $this->ensureAuth(['users.admin' => 'gas', 'gas.multi' => 'gas']);

        $user = new User();
        $this->setCommonAttributes($user, $request);
        $user->gas_id = $creator->gas->id;
        $user->member_since = date('Y-m-d', time());
        $user->password = Hash::make(Str::random(10));
        $user->save();

        if (isset($request['sendmail'])) {
            $user->addContact('email', $request['email']);
            $user->initialWelcome();
        }
        else {
            $this->updatePassword($user, $request);
        }

        DB::commit();
        return $user;
    }

    public function storeFriend(array $request)
    {
        DB::beginTransaction();

        $creator = $this->ensureAuth(['users.subusers' => 'gas']);
        if (isset($request['creator_id'])) {
            $creator = User::findOrFail($request['creator_id']);
        }

        $user = new User();
        $this->setCommonAttributes($user, $request);
        $user->parent_id = $creator->id;
        $user->gas_id = $creator->gas->id;
        $user->member_since = date('Y-m-d', time());
        $this->updatePassword($user, $request);
        DB::commit();
        return $user;
    }

    private function updateAccessType($id, $request)
    {
        $user = Auth::user();
        if (is_null($user)) {
            throw new AuthException(401);
        }

        if ($user->can('users.admin', $user->gas)) {
            $type = 1;
        }
        else if ($user->id == $id) {
            if ($user->can('users.self', $user->gas) == false) {
                /*
                    Anche laddove non sia concesso agli utenti il permesso di
                    cambiare la propria anagrafica, devono comunque poter cambiare
                    la propria password. Se quello è il solo parametro passato, la
                    nuova password viene salvata e la funzione ritorna
                    correttamente, altrimenti si testa il suddetto permesso
                */
                if (isset($request['password']) && !empty($request['password'])) {
                    $user = $this->show($id);

                    $this->transformAndSetIfSet($user, $request, 'password', function ($password) use ($user) {
                        \Log::debug('Cambio password utente ' . $user->username);
                        return Hash::make($password);
                    });

                    $user->enforce_password_change = false;
                    $user->save();
                    return $user;
                }

                throw new AuthException(403);
            }

            $type = 2;
        }
        else if ($user->can('users.subusers', $user->gas)) {
            $test = $this->show($id);
            if ($test->parent_id == $user->id) {
                $type = 2;
            }
            else {
                throw new AuthException(403);
            }
        }
        else {
            throw new AuthException(403);
        }

        return $type;
    }

    private function readRID($user, $request)
    {
        if ($user->gas->hasFeature('rid')) {
            $rid = $user->rid;
            $changed = false;

            if (isset($request['rid->iban'])) {
                $rid['iban'] = $request['rid->iban'];
                $changed = true;
            }

            if (isset($request['rid->id'])) {
                $rid['id'] = $request['rid->id'];
                $changed = true;
            }

            if (isset($request['rid->date'])) {
                $rid['date'] = decodeDate($request['rid->date']);
                $changed = true;
            }

            if ($changed) {
                $user->rid = $rid;
            }
        }
    }

    public function update($id, array $request)
    {
        $type = $this->updateAccessType($id, $request);
        if (is_object($type)) {
            return $type;
        }

        DB::beginTransaction();

        $user = $this->show($id);

        $this->setCommonAttributes($user, $request);
        $this->setIfSet($user, $request, 'birthplace');
        $this->transformAndSetIfSet($user, $request, 'birthday', "decodeDate");
        $this->setIfSet($user, $request, 'taxcode');
        $this->transformAndSetIfSet($user, $request, 'family_members', 'enforceNumber');
        $this->setIfSet($user, $request, 'preferred_delivery_id');
        $this->setIfSet($user, $request, 'payment_method_id');

        if ($type == 1) {
            $user->enforce_password_change = (isset($request['enforce_password_change']) && $request['enforce_password_change'] == 'true');

            if (isset($request['status'])) {
                $user->setStatus($request['status'], $request['deleted_at'], $request['suspended_at']);
            }

            $this->transformAndSetIfSet($user, $request, 'member_since', "decodeDate");
            $this->setIfSet($user, $request, 'card_number');
        }
        else {
            $user->enforce_password_change = false;
        }

        if (isset($request['password']) && !empty($request['password'])) {
            $this->transformAndSetIfSet($user, $request, 'password', function ($password) use ($user) {
                \Log::debug('Cambio password utente ' . $user->username);
                return Hash::make($password);
            });
        }

        $this->readRID($user, $request);
        $user->save();

        handleFileUpload($request, $user, 'picture');
        $user->updateContacts($request);

        DB::commit();
        return $user;
    }

    public function revisioned($id, $approved)
    {
        DB::beginTransaction();

        $user = $this->show($id);

        if ($approved) {
            $user->pending = false;
            $user->save();

            try {
                $user->notify(new ApprovedMessage());
            }
            catch(\Exception $e) {
                \Log::error('Impossibile notificare approvazione utente');
            }
        }
        else {
            try {
                $user->notify(new DeclinedMessage());
            }
            catch(\Exception $e) {
                \Log::error('Impossibile notificare non approvazione utente');
            }

            $user->forceDelete();
        }

        DB::commit();
    }

    public function promoteFriend($request, $id)
    {
        $admin = $this->ensureAuth(['users.admin' => 'gas']);

        $roles = app()->make('RolesService');
        $friend_role = $admin->gas->roles['friend'];
        $user_role = $admin->gas->roles['user'];

        $roles->detachUser($id, $friend_role, null);
        $roles->attachUser($id, $user_role, null);

        $user = $this->show($id);
        $user->parent_id = null;
        $user->save();

        $email = $request['email'] ?? null;
        if ($email) {
            $user->addContact('email', $email);
        }

        return $user;
    }

    public function reassignFriend($user_id, $parent_id)
    {
        $this->ensureAuth(['users.admin' => 'gas']);

        if ($parent_id == $user_id) {
            throw new IllegalArgumentException(_i('Un utente non può essere amico di sé stesso'), 1);
        }

        $parent = $this->show($parent_id);
        if ($parent->can('users.subusers') == false) {
            throw new IllegalArgumentException(_i("Il nuovo utente assegnatario non può gestire amici"), 1);
        }

        $user = $this->show($user_id);
        if ($user->isFriend() == false) {
            throw new IllegalArgumentException(_i('Un utente regolare non può essere retrocesso ad amico'), 1);
        }

        $user->parent_id = $parent->id;
        $user->save();

        return $user;
    }

    public function picture($id)
    {
        $user = $this->show($id);
        return downloadFile($user, 'picture');
    }

    public function notifications($id, $suppliers)
    {
        $user = $this->show($id);

        if ($user->testUserAccess() == false) {
            $this->ensureAuth(['users.admin' => 'gas']);
        }

        $user->suppliers()->sync($suppliers);
    }

    public function destroy($id)
    {
        DB::beginTransaction();

        $user = $this->show($id);

        if ($user->testUserAccess() == false) {
            $this->ensureAuth(['users.admin' => 'gas']);
        }

        if ($user->trashed()) {
            $user->forceDelete();
        }
        else {
            $user->delete();
        }

        DB::commit();
        return $user;
    }
}