Passed
Pull Request — master (#61)
by Rafael
06:01
created

UsersController::getActiveDevices()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 12
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 6

Importance

Changes 0
Metric Value
cc 2
eloc 6
nc 2
nop 0
dl 0
loc 12
ccs 0
cts 7
cp 0
crap 6
rs 10
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\Users;
8
use Gewaer\Models\UserLinkedSources;
9
use Baka\Auth\Models\Sources;
10
use Gewaer\Models\Companies;
11
use Phalcon\Http\Response;
12
use Phalcon\Validation;
13
use Phalcon\Validation\Validator\PresenceOf;
14
use Gewaer\Exception\BadRequestHttpException;
15
use Gewaer\Exception\UnprocessableEntityHttpException;
16
use Baka\Http\QueryParser;
17
use Gewaer\Exception\ModelException;
18
use Gewaer\Exception\NotFoundHttpException;
19
use Gewaer\Models\AccessList;
20
21
/**
22
 * Class UsersController
23
 *
24
 * @package Gewaer\Api\Controllers
25
 *
26
 * @property Users $userData
27
 * @property Request $request
28
 * @property Config $config
29
 * @property Apps $app
30
 */
31
class UsersController extends \Baka\Auth\UsersController
32
{
33
    /*
34
     * fields we accept to create
35
     *
36
     * @var array
37
     */
38
    protected $createFields = ['name', 'firstname', 'lastname', 'displayname', 'language', 'email', 'password', 'created_at', 'updated_at', 'default_company', 'family', 'cell_phone_number', 'country_id'];
39
40
    /*
41
     * fields we accept to create
42
     *
43
     * @var array
44
     */
45
    protected $updateFields = ['name', 'firstname', 'lastname', 'displayname', 'language', 'email', 'password', 'created_at', 'updated_at', 'default_company', 'cell_phone_number', 'country_id'];
46
47
    /**
48
     * set objects
49
     *
50
     * @return void
51
     */
52 3
    public function onConstruct()
53
    {
54 3
        $this->model = new Users();
55
56
        //if you are not a admin you cant see all the users
57 3
        if (!$this->userData->hasRole('Defaults.Admins')) {
58
            $this->additionalSearchFields = [
59
                ['id', ':', $this->userData->getId()],
60
            ];
61
        } else {
62
            //admin get all the users for this company
63 3
            $this->additionalSearchFields = [
64 3
                ['default_company', ':', $this->userData->currentCompanyId()],
65
            ];
66
        }
67 3
    }
68
69
    /**
70
     * Get Uer
71
     *
72
     * @param mixed $id
73
     *
74
     * @method GET
75
     * @url /v1/users/{id}
76
     *
77
     * @return Response
78
     */
79
    public function getById($id) : Response
80
    {
81
        //find the info
82
        $user = $this->model->findFirst([
83
            'id = ?0 AND is_deleted = 0',
84
            'bind' => [$this->userData->getId()],
85
        ]);
86
87
        $user->password = null;
88
89
        //get relationship
90
        if ($this->request->hasQuery('relationships')) {
91
            $relationships = $this->request->getQuery('relationships', 'string');
92
93
            $user = QueryParser::parseRelationShips($relationships, $user);
94
        }
95
96
        //if you search for roles we give you the access for this app
97
        if (array_key_exists('roles', $user)) {
98
            $accesList = AccessList::find([
99
                'conditions' => 'roles_name = ?0 and apps_id = ?1 and allowed = 0',
100
                'bind' => [$user['roles'][0]->name, $this->config->app->id]
101
            ]);
102
103
            if (count($accesList) > 0) {
104
                foreach ($accesList as $access) {
105
                    $user['access_list'][strtolower($access->resources_name)][$access->access_name] = 0;
106
                }
107
            }
108
        }
109
110
        if ($user) {
111
            return $this->response($user);
112
        } else {
113
            throw new ModelException('Record not found');
114
        }
115
    }
116
117
    /**
118
     * Update a User Info
119
     *
120
     * @method PUT
121
     * @url /v1/users/{id}
122
     *
123
     * @return Response
124
     */
125
    public function edit($id) : Response
126
    {
127
        //none admin users can only edit themselves
128
        if (!$this->userData->hasRole('Default.Admins')) {
129
            $id = $this->userData->getId();
130
        }
131
132
        if ($user = $this->model->findFirst($id)) {
133
            $request = $this->request->getPut();
134
135
            if (empty($request)) {
136
                $request = $this->request->getJsonRawBody(true);
137
            }
138
139
            if (empty($request)) {
140
                throw new BadRequestHttpException(_('No data to update this account with '));
141
            }
142
143
            //update password
144
            if (array_key_exists('new_password', $request) && (!empty($request['new_password']) && !empty($request['current_password']))) {
145
                //Ok let validate user password
146
                $validation = new Validation();
147
                $validation->add('new_password', new PresenceOf(['message' => 'The new_password is required.']));
148
                $validation->add('current_password', new PresenceOf(['message' => 'The current_password is required.']));
149
                $validation->add('confirm_new_password', new PresenceOf(['message' => 'The confirm_new_password is required.']));
150
                $messages = $validation->validate($request);
151
152
                if (count($messages)) {
153
                    foreach ($messages as $message) {
154
                        throw new BadRequestHttpException((string)$message);
155
                    }
156
                }
157
158
                $user->updatePassword($request['current_password'], $request['new_password'], $request['confirm_new_password']);
159
            } else {
160
                //remove on any actino that doesnt involve password
161
                unset($request['password']);
162
            }
163
164
            //change my default company
165
            if (array_key_exists('default_company', $request)) {
166
                if ($company = Companies::findFirst($request['default_company'])) {
167
                    if ($company->userAssociatedToCompany($this->userData)) {
168
                        $user->default_company = $company->getId();
169
                        unset($request['default_company']);
170
                    }
171
                }
172
            }
173
174
            //update
175
            if ($user->update($request, $this->updateFields)) {
176
                $user->password = null;
177
                return $this->response($user);
178
            } else {
179
                //didnt work
180
                throw new ModelException((string)current($user->getMessages()));
181
            }
182
        } else {
183
            throw new NotFoundHttpException('Record not found');
184
        }
185
    }
186
187
    /**
188
     * Add users notifications
189
     *
190
     * @param int $id
191
     * @method PUT
192
     * @return Response
193
     */
194
    public function updateNotifications(int $id) : Response
195
    {
196
        //get the notification array
197
        //delete the current ones
198
        //iterate and save into users
199
200
        return $this->response(['OK' => $id]);
201
    }
202
203
    /**
204
     * Associate a Device with the corrent loggedin user
205
     *
206
     * @url /users/{id}/device
207
     * @method POST
208
     * @return Response
209
     */
210 2
    public function devices() : Response
211
    {
212
        //Ok let validate user password
213 2
        $validation = new Validation();
214 2
        $validation->add('app', new PresenceOf(['message' => _('App name is required.')]));
215 2
        $validation->add('deviceId', new PresenceOf(['message' => _('device ID is required.')]));
216 2
        $msg = null;
217
218
        //validate this form for password
219 2
        $messages = $validation->validate($this->request->getPost());
220 2
        if (count($messages)) {
221
            foreach ($messages as $message) {
222
                throw new BadRequestHttpException((string)$message);
223
            }
224
        }
225
226 2
        $app = $this->request->getPost('app', 'string');
227 2
        $deviceId = $this->request->getPost('deviceId', 'string');
228
229
        //get the app source
230 2
        if ($source = Sources::getByTitle($app)) {
231 2
            $userSource = UserLinkedSources::findFirst([
232 2
                'conditions' => 'users_id = ?0 and source_users_id_text = ?1',
233 2
                'bind' => [$this->userData->getId(), $deviceId]
234
            ]);
235
236 2
            if (!is_object($userSource)) {
237 1
                $userSource = new UserLinkedSources();
238 1
                $userSource->users_id = $this->userData->getId();
239 1
                $userSource->source_id = $source->getId();
240 1
                $userSource->source_users_id = $this->userData->getId();
241 1
                $userSource->source_users_id_text = $deviceId;
242 1
                $userSource->source_username = $this->userData->displayname . ' ' . $app;
243
244 1
                if (!$userSource->save()) {
245
                    throw new UnprocessableEntityHttpException((string) current($userSource->getMessages()));
246
                }
247
248 1
                $msg = 'User Device Associated';
249
            } else {
250 1
                $msg = 'User Device Already Associated';
251
            }
252
        }
253
254
        //clean password @todo move this to a better place
255 2
        $this->userData->password = null;
256
257 2
        return $this->response([
258 2
            'msg' => $msg,
259 2
            'user' => $this->userData
260
        ]);
261
    }
262
263
    /**
264
     * Detach user's devices
265
     * @param integer $deviceId User's devices id
266
     * @return Response
267
     */
268 1
    public function detachDevice(int $id, int $deviceId): Response
269
    {
270
        //Validation
271 1
        $validation = new Validation();
272 1
        $validation->add('app', new PresenceOf(['message' => _('App name is required.')]));
273
274
        //validate this form for password
275 1
        $messages = $validation->validate($this->request->getPost());
276 1
        if (count($messages)) {
277
            foreach ($messages as $message) {
278
                throw new BadRequestHttpException((string)$message);
279
            }
280
        }
281
282 1
        $app = $this->request->getPost('app', 'string');
283
284
        //Get Source
285
286 1
        $source = Sources::getByTitle($app);
287
288 1
        if (!is_object($source)) {
289
            throw new NotFoundHttpException('Source not found');
290
        }
291
292 1
        $userSource = UserLinkedSources::findFirst([
293 1
                'conditions' => 'users_id = ?0 and source_id = ?1 and source_users_id_text = ?2 and is_deleted = 0',
294 1
                'bind' => [$this->userData->getId(), $source->getId(), $deviceId]
295
            ]);
296
297
        //Check if User Linked Sources exists by users_id and source_users_id_text
298 1
        if (!is_object($userSource)) {
299
            throw new NotFoundHttpException('User Linked Source not found');
300
        }
301
302 1
        $userSource->is_deleted = 1;
303 1
        if (!$userSource->update()) {
304
            throw new UnprocessableEntityHttpException((string) current($userSource->getMessages()));
305
        }
306
307 1
        return $this->response([
308 1
                'msg' => 'User Device detached',
309 1
                'user' => $this->userData
310
            ]);
311
    }
312
313
    /**
314
     * Get current active device of user
315
     * @return Response
316
     */
317
    public function getActiveDevices(): Response
318
    {
319
        $userSources = UserLinkedSources::find([
320
                'conditions' => "users_id = ?0 and source_id in ('androipapp','iosapp') and is_deleted = 0",
321
                'bind' => [$this->userData->getId()]
322
            ]);
323
324
        if (empty($userSources->toArray())) {
325
            throw new NotFoundHttpException('User Linked Sources not found');
326
        }
327
328
        return $this->response($userSources);
329
    }
330
}
331