Passed
Pull Request — master (#37)
by Rafael
03:58
created

UsersInviteController::processUserInvite()   C

Complexity

Conditions 10
Paths 54

Size

Total Lines 118
Code Lines 71

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 55
CRAP Score 10.8353

Importance

Changes 0
Metric Value
cc 10
eloc 71
nc 54
nop 1
dl 0
loc 118
ccs 55
cts 69
cp 0.7971
crap 10.8353
rs 6.766
c 0
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
declare(strict_types=1);
4
5
namespace Gewaer\Api\Controllers;
6
7
use Gewaer\Models\UsersInvite;
8
use Gewaer\Models\Users;
9
use Gewaer\Models\UsersAssociatedCompany;
10
use Gewaer\Models\Roles;
11
use Phalcon\Security\Random;
12
use Phalcon\Validation;
13
use Phalcon\Validation\Validator\PresenceOf;
14
use Phalcon\Validation\Validator\StringLength;
15
use Gewaer\Exception\UnprocessableEntityHttpException;
16
use Gewaer\Exception\NotFoundHttpException;
17
use Gewaer\Exception\ServerErrorHttpException;
18
use Phalcon\Http\Response;
19
use Exception;
20
use Baka\Auth\Models\Sessions;
21
use Gewaer\Exception\ModelException;
22
23
/**
24
 * Class LanguagesController
25
 * @property Users $userData
26
 * @property Request $request
27
 * @property Config $config
28
 * @property Apps $app
29
 * @property Mail $mail
30
 * @property Auth $auth
31
 * @package Gewaer\Api\Controllers
32
 *
33
 */
34
class UsersInviteController extends BaseController
35
{
36
    /*
37
     * fields we accept to create
38
     *
39
     * @var array
40
     */
41
    protected $createFields = ['invite_hash', 'companies_id', 'role_id', 'app_id', 'email'];
42
43
    /*
44
     * fields we accept to create
45
     *
46
     * @var array
47
     */
48
    protected $updateFields = ['invite_hash', 'companies_id', 'role_id', 'app_id', 'email'];
49
50
    /**
51
     * set objects
52
     *
53
     * @return void
54
     */
55 4
    public function onConstruct()
56
    {
57 4
        $this->model = new UsersInvite();
58 4
        $this->additionalSearchFields = [
59 4
            ['is_deleted', ':', '0'],
60 4
            ['companies_id', ':', $this->userData->currentCompanyId()],
61
        ];
62 4
    }
63
64
    /**
65
     * Get users invite by hash
66
     * @param string $hash
67
     * @return Response
68
     */
69 1
    public function getByHash(string $hash):Response
70
    {
71 1
        $userInvite = $this->model::findFirst([
72 1
            'conditions' => 'invite_hash =  ?0 and is_deleted = 0',
73 1
            'bind' => [$hash]
74
        ]);
75
76 1
        if (!is_object($userInvite)) {
77
            throw new NotFoundHttpException('Users Invite not found');
78
        }
79
80 1
        return $this->response($userInvite);
81
    }
82
83
    /**
84
     * Sets up invitation information for a would be user
85
     * @return Response
86
     */
87 4
    public function insertInvite(): Response
88
    {
89 4
        $request = $this->request->getPost();
90 4
        $random = new Random();
91
92 4
        $validation = new Validation();
93 4
        $validation->add('email', new PresenceOf(['message' => _('The email is required.')]));
94 4
        $validation->add('role_id', new PresenceOf(['message' => _('The role is required.')]));
95
96
        //validate this form for password
97 4
        $messages = $validation->validate($this->request->getPost());
98 4
        if (count($messages)) {
99
            foreach ($messages as $message) {
100
                throw new ServerErrorHttpException((string)$message);
101
            }
102
        }
103
104
        //Check if user was already was invited to current company and return message
105 4
        $invitedUser = $this->model::findFirst([
106 4
            'conditions' => 'email = ?0 and companies_id = ?1 and role_id = ?2',
107 4
            'bind' => [$request['email'], $this->userData->default_company, $request['role_id']]
108
        ]);
109
110 4
        if (is_object($invitedUser)) {
111
            throw new ModelException('User already invited to this company and added with this role');
112
        }
113
114
        //Save data to users_invite table and generate a hash for the invite
115 4
        $userInvite = $this->model;
116 4
        $userInvite->companies_id = $this->userData->default_company;
117 4
        $userInvite->app_id = $this->app->getId();
118 4
        $userInvite->role_id = Roles::getById((int)$request['role_id'])->id;
119 4
        $userInvite->email = $request['email'];
120 4
        $userInvite->invite_hash = $random->base58();
121 4
        $userInvite->created_at = date('Y-m-d H:m:s');
122
123 4
        if (!$userInvite->save()) {
124
            throw new UnprocessableEntityHttpException((string) current($userInvite->getMessages()));
125
        }
126
127
        //Check whether user exists or not
128 4
        $userExists = Users::findFirst([
129 4
            'conditions' => 'email = ?0 and is_deleted = 0',
130 4
            'bind' => [$request['email']]
131
        ]);
132
133 4
        $invitationUrl = $this->config->app->frontEndUrl . '/users/invites/' . $userInvite->invite_hash;
134
135 4
        if (is_object($userExists)) {
136
            $invitationUrl = $this->config->app->frontEndUrl . '/users/invites/' . $userInvite->invite_hash . '/confirm';
137
        }
138
139
        // Lets send the mail
140
141 4
        if (!defined('API_TESTS')) {
142
            $subject = _('You have been invited!');
143
            $this->mail
144
            ->to($userInvite->email)
145
            ->subject($subject)
146
            ->content($invitationUrl)
147
            ->sendNow();
148
        }
149
150 4
        return $this->response($userInvite);
151
    }
152
153
    /**
154
     * Add invited user to our system
155
     * @return Response
156
     */
157 2
    public function processUserInvite(string $hash): Response
158
    {
159 2
        $request = $this->request->getPost();
160 2
        $password = ltrim(trim($request['password']));
161
162 2
        if (empty($request)) {
163
            $request = $this->request->getJsonRawBody(true);
164
        }
165
166
        //Ok let validate user password
167 2
        $validation = new Validation();
168 2
        $validation->add('password', new PresenceOf(['message' => _('The password is required.')]));
169
170 2
        $validation->add(
171 2
            'password',
172 2
            new StringLength([
173 2
                'min' => 8,
174 2
                'messageMinimum' => _('Password is too short. Minimum 8 characters.'),
175
            ])
176
        );
177
178
        //validate this form for password
179 2
        $messages = $validation->validate($request);
180 2
        if (count($messages)) {
181
            foreach ($messages as $message) {
182
                throw new ServerErrorHttpException((string)$message);
183
            }
184
        }
185
186
        //Lets find users_invite by hash on our database
187 2
        $usersInvite = $this->model::findFirst([
188 2
                'conditions' => 'invite_hash = ?0 and is_deleted = 0',
189 2
                'bind' => [$hash]
190
            ]);
191
192 2
        if (!is_object($usersInvite)) {
193
            throw new NotFoundHttpException('Users Invite not found');
194
        }
195
196
        //Check if user already exists
197 2
        $userExists = Users::findFirst([
198 2
            'conditions' => 'email = ?0 and is_deleted = 0',
199 2
            'bind' => [$usersInvite->email]
200
        ]);
201
202 2
        if (is_object($userExists)) {
203 1
            $newUser = new UsersAssociatedCompany;
204 1
            $newUser->users_id = $userExists->id;
0 ignored issues
show
Documentation Bug introduced by
It seems like $userExists->id of type Phalcon\Mvc\Model\Resultset or Phalcon\Mvc\Phalcon\Mvc\Model is incompatible with the declared type integer of property $users_id.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
205 1
            $newUser->companies_id = $userExists->default_company;
0 ignored issues
show
Documentation Bug introduced by
It seems like $userExists->default_company of type Phalcon\Mvc\Model\Resultset or Phalcon\Mvc\Phalcon\Mvc\Model is incompatible with the declared type integer of property $companies_id.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
206 1
            $newUser->identify_id = $userExists->roles_id;
0 ignored issues
show
Documentation Bug introduced by
It seems like $userExists->roles_id can also be of type Phalcon\Mvc\Model\Resultset. However, the property $identify_id is declared as type string. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
207 1
            $newUser->user_active = 1;
208 1
            $newUser->user_role = Roles::getById((int)$userExists->roles_id)->name;
209
210 1
            if (!$newUser->save()) {
211 1
                throw new UnprocessableEntityHttpException((string) current($newUser->getMessages()));
212
            }
213
        } else {
214 2
            $newUser = new Users();
215 2
            $newUser->firstname = $request['firstname'];
216 2
            $newUser->lastname = $request['lastname'];
217 2
            $newUser->displayname = $request['displayname'];
218 2
            $newUser->password = $password;
219 2
            $newUser->email = $usersInvite->email;
220 2
            $newUser->user_active = 1;
221 2
            $newUser->roles_id = $usersInvite->role_id;
222 2
            $newUser->created_at = date('Y-m-d H:m:s');
223 2
            $newUser->default_company = $usersInvite->companies_id;
224 2
            $newUser->default_company_branch = $usersInvite->company->branch->getId();
225
226
            try {
227 2
                $this->db->begin();
228
229
                //signup
230 2
                $newUser->signup();
231
232 2
                $this->db->commit();
233
            } catch (Exception $e) {
234
                $this->db->rollback();
235
236
                throw new UnprocessableEntityHttpException($e->getMessage());
237
            }
238
        }
239
240
        //Lets login the new user
241 2
        $userIp = !defined('API_TESTS') ? $this->request->getClientAddress() : '127.0.0.1';
242
243 2
        $random = new \Phalcon\Security\Random();
244
245 2
        $userData = Users::login($usersInvite->email, $password, 1, 0, $userIp);
246
247 2
        $sessionId = $random->uuid();
248
249
        //save in user logs
250
        $payload = [
251 2
            'sessionId' => $sessionId,
252 2
            'email' => $userData->getEmail(),
253 2
            'iat' => time(),
254
        ];
255
256 2
        $token = $this->auth->make($payload);
257
258
        //start session
259 2
        $session = new Sessions();
260 2
        $session->start($userData, $sessionId, $token, $userIp, 1);
261
262 2
        if (!defined('API_TESTS')) {
263
            $usersInvite->is_deleted = 1;
264
            $usersInvite->update();
265
266
            return $this->response([
267
                'token' => $token,
268
                'time' => date('Y-m-d H:i:s'),
269
                'expires' => date('Y-m-d H:i:s', time() + $this->config->jwt->payload->exp),
270
                'id' => $userData->getId(),
271
            ]);
272
        }
273
274 2
        return $this->response($newUser);
275
    }
276
}
277