Code Coverage
 
Classes and Traits
Functions and Methods
Lines
Total
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
19 / 19
CRAP
100.00% covered (success)
100.00%
146 / 146
UsersController
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
19 / 19
37
100.00% covered (success)
100.00%
146 / 146
 __construct
100.00% covered (success)
100.00%
1 / 1
1
100.00% covered (success)
100.00%
2 / 2
 validator
100.00% covered (success)
100.00%
1 / 1
2
100.00% covered (success)
100.00%
12 / 12
 index
100.00% covered (success)
100.00%
1 / 1
1
100.00% covered (success)
100.00%
1 / 1
 store
100.00% covered (success)
100.00%
1 / 1
1
100.00% covered (success)
100.00%
9 / 9
 show
100.00% covered (success)
100.00%
1 / 1
1
100.00% covered (success)
100.00%
1 / 1
 update
100.00% covered (success)
100.00%
1 / 1
1
100.00% covered (success)
100.00%
8 / 8
 destroy
100.00% covered (success)
100.00%
1 / 1
1
100.00% covered (success)
100.00%
3 / 3
 changePwd
100.00% covered (success)
100.00%
1 / 1
2
100.00% covered (success)
100.00%
9 / 9
 forgotPwd
100.00% covered (success)
100.00%
1 / 1
1
100.00% covered (success)
100.00%
4 / 4
 getUsersFromv2
100.00% covered (success)
100.00%
1 / 1
1
100.00% covered (success)
100.00%
2 / 2
 manageEntities
100.00% covered (success)
100.00%
1 / 1
3
100.00% covered (success)
100.00%
11 / 11
 broker
100.00% covered (success)
100.00%
1 / 1
1
100.00% covered (success)
100.00%
1 / 1
 credentialsSendResetLink
100.00% covered (success)
100.00%
1 / 1
1
100.00% covered (success)
100.00%
1 / 1
 credentialsReset
100.00% covered (success)
100.00%
1 / 1
1
100.00% covered (success)
100.00%
2 / 2
 resetPassword
100.00% covered (success)
100.00%
1 / 1
1
100.00% covered (success)
100.00%
12 / 12
 sendResetLink
100.00% covered (success)
100.00%
1 / 1
5
100.00% covered (success)
100.00%
16 / 16
 sendNotificationResetPwd
100.00% covered (success)
100.00%
1 / 1
4
100.00% covered (success)
100.00%
19 / 19
 getUsersByEntity
100.00% covered (success)
100.00%
1 / 1
2
100.00% covered (success)
100.00%
19 / 19
 getSitesByUser
100.00% covered (success)
100.00%
1 / 1
7
100.00% covered (success)
100.00%
14 / 14
1<?php
2
3namespace Qmp\Laravel\ExternalUsers\Controllers;
4
5use Illuminate\Http\Exceptions\HttpResponseException;
6use Illuminate\Support\Facades\Log;
7use Illuminate\Support\Str;
8use Illuminate\Support\Arr;
9use Illuminate\Validation\Rule;
10use Illuminate\Http\Response;
11use Illuminate\Http\Request;
12use Qmp\Laravel\ApiDigitalV2\Api\DigitalV2InterfaceProvider;
13use Qmp\Laravel\ExternalUsers\Models\EntityUser;
14use Qmp\Laravel\ExternalUsers\Models\User;
15use Illuminate\Support\Facades\Password;
16use Illuminate\Auth\Events\PasswordReset;
17use Illuminate\Support\Facades\Hash;
18use Qmp\Laravel\ExternalUsers\Models\Site;
19use Qmp\Laravel\MicroService\Controllers\AbstractMicroServiceController;
20
21use Qmp\Laravel\MicroService\Client\Tools\Request as ClientRequest;
22use Qmp\Laravel\MicroService\Client\Client;
23
24class UsersController extends AbstractMicroServiceController
25{
26    public function __construct(Request $request)
27    {
28        parent::__construct($request);
29    }
30
31    protected function validator(Request $request, User $user = null)
32    {
33        $rules = [
34            'name' => 'required|string',
35            'email' => [
36                'required',
37                'email',
38            ],
39            'type' => [
40                'required',
41                Rule::in([User::TYPE_PUBLISHER, User::TYPE_ADVERTISER]),
42            ],
43            /*'sites' => [
44                'required',
45                'array'
46            ]*/
47        ];
48
49        if ($user) {
50            $rules['email'][] = Rule::unique($user->getConnectionName() . '.' . $user->getTable())->ignore($user);
51            $rules['active'] = [
52                'required',
53                Rule::in([0, 1]),
54            ];
55        } else {
56            $user = new User();
57            $rules['email'][] = Rule::unique($user->getConnectionName() . '.' . $user->getTable());
58        }
59
60        $use = $request->validate($rules);
61    }
62
63    public function index(Request $request)
64    {
65        // List all external users with attached sites
66        return response()->json(User::all());
67    }
68
69    public function store(Request $request)
70    {
71        // Create new external user
72        $this->validator($request);
73        $user = new User();
74        $user->name = $request->name;
75        $user->email = $request->email;
76        $user->type = $request->type;
77        $user->save();
78        $user->sites()->sync($request->sites);
79        $user->refresh();
80
81        // Send mail to create his password
82        // $this->sendNotificationResetPwd($request);
83
84        return response()->json(['status' => 'ok', 'user' => $user], 201);
85    }
86
87    public function show(Request $request, User $user)
88    {
89        // Show detail of user with attached sites
90        //$user->sites = $user->sites;
91        return response()->json($user);
92    }
93
94    public function update(Request $request, User $user)
95    {
96        // Update external user infos and attached sites
97        $this->validator($request, $user);
98        $user->name = $request->name;
99        $user->email = $request->email;
100        $user->type = $request->type;
101        $user->active = $request->active;
102        $user->save();
103        $user->sites()->sync($request->sites);
104
105        return response()->json(['status' => 'ok']);
106    }
107
108    public function destroy(Request $request, User $user)
109    {
110        // Inactive external user
111        $user->active = 0;
112        $user->save();
113
114        return response()->json(['status' => 'ok']);
115    }
116
117    public function changePwd(Request $request, User $user)
118    {
119        // Create or Update password from external user request
120        $request->validate([
121            'token' => 'required',
122            'email' => 'required|email',
123            'password' => 'required|confirmed|min:8',
124        ]);
125
126        $response = $this->broker()->reset(
127            $this->credentialsReset($request), function ($user, $password) {
128            $this->resetPassword($user, $password);
129        });
130
131        if ($response != Password::PASSWORD_RESET) {
132            throw new HttpResponseException(response()->json(['errors' => ['unable to change user password']], 422));
133        }
134
135        return response()->json(['status' => 'ok']);
136    }
137
138    public function forgotPwd(Request $request)
139    {
140        $request->validate([
141            'email' => 'required|email',
142        ]);
143
144        // Send mail to create his password
145        $this->sendNotificationResetPwd($request);
146
147        return response()->json(['status' => 'ok'], 200);
148    }
149
150    public function getUsersFromv2()
151    {
152        $users = resolve(DigitalV2InterfaceProvider::class)->getExternalUsers();
153
154        return response()->json($users);
155    }
156
157    public function manageEntities(Request $request)
158    {
159        $request->validate([
160            'id' => 'required|string',
161            'add' => 'present|array',
162            'delete' => 'present|array'
163        ]);
164
165
166        foreach ($request->delete as $user_id) {
167            EntityUser::where('user_id', $user_id)
168                ->where('entity_id', $request->id)
169                ->delete();
170        }
171
172        foreach ($request->add as $user_id) {
173            EntityUser::create([
174                'entity_id' => $request->id,
175                'user_id' => $user_id
176            ]);
177        }
178
179        return response()->json(["status" => "ok"], Response::HTTP_OK);
180    }
181
182    public function broker()
183    {
184        return Password::broker('external_users');
185    }
186
187    protected function credentialsSendResetLink(Request $request)
188    {
189        return $request->only('email');
190    }
191
192    protected function credentialsReset(Request $request)
193    {
194        return $request->only(
195            'email', 'password', 'password_confirmation', 'token'
196        );
197    }
198
199    protected function resetPassword($user, $password)
200    {
201        $httprequest = ClientRequest::createObject('service_entities', 'entity/from-url', ['body' => [
202            'url' => $this->httpOrigin
203        ]]);
204        $response = Client::systemSend('post', $httprequest)->content;
205
206        $entityPwd = EntityUser::where('entity_id', $response['id'])
207            ->where('user_id', $user->id)
208            ->first();
209
210        $entityPwd->password = Hash::make($password);
211        $entityPwd->save();
212
213        $user->setRememberToken(Str::random(60));
214
215        $user->save();
216
217        event(new PasswordReset($user));
218    }
219
220    protected function sendResetLink(array $credentials, array $config)
221    {
222        // Override PasswordBroker::sendResetLink method
223
224        $broker = $this->broker();
225        $user = $broker->getUser($credentials);
226
227        if (is_null($user)) {
228            return Password::INVALID_USER;
229        }
230
231        $entityUser = EntityUser::where('entity_id', $config['entity_id'])
232            ->where('user_id', $user->id)
233            ->first();
234
235        if (is_null($entityUser)) {
236            return Password::INVALID_USER;
237        }
238
239        $tokens = $broker->getRepository();
240
241        if (method_exists($tokens, 'recentlyCreatedToken') &&
242            $tokens->recentlyCreatedToken($user)) {
243            return Password::RESET_THROTTLED;
244        }
245
246        $user->sendPasswordResetNotificationWithConfig(
247            $tokens->create($user), $config
248        );
249
250        return Password::RESET_LINK_SENT;
251    }
252
253    protected function sendNotificationResetPwd(Request $request)
254    {
255        $httprequest = ClientRequest::createObject('service_entities', 'entity/from-url', ['body' => [
256            'url' => $this->httpOrigin
257        ]]);
258        $entity = Client::systemSend('post', $httprequest)->content;
259
260        if (empty($entity)) {
261            Log::debug('No entity found for domain: ' . $this->httpOrigin);
262            throw new HttpResponseException(response()->json(['errors' => ['unable to send create password mail to this user']], 422));
263        }
264
265        $config = [];
266        if (isset($entity['config'])) {
267            $config = collect($entity['config'])->first(function ($item) {
268                return $item['id'] === 4;
269            });
270            unset($config['external-users']);
271            unset($config['id']);
272            $config['entity_id'] = $entity['id'];
273        }
274
275        // Send mail to create his password
276        $response = $this->sendResetLink(
277            $this->credentialsSendResetLink($request),
278            $config
279        );
280
281        /* $response = $this->broker()->sendResetLink(
282            $this->credentialsSendResetLink($request)
283        ); */
284
285        if ($response != Password::RESET_LINK_SENT) {
286            throw new HttpResponseException(response()->json(['errors' => ['unable to send create password mail to this user']], 422));
287        }
288    }
289
290    public function getUsersByEntity($dedupId)
291    {
292        // Get campaign
293        $request = ClientRequest::createObject('service_campaigns', 'campaign/get-by-session-id', [
294            'body' => [
295                'type' => 3,
296                'sessionId' => $dedupId
297            ]
298        ]);
299        $response = Client::systemSend('post', $request)->content;
300
301        // Get entities
302        $entityIds = [];
303        if (isset($response['datas'])) {
304            $entityIds = $response['datas']['entities'];
305        }
306
307        $request = ClientRequest::createObject('service_entities', 'entity');
308        $entities = Client::systemSend('get', $request)->content;
309
310        $entities = array_filter($entities, function ($entity) use ($entityIds) {
311            return in_array($entity['id'], $entityIds);
312        });
313
314        // Get users
315        $usersIds = EntityUser::whereIn('entity_id', $entityIds)->get('user_id')->map(function ($item) {
316            return $item->user_id;
317        })->toArray();
318
319        $users = User::whereIn('id', $usersIds)->get()->each(function ($user) use ($entities) {
320            $user->sites = $this->getSitesByUser($user->id, $entities);
321        });
322
323
324        return $users;
325    }
326
327    protected function getSitesByUser($userId, $entities)
328    {
329        $siteIds = [];
330        foreach ($entities as $entity) {
331            $config = Arr::first($entity['config'], function ($item) {
332                return $item['id'] === 4;
333            });
334
335            if ($config && isset($config['external-users'])) {
336                $user = Arr::first($config['external-users'], function ($item) use ($userId) {
337                    return $item['id'] === $userId;
338                });
339
340                if ($user && isset($user['sites_selected'])) {
341                    $siteIds = array_merge($siteIds, $user['sites_selected']);
342                }
343            }
344        }
345
346        if (empty($siteIds)) {
347            return [];
348        }
349
350        return Site::whereIn('id', $siteIds)->get();
351    }
352}