Created
March 26, 2019 15:53
-
-
Save hovsep/b6b448e6338a6299c1f84f98afaf5fcf to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?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