AdminCuratedRegisterController.php 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335
  1. <?php
  2. namespace App\Http\Controllers;
  3. use App\Mail\CuratedRegisterAcceptUser;
  4. use App\Mail\CuratedRegisterRejectUser;
  5. use App\Mail\CuratedRegisterRequestDetailsFromUser;
  6. use App\Models\CuratedRegister;
  7. use App\Models\CuratedRegisterActivity;
  8. use App\Models\CuratedRegisterTemplate;
  9. use App\User;
  10. use Illuminate\Http\Request;
  11. use Illuminate\Support\Facades\Mail;
  12. use Illuminate\Support\Str;
  13. class AdminCuratedRegisterController extends Controller
  14. {
  15. public function __construct()
  16. {
  17. $this->middleware(['auth', 'admin']);
  18. }
  19. public function index(Request $request)
  20. {
  21. $this->validate($request, [
  22. 'filter' => 'sometimes|in:open,all,awaiting,approved,rejected,responses',
  23. 'sort' => 'sometimes|in:asc,desc',
  24. ]);
  25. $filter = $request->input('filter', 'open');
  26. $sort = $request->input('sort', 'asc');
  27. $records = CuratedRegister::when($filter, function ($q, $filter) {
  28. if ($filter === 'open') {
  29. return $q->where('is_rejected', false)
  30. ->where(function ($query) {
  31. return $query->where('user_has_responded', true)->orWhere('is_awaiting_more_info', false);
  32. })
  33. ->whereNotNull('email_verified_at')
  34. ->whereIsClosed(false);
  35. } elseif ($filter === 'all') {
  36. return $q;
  37. } elseif ($filter === 'responses') {
  38. return $q->whereIsClosed(false)
  39. ->whereNotNull('email_verified_at')
  40. ->where('user_has_responded', true)
  41. ->where('is_awaiting_more_info', true);
  42. } elseif ($filter === 'awaiting') {
  43. return $q->whereIsClosed(false)
  44. ->where('is_rejected', false)
  45. ->where('is_approved', false)
  46. ->where('user_has_responded', false)
  47. ->where('is_awaiting_more_info', true);
  48. } elseif ($filter === 'approved') {
  49. return $q->whereIsClosed(true)->whereIsApproved(true);
  50. } elseif ($filter === 'rejected') {
  51. return $q->whereIsClosed(true)->whereIsRejected(true);
  52. }
  53. })
  54. ->when($sort, function ($query, $sort) {
  55. return $query->orderBy('id', $sort);
  56. })
  57. ->paginate(10)
  58. ->withQueryString();
  59. return view('admin.curated-register.index', compact('records', 'filter'));
  60. }
  61. public function show(Request $request, $id)
  62. {
  63. $record = CuratedRegister::findOrFail($id);
  64. return view('admin.curated-register.show', compact('record'));
  65. }
  66. public function apiActivityLog(Request $request, $id)
  67. {
  68. $record = CuratedRegister::findOrFail($id);
  69. $res = collect([
  70. [
  71. 'id' => 1,
  72. 'action' => 'created',
  73. 'title' => 'Onboarding application created',
  74. 'message' => null,
  75. 'link' => null,
  76. 'timestamp' => $record->created_at,
  77. ],
  78. ]);
  79. if ($record->email_verified_at) {
  80. $res->push([
  81. 'id' => 3,
  82. 'action' => 'email_verified_at',
  83. 'title' => 'Applicant successfully verified email address',
  84. 'message' => null,
  85. 'link' => null,
  86. 'timestamp' => $record->email_verified_at,
  87. ]);
  88. }
  89. $activities = CuratedRegisterActivity::whereRegisterId($record->id)->get();
  90. $idx = 4;
  91. $userResponses = collect([]);
  92. foreach ($activities as $activity) {
  93. $idx++;
  94. if ($activity->type === 'user_resend_email_confirmation') {
  95. continue;
  96. }
  97. if ($activity->from_user) {
  98. $userResponses->push($activity);
  99. continue;
  100. }
  101. $res->push([
  102. 'id' => $idx,
  103. 'aid' => $activity->id,
  104. 'action' => $activity->type,
  105. 'title' => $activity->from_admin ? 'Admin requested info' : 'User responded',
  106. 'message' => $activity->message,
  107. 'link' => $activity->adminReviewUrl(),
  108. 'timestamp' => $activity->created_at,
  109. ]);
  110. }
  111. foreach ($userResponses as $ur) {
  112. $res = $res->map(function ($r) use ($ur) {
  113. if (! isset($r['aid'])) {
  114. return $r;
  115. }
  116. if ($ur->reply_to_id === $r['aid']) {
  117. $r['user_response'] = $ur;
  118. return $r;
  119. }
  120. return $r;
  121. });
  122. }
  123. if ($record->is_approved) {
  124. $idx++;
  125. $res->push([
  126. 'id' => $idx,
  127. 'action' => 'approved',
  128. 'title' => 'Application Approved',
  129. 'message' => null,
  130. 'link' => null,
  131. 'timestamp' => $record->action_taken_at,
  132. ]);
  133. } elseif ($record->is_rejected) {
  134. $idx++;
  135. $res->push([
  136. 'id' => $idx,
  137. 'action' => 'rejected',
  138. 'title' => 'Application Rejected',
  139. 'message' => null,
  140. 'link' => null,
  141. 'timestamp' => $record->action_taken_at,
  142. ]);
  143. }
  144. return $res->reverse()->values();
  145. }
  146. public function apiMessagePreviewStore(Request $request, $id)
  147. {
  148. $record = CuratedRegister::findOrFail($id);
  149. return $request->all();
  150. }
  151. public function apiMessageSendStore(Request $request, $id)
  152. {
  153. $this->validate($request, [
  154. 'message' => 'required|string|min:5|max:1000',
  155. ]);
  156. $record = CuratedRegister::findOrFail($id);
  157. abort_if($record->email_verified_at === null, 400, 'Cannot message an unverified email');
  158. $activity = new CuratedRegisterActivity;
  159. $activity->register_id = $record->id;
  160. $activity->admin_id = $request->user()->id;
  161. $activity->secret_code = Str::random(32);
  162. $activity->type = 'request_details';
  163. $activity->from_admin = true;
  164. $activity->message = $request->input('message');
  165. $activity->save();
  166. $record->is_awaiting_more_info = true;
  167. $record->user_has_responded = false;
  168. $record->save();
  169. Mail::to($record->email)->send(new CuratedRegisterRequestDetailsFromUser($record, $activity));
  170. return $request->all();
  171. }
  172. public function previewDetailsMessageShow(Request $request, $id)
  173. {
  174. $record = CuratedRegister::findOrFail($id);
  175. abort_if($record->email_verified_at === null, 400, 'Cannot message an unverified email');
  176. $activity = new CuratedRegisterActivity;
  177. $activity->message = $request->input('message');
  178. return new \App\Mail\CuratedRegisterRequestDetailsFromUser($record, $activity);
  179. }
  180. public function previewMessageShow(Request $request, $id)
  181. {
  182. $record = CuratedRegister::findOrFail($id);
  183. abort_if($record->email_verified_at === null, 400, 'Cannot message an unverified email');
  184. $record->message = $request->input('message');
  185. return new \App\Mail\CuratedRegisterSendMessage($record);
  186. }
  187. public function apiHandleReject(Request $request, $id)
  188. {
  189. $this->validate($request, [
  190. 'action' => 'required|in:reject-email,reject-silent',
  191. ]);
  192. $action = $request->input('action');
  193. $record = CuratedRegister::findOrFail($id);
  194. abort_if($record->email_verified_at === null, 400, 'Cannot reject an unverified email');
  195. $record->is_rejected = true;
  196. $record->is_closed = true;
  197. $record->action_taken_at = now();
  198. $record->save();
  199. if ($action === 'reject-email') {
  200. Mail::to($record->email)->send(new CuratedRegisterRejectUser($record));
  201. }
  202. return [200];
  203. }
  204. public function apiHandleApprove(Request $request, $id)
  205. {
  206. $record = CuratedRegister::findOrFail($id);
  207. abort_if($record->email_verified_at === null, 400, 'Cannot reject an unverified email');
  208. $record->is_approved = true;
  209. $record->is_closed = true;
  210. $record->action_taken_at = now();
  211. $record->save();
  212. $user = User::create([
  213. 'name' => $record->username,
  214. 'username' => $record->username,
  215. 'email' => $record->email,
  216. 'password' => $record->password,
  217. 'app_register_ip' => $record->ip_address,
  218. 'email_verified_at' => now(),
  219. 'register_source' => 'cur_onboarding',
  220. ]);
  221. Mail::to($record->email)->send(new CuratedRegisterAcceptUser($record));
  222. return [200];
  223. }
  224. public function templates(Request $request)
  225. {
  226. $templates = CuratedRegisterTemplate::paginate(10);
  227. return view('admin.curated-register.templates', compact('templates'));
  228. }
  229. public function templateCreate(Request $request)
  230. {
  231. return view('admin.curated-register.template-create');
  232. }
  233. public function templateEdit(Request $request, $id)
  234. {
  235. $template = CuratedRegisterTemplate::findOrFail($id);
  236. return view('admin.curated-register.template-edit', compact('template'));
  237. }
  238. public function templateEditStore(Request $request, $id)
  239. {
  240. $this->validate($request, [
  241. 'name' => 'required|string|max:30',
  242. 'content' => 'required|string|min:5|max:3000',
  243. 'description' => 'nullable|sometimes|string|max:1000',
  244. 'active' => 'sometimes',
  245. ]);
  246. $template = CuratedRegisterTemplate::findOrFail($id);
  247. $template->name = $request->input('name');
  248. $template->content = $request->input('content');
  249. $template->description = $request->input('description');
  250. $template->is_active = $request->boolean('active');
  251. $template->save();
  252. return redirect()->back()->with('status', 'Successfully updated template!');
  253. }
  254. public function templateDelete(Request $request, $id)
  255. {
  256. $template = CuratedRegisterTemplate::findOrFail($id);
  257. $template->delete();
  258. return redirect(route('admin.curated-onboarding.templates'))->with('status', 'Successfully deleted template!');
  259. }
  260. public function templateStore(Request $request)
  261. {
  262. $this->validate($request, [
  263. 'name' => 'required|string|max:30',
  264. 'content' => 'required|string|min:5|max:3000',
  265. 'description' => 'nullable|sometimes|string|max:1000',
  266. 'active' => 'sometimes',
  267. ]);
  268. CuratedRegisterTemplate::create([
  269. 'name' => $request->input('name'),
  270. 'content' => $request->input('content'),
  271. 'description' => $request->input('description'),
  272. 'is_active' => $request->boolean('active'),
  273. ]);
  274. return redirect(route('admin.curated-onboarding.templates'))->with('status', 'Successfully created new template!');
  275. }
  276. public function getActiveTemplates(Request $request)
  277. {
  278. $templates = CuratedRegisterTemplate::whereIsActive(true)
  279. ->orderBy('order')
  280. ->get()
  281. ->map(function ($tmp) {
  282. return [
  283. 'name' => $tmp->name,
  284. 'content' => $tmp->content,
  285. ];
  286. });
  287. return response()->json($templates);
  288. }
  289. }