Passed
Pull Request — master (#37)
by Rafael
05:21
created

UsersInviteController   A

Complexity

Total Complexity 20

Size/Duplication

Total Lines 224
Duplicated Lines 0 %

Test Coverage

Coverage 80%

Importance

Changes 0
Metric Value
eloc 109
dl 0
loc 224
ccs 88
cts 110
cp 0.8
rs 10
c 0
b 0
f 0
wmc 20

5 Methods

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