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

UsersInviteController::insertInvite()   B

Complexity

Conditions 6
Paths 9

Size

Total Lines 48
Code Lines 28

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 24
CRAP Score 6.1844

Importance

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