Passed
Pull Request — master (#55)
by Rafael
08:50
created

UsersInviteController::processUserInvite()   C

Complexity

Conditions 10
Paths 42

Size

Total Lines 104
Code Lines 66

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 54
CRAP Score 10.4843

Importance

Changes 0
Metric Value
cc 10
eloc 66
nc 42
nop 1
dl 0
loc 104
ccs 54
cts 65
cp 0.8308
crap 10.4843
rs 6.8751
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\UsersAssociatedApps;
11
use Gewaer\Models\Roles;
12
use Phalcon\Security\Random;
13
use Phalcon\Validation;
14
use Phalcon\Validation\Validator\PresenceOf;
15
use Phalcon\Validation\Validator\StringLength;
16
use Gewaer\Exception\UnprocessableEntityHttpException;
17
use Gewaer\Exception\NotFoundHttpException;
18
use Gewaer\Exception\ServerErrorHttpException;
19
use Phalcon\Http\Response;
20
use Exception;
21
use Gewaer\Exception\ModelException;
22
use Gewaer\Traits\AuthTrait;
23
24
/**
25
 * Class LanguagesController
26
 * @property Users $userData
27
 * @property Request $request
28
 * @property Config $config
29
 * @property Apps $app
30
 * @property Mail $mail
31
 * @property Auth $auth
32
 * @property Payload $payload
33
 * @property Exp $exp
34
 * @property JWT $jwt
35
 * @package Gewaer\Api\Controllers
36
 *
37
 */
38
class UsersInviteController extends BaseController
39
{
40
    use AuthTrait;
41
42
    /*
43
     * fields we accept to create
44
     *
45
     * @var array
46
     */
47
    protected $createFields = ['invite_hash', 'companies_id', 'role_id', 'app_id', 'email'];
48
49
    /*
50
     * fields we accept to create
51
     *
52
     * @var array
53
     */
54
    protected $updateFields = ['invite_hash', 'companies_id', 'role_id', 'app_id', 'email'];
55
56
    /**
57
     * set objects
58
     *
59
     * @return void
60
     */
61 4
    public function onConstruct()
62
    {
63 4
        $this->model = new UsersInvite();
64 4
        $this->additionalSearchFields = [
65 4
            ['is_deleted', ':', '0'],
66 4
            ['companies_id', ':', $this->userData->currentCompanyId()],
67
        ];
68 4
    }
69
70
    /**
71
     * Get users invite by hash
72
     * @param string $hash
73
     * @return Response
74
     */
75 1
    public function getByHash(string $hash):Response
76
    {
77 1
        $userInvite = $this->model::findFirst([
78 1
            'conditions' => 'invite_hash =  ?0 and is_deleted = 0',
79 1
            'bind' => [$hash]
80
        ]);
81
82 1
        if (!is_object($userInvite)) {
83
            throw new NotFoundHttpException('Users Invite not found');
84
        }
85
86 1
        return $this->response($userInvite);
87
    }
88
89
    /**
90
     * Sets up invitation information for a would be user
91
     * @return Response
92
     */
93 4
    public function insertInvite(): Response
94
    {
95 4
        $request = $this->request->getPost();
96 4
        $random = new Random();
97
98 4
        $validation = new Validation();
99 4
        $validation->add('email', new PresenceOf(['message' => _('The email is required.')]));
100 4
        $validation->add('role_id', new PresenceOf(['message' => _('The role is required.')]));
101
102
        //validate this form for password
103 4
        $messages = $validation->validate($this->request->getPost());
104 4
        if (count($messages)) {
105
            foreach ($messages as $message) {
106
                throw new ServerErrorHttpException((string)$message);
107
            }
108
        }
109
110
        //Check if user was already was invited to current company and return message
111 4
        $invitedUser = $this->model::findFirst([
112 4
            'conditions' => 'email = ?0 and companies_id = ?1 and role_id = ?2',
113 4
            'bind' => [$request['email'], $this->userData->default_company, $request['role_id']]
114
        ]);
115
116 4
        if (is_object($invitedUser)) {
117
            throw new ModelException('User already invited to this company and added with this role');
118
        }
119
120
        //Save data to users_invite table and generate a hash for the invite
121 4
        $userInvite = $this->model;
122 4
        $userInvite->companies_id = $this->userData->default_company;
123 4
        $userInvite->app_id = $this->app->getId();
124 4
        $userInvite->role_id = Roles::existsById((int)$request['role_id'])->id;
125 4
        $userInvite->email = $request['email'];
126 4
        $userInvite->invite_hash = $random->base58();
127 4
        $userInvite->created_at = date('Y-m-d H:m:s');
128
129 4
        if (!$userInvite->save()) {
130
            throw new UnprocessableEntityHttpException((string) current($userInvite->getMessages()));
131
        }
132
133 4
        $this->sendInviteEmail($request['email'], $userInvite->invite_hash);
134 4
        return $this->response($userInvite);
135
    }
136
137
    /**
138
     * Send users invite email
139
     * @param string $email
140
     * @return void
141
     */
142 4
    private function sendInviteEmail(string $email, string $hash): void
143
    {
144 4
        $userExists = Users::findFirst([
145 4
            'conditions' => 'email = ?0 and is_deleted = 0',
146 4
            'bind' => [$email]
147
        ]);
148
149 4
        $invitationUrl = $this->config->app->frontEndUrl . '/users/invites/' . $hash;
150
151 4
        if (is_object($userExists)) {
152
            $invitationUrl = $this->config->app->frontEndUrl . '/users/link/' . $hash;
153
        }
154
155 4
        if (!defined('API_TESTS')) {
156
            $subject = _('You have been invited!');
157
            $this->mail
158
            ->to($email)
159
            ->subject($subject)
160
            ->content($invitationUrl)
161
            ->sendNow();
162
        }
163 4
    }
164
165
    /**
166
     * Add invited user to our system
167
     * @return Response
168
     */
169 2
    public function processUserInvite(string $hash): Response
170
    {
171 2
        $request = $this->request->getPost();
172 2
        $password = ltrim(trim($request['password']));
173
174 2
        if (empty($request)) {
175
            $request = $this->request->getJsonRawBody(true);
176
        }
177
178
        //Ok let validate user password
179 2
        $validation = new Validation();
180 2
        $validation->add('password', new PresenceOf(['message' => _('The password is required.')]));
181
182 2
        $validation->add(
183 2
            'password',
184 2
            new StringLength([
185 2
                'min' => 8,
186 2
                'messageMinimum' => _('Password is too short. Minimum 8 characters.'),
187
            ])
188
        );
189
190
        //validate this form for password
191 2
        $messages = $validation->validate($request);
192 2
        if (count($messages)) {
193
            foreach ($messages as $message) {
194
                throw new ServerErrorHttpException((string)$message);
195
            }
196
        }
197
198
        //Lets find users_invite by hash on our database
199 2
        $usersInvite = $this->model::findFirst([
200 2
                'conditions' => 'invite_hash = ?0 and is_deleted = 0',
201 2
                'bind' => [$hash]
202
            ]);
203
204 2
        if (!is_object($usersInvite)) {
205
            throw new NotFoundHttpException('Users Invite not found');
206
        }
207
208
        //Check if user already exists
209 2
        $userExists = Users::findFirst([
210 2
            'conditions' => 'email = ?0 and is_deleted = 0',
211 2
            'bind' => [$usersInvite->email]
212
        ]);
213
214 2
        if (is_object($userExists)) {
215 1
            $newUser = new UsersAssociatedCompany;
216 1
            $newUser->users_id = (int)$userExists->id;
217 1
            $newUser->companies_id = (int)$usersInvite->companies_id;
218 1
            $newUser->identify_id = $usersInvite->role_id;
219 1
            $newUser->user_active = 1;
220 1
            $newUser->user_role = Roles::existsById((int)$userExists->roles_id)->name;
221 1
            if (!$newUser->save()) {
222
                throw new UnprocessableEntityHttpException((string) current($newUser->getMessages()));
223
            }
224
225 1
            $usersAssociatedApp = new UsersAssociatedApps;
226 1
            $usersAssociatedApp->users_id = (int)$userExists->id;
227 1
            $usersAssociatedApp->companies_id = (int)$usersInvite->companies_id;
228 1
            $usersAssociatedApp->apps_id = $this->app->getId();
229 1
            $usersAssociatedApp->identify_id = $usersInvite->role_id;
230 1
            $usersAssociatedApp->user_active = 1;
231 1
            $usersAssociatedApp->user_role = Roles::existsById((int)$userExists->roles_id)->name;
232 1
            if (!$usersAssociatedApp->save()) {
233 1
                throw new Exception((string)current($usersAssociatedApp->getMessages()));
234
            }
235
        } else {
236 2
            $newUser = new Users();
237 2
            $newUser->firstname = $request['firstname'];
238 2
            $newUser->lastname = $request['lastname'];
239 2
            $newUser->displayname = $request['displayname'];
240 2
            $newUser->password = $password;
241 2
            $newUser->email = $usersInvite->email;
242 2
            $newUser->user_active = 1;
243 2
            $newUser->roles_id = $usersInvite->role_id;
244 2
            $newUser->created_at = date('Y-m-d H:m:s');
245 2
            $newUser->default_company = $usersInvite->companies_id;
246 2
            $newUser->default_company_branch = $usersInvite->company->branch->getId();
247
248
            try {
249 2
                $this->db->begin();
250
251
                //signup
252 2
                $newUser->signup();
253
254 2
                $this->db->commit();
255
            } catch (Exception $e) {
256
                $this->db->rollback();
257
258
                throw new UnprocessableEntityHttpException($e->getMessage());
259
            }
260
        }
261
262
        //Lets login the new user
263 2
        $authInfo = $this->loginUsers($usersInvite->email, $password);
264
265 2
        if (!defined('API_TESTS')) {
266
            $usersInvite->is_deleted = 1;
267
            $usersInvite->update();
268
269
            return $this->response($authInfo);
270
        }
271
272 2
        return $this->response($newUser);
273
    }
274
}
275