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

UsersInviteController::insertInvite()   B

Complexity

Conditions 6
Paths 9

Size

Total Lines 54
Code Lines 32

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 23
CRAP Score 7.0014

Importance

Changes 0
Metric Value
cc 6
eloc 32
nc 9
nop 0
dl 0
loc 54
ccs 23
cts 33
cp 0.6969
crap 7.0014
rs 8.7857
c 0
b 0
f 0

How to fix   Long Method   

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
        // Lets send the mail
128
129 4
        $invitationUrl = $this->config->app->frontEndUrl . '/users/invites/' . $userInvite->invite_hash;
130
131 4
        if (!defined('API_TESTS')) {
132
            $subject = _('You have been invited!');
133
            $this->mail
134
            ->to($userInvite->email)
135
            ->subject($subject)
136
            ->content($invitationUrl)
137
            ->sendNow();
138
        }
139
140 4
        return $this->response($userInvite);
141
    }
142
143
    /**
144
     * Add invited user to our system
145
     * @return Response
146
     */
147 2
    public function processUserInvite(string $hash): Response
148
    {
149 2
        $request = $this->request->getPost();
150 2
        $password = ltrim(trim($request['password']));
151
152 2
        if (empty($request)) {
153
            $request = $this->request->getJsonRawBody(true);
154
        }
155
156
        //Ok let validate user password
157 2
        $validation = new Validation();
158 2
        $validation->add('password', new PresenceOf(['message' => _('The password is required.')]));
159
160 2
        $validation->add(
161 2
            'password',
162 2
            new StringLength([
163 2
                'min' => 8,
164 2
                'messageMinimum' => _('Password is too short. Minimum 8 characters.'),
165
            ])
166
        );
167
168
        //validate this form for password
169 2
        $messages = $validation->validate($request);
170 2
        if (count($messages)) {
171
            foreach ($messages as $message) {
172
                throw new ServerErrorHttpException((string)$message);
173
            }
174
        }
175
176
        //Lets find users_invite by hash on our database
177 2
        $usersInvite = $this->model::findFirst([
178 2
                'conditions' => 'invite_hash = ?0 and is_deleted = 0',
179 2
                'bind' => [$hash]
180
            ]);
181
182 2
        if (!is_object($usersInvite)) {
183
            throw new NotFoundHttpException('Users Invite not found');
184
        }
185
186
        //Check if user already exists
187 2
        $userExists = Users::findFirst([
188 2
            'conditions' => 'email = ?0 and is_deleted = 0',
189 2
            'bind' => [$usersInvite->email]
190
        ]);
191
192 2
        if (is_object($userExists)) {
193 1
            $newUser = new UsersAssociatedCompany;
194 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...
195 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...
196 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...
197 1
            $newUser->user_active = 1;
198 1
            $newUser->user_role = Roles::getById((int)$userExists->roles_id)->name;
199
200 1
            if (!$newUser->save()) {
201 1
                throw new UnprocessableEntityHttpException((string) current($newUser->getMessages()));
202
            }
203
        } else {
204 2
            $newUser = new Users();
205 2
            $newUser->firstname = $request['firstname'];
206 2
            $newUser->lastname = $request['lastname'];
207 2
            $newUser->displayname = $request['displayname'];
208 2
            $newUser->password = $password;
209 2
            $newUser->email = $usersInvite->email;
210 2
            $newUser->user_active = 1;
211 2
            $newUser->roles_id = $usersInvite->role_id;
212 2
            $newUser->created_at = date('Y-m-d H:m:s');
213 2
            $newUser->default_company = $usersInvite->companies_id;
214 2
            $newUser->default_company_branch = $usersInvite->company->branch->getId();
215
216
            try {
217 2
                $this->db->begin();
218
219
                //signup
220 2
                $newUser->signup();
221
222 2
                $this->db->commit();
223
            } catch (Exception $e) {
224
                $this->db->rollback();
225
226
                throw new UnprocessableEntityHttpException($e->getMessage());
227
            }
228
        }
229
230
        //Lets login the new user
231 2
        $userIp = !defined('API_TESTS') ? $this->request->getClientAddress() : '127.0.0.1';
232
233 2
        $random = new \Phalcon\Security\Random();
234
235 2
        $userData = Users::login($usersInvite->email, $password, 1, 0, $userIp);
236
237 2
        $sessionId = $random->uuid();
238
239
        //save in user logs
240
        $payload = [
241 2
            'sessionId' => $sessionId,
242 2
            'email' => $userData->getEmail(),
243 2
            'iat' => time(),
244
        ];
245
246 2
        $token = $this->auth->make($payload);
247
248
        //start session
249 2
        $session = new Sessions();
250 2
        $session->start($userData, $sessionId, $token, $userIp, 1);
251
252 2
        if (!defined('API_TESTS')) {
253
            $usersInvite->is_deleted = 1;
254
            $usersInvite->update();
255
256
            return $this->response([
257
                'token' => $token,
258
                'time' => date('Y-m-d H:i:s'),
259
                'expires' => date('Y-m-d H:i:s', time() + $this->config->jwt->payload->exp),
260
                'id' => $userData->getId(),
261
            ]);
262
        }
263
264 2
        return $this->response($newUser);
265
    }
266
}
267