Skip to content

Instantly share code, notes, and snippets.

@hovsep
Created March 26, 2019 15:53
Show Gist options
  • Save hovsep/b6b448e6338a6299c1f84f98afaf5fcf to your computer and use it in GitHub Desktop.
Save hovsep/b6b448e6338a6299c1f84f98afaf5fcf to your computer and use it in GitHub Desktop.
<?php
namespace App\Http\Controllers\Api;
use App\Entities\AddressVerificationStatus;
use App\Models\AuStreet;
use App\Models\UserForward;
use App\Models\UserLocation;
use App\Models\UserSubscriptionHistoryItem;
use App\User;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Log;
use PHPZen\LaravelRbac\Model\Role;
class UserController extends \App\Http\Controllers\Controller
{
public function store(Request $request)
{
//Common user fields
$rules = [
'account_id' => 'required|int',
'name' => 'required|unique:users|max:255',
'email' => 'required|email|max:255|unique:users',
'password' => 'required|min:6',
'roles' => 'required|array',
'roles.*' => 'string|exists:roles,slug',
'mta_id' => 'required|string',
'score' => 'required|int|min:0'
];
$storingIndividual = in_array(\App\Entities\RBAC\Role::INDIVIDUAL, array_wrap(data_get($request, 'roles')));
//Additional rules for individual users
if ($storingIndividual) {
$rules += [
'address_verification_status' => 'sometimes|string|in:' . AddressVerificationStatus::all()->implode(','),
'phone' => 'nullable|string',
'address' => 'required|string',
'postcode' => 'required|string',
'street_locality_pid' => 'required|string|exists:au_streets,street_locality_pid',
'ip' => 'sometimes|nullable|ip',
'lat' => 'required|numeric',//User's current location coordinates (html5 geo)
'lng' => 'required|numeric',
'home_lat' => 'required|numeric',//User's selected street coordinates
'home_lng' => 'required|numeric',
'super_user_email' => 'nullable|sometimes|email'
];
}
$this->validate($request, $rules);
try {
$user = null;
DB::transaction(function () use ($request, &$user, $storingIndividual) {
$user = new User([
'account_id' => $request->account_id,
'name' => $request->name,
'email' => $request->email,
'password' => Hash::make($request->password),
'triton_id' => array_first(array_keys(config('services.tritons'))),
'mta_id' => $request->mta_id,
'score' => $request->score,
'subscribing_status' => 1
]);
//Augment data
if ($storingIndividual) {
$user->fill([
'phone' => $request->get('phone'),
'address' => $request->get('address'),
'postcode' => $request->get('postcode'),
'home_lat' => $request->get('home_lat'),
'home_lng' => $request->get('home_lng'),
'address_verification_status' => $request->get('address_verification_status', AddressVerificationStatus::UNVERIFIED)
]);
if ($request->filled('super_user_email')) {
$super_user = User::where('email', $request->super_user_email)->first();
if (!$super_user) {
$super_user = User::whereHas('roles', function ($q) {
$q->whereIn('slug', [\App\Entities\RBAC\Role::ADMIN]);
})->whereNull('super_user_id')->first();
}
$user->superUser()->associate($super_user);
}
if ($request->filled('street_locality_pid')) {
$street = AuStreet::with('suburb')->where('street_locality_pid', $request->street_locality_pid)->firstOrFail();
$user->registeredStreet()->associate($street);
$user->registeredSuburb()->associate($street->suburb);
}
}
$user->save();
$user->roles()->sync(Role::whereIn('slug', array_wrap($request->roles))->get());
if ($request->filled(['lat', 'lng'])) {
UserLocation::create([
'user_id' => $user->id,
'ip' => $request->get('ip'),
'lat' => $request->lat,
'lng' => $request->lng
]);
}
});
return response()->json(['msg' => 'ok', 'user' => $user]);
} catch (\Exception $e) {
Log::error('Failed to store user', ['reason' => $e->getMessage()]);
return response()->json(['error' => 'Failed to store user'], 500);
}
}
public function updateSubscription(Request $request)
{
$this->validate($request, [
'email' => 'required|exists:users,email',
'subscribed_street' => 'nullable|sometimes|required_without_all:subscribed_suburb|string|exists:au_streets,street_locality_pid',
'subscribed_suburb' => 'nullable|sometimes|required_without_all:subscribed_street|string|exists:au_suburbs,locality_pid',
'lat' => 'nullable|sometimes|numeric',
'lng' => 'nullable|sometimes|numeric'
]);
try {
if ($request->has(['subscribed_street', 'subscribed_suburb'])) {
throw new \Exception('Do not send both (street & suburb) subscriptions at the same time', 422);
}
$user = User::where('email', $request->email)->firstOrFail();
$unsubscribedStreet = null;
$unsubscribedSuburb = null;
if (0 !== strcmp($request->subscribed_street, $user->subscribed_street)) {
$unsubscribedStreet = $user->subscribed_street;
}
if (0 !== strcmp($request->subscribed_suburb, $user->subscribed_suburb)) {
$unsubscribedSuburb = $user->subscribed_suburb;
}
$newSubscriptionStreet = null;
$newSubscriptionSuburb = null;
$newSubscriptionStreet = $request->get('subscribed_street', null);
if ($request->has('subscribed_suburb')) {
$newSubscriptionSuburb = $request->subscribed_suburb;
} else {
$newSubscriptionSuburb = null;
}
if ($newSubscriptionStreet == $user->street) {
//Do not allow to subscribe 'home' street
$newSubscriptionStreet = null;
}
if ($newSubscriptionSuburb == $user->suburb) {
//Do not allow to subscribe 'home' suburb
$newSubscriptionSuburb = null;
}
$user->subscribed_street = $newSubscriptionStreet;
$user->subscribed_suburb = $newSubscriptionSuburb;
DB::transaction(function() use ($request, $user, $unsubscribedStreet, $unsubscribedSuburb, $newSubscriptionStreet, $newSubscriptionSuburb) {
$user->save();
$userSubscriptionHistoryItem = new UserSubscriptionHistoryItem(
[
'user_id' => $user->id,
'subscribed_street' => $newSubscriptionStreet,
'subscribed_suburb' => $newSubscriptionSuburb,
'unsubscribed_street' => $unsubscribedStreet,
'unsubscribed_suburb' => $unsubscribedSuburb,
'lat' => $request->lat,
'lng' => $request->lng
]
);
$userSubscriptionHistoryItem->save();
});
return response()->json(['msg' => 'ok', 'user' => $user]);
} catch (\Exception $e) {
Log::error('Failed to update user subscription', ['reason' => $e->getMessage()]);
return response()->json(['error' => 'Failed to update user subscription'], 500);
}
}
public function updateForwards(Request $request)
{
$this->validate($request, [
'email' => 'required|exists:users,email',
'forwards' => 'required|array',
'forwards.*' => 'email',
'activity' => 'required|array',
'activity.*' => 'required|boolean'
]);
try {
if (count($request->forwards) != count($request->activity)) {
throw new \Exception('forwards[] and activity[] must be same size', 422);
}
$user = User::where('email', $request->email)->firstOrFail();
DB::transaction(function() use ($request, $user) {
$user->forwards()->delete();
for ($i = 0; $i < count($request->forwards); $i++) {
if ($user->email == $request->forwards[$i]) {
throw new \Exception('Infinite forward', 422);
}
UserForward::firstOrCreate([
'user_id' => $user->id,
'from' => $user->email,
'to' => $request->forwards[$i],
'is_active' => $request->activity[$i]
]);
}
});
return response()->json(['msg' => 'ok', 'user' => $user->load('forwards')]);
} catch (\Exception $e) {
Log::error('Failed to update user forwards', ['reason' => $e->getMessage()]);
return response()->json(['error' => 'Failed to update user forwards'], 500);
}
}
/**
* Returns all users of single account
*
* @param Request $request
* @return \Illuminate\Http\JsonResponse
*/
public function show(Request $request)
{
$this->validate($request, [
'email' => 'required|exists:users,email'
]);
$maxUsersPerAccount = 5;
$users = User::with([
'subUsers.roles',
'roles',
'registeredSuburb',
'registeredStreet',
'subscribedStreet.suburb',
'subscribedSuburb',
'forwards',
'subscriptionHistory' => function ($q) {
$q->latest()->take(1);
}
])->where('users.email', $request->email)
->where('users.account_id', '>', 0)
->leftJoin('users AS _u', 'users.account_id', '=', '_u.account_id')
->limit($maxUsersPerAccount)
->get();
return response()->json($users);
}
public function getTritonLink(Request $request)
{
$this->validate($request, [
'email' => 'required|exists:users,email'
]);
try {
$user = User::where('email', $request->email)->firstOrFail();
throw_if(empty($user->triton_id), new \Exception('User triton_id is empty'));
throw_if(!config()->has('services.tritons.' . $user->triton_id), new \Exception('Unknown triton id'));
$user->refreshAutologinToken();
return response()->json(['msg' => 'ok', 'link' => $user->autologin_triton_url]);
} catch (\Exception $e) {
Log::error('Failed to create triton autologin link', ['reason' => $e->getMessage()]);
return response()->json(['error' => 'Failed to create triton autologin link'], 400);
}
}
public function update(Request $request)
{
$this->validate($request, [
'email' => 'required|exists:users,email',
'last_panic' => 'sometimes|date',
'score' => 'sometimes|integer|min:0',
'address_verification_status' => 'sometimes|string|in:' . AddressVerificationStatus::all()->implode(','),
'password' => 'sometimes|min:6',
'subscribing_status' => 'sometimes|boolean'
]);
try {
$user = User::where('email', $request->email)->firstOrFail();
foreach($request->except(['email', 'password']) as $inputName => $inputValue) {
if ($request->filled($inputName)) {
$user->fill([$inputName => $inputValue]);
}
}
if ($request->filled('password')) {
$user->password = Hash::make($request->password);
}
$user->save();
return response()->json($user);
} catch (\Exception $e) {
Log::error('Failed to update user', ['reason' => $e->getMessage()]);
return response()->json(['error' => 'Failed to update user'], 500);
}
}
public function destroy(Request $request)
{
$this->validate($request, [
'email' => 'required|exists:users,email'
]);
try {
$user = User::where('email', $request->email)->firstOrFail();
if (!$user->delete()) {
throw new \Exception('DB error');
}
return response()->json(['msg' => 'ok']);
} catch (\Exception $e) {
Log::error('Failed to delete user', ['reason' => $e->getMessage()]);
return response()->json(['error' => 'Failed to delete user'], 500);
}
}
public function getAuthorized(Request $request)
{
$this->validate($request, [
'triton_id' => 'required|string|in:' . $request->user()->triton_id,//
]);
return $request->user()->load('roles.permissions');
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment