Failed Conditions
Pull Request — master (#55)
by Rafael
07:05
created

UsersInviteController::processUserInvite()   B

Complexity

Conditions 8
Paths 34

Size

Total Lines 86
Code Lines 51

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 40
CRAP Score 8.512

Importance

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