json(TwoFAccount::ofGroup(Options::get('activeGroup'))->ordered()->get()->toArray()); } /** * Store a newly created resource in storage. * * @param \Illuminate\Http\Request $request * @return \Illuminate\Http\Response */ public function store(Request $request) { // see https://github.com/google/google-authenticator/wiki/Key-Uri-Format // for otpauth uri format validation $this->validate($request, [ 'service' => 'required', 'uri' => 'required|regex:/^otpauth:\/\/[h,t]otp\//i', ]); OTP::get($request->uri); $twofaccount = TwoFAccount::create([ 'service' => $request->service, 'account' => $request->account, 'uri' => $request->uri, 'icon' => $request->icon ]); // Possible group association $groupId = Options::get('defaultGroup') === '-1' ? (int) Options::get('activeGroup') : (int) Options::get('defaultGroup'); // 0 is the pseudo group 'All', only groups with id > 0 are true user groups if( $groupId > 0 ) { $group = Group::find($groupId); if($group) { $group->twofaccounts()->save($twofaccount); } } return response()->json($twofaccount, 201); } /** * Display the specified resource. * * @param \App\TwoFAccount $twofaccount * @return \Illuminate\Http\Response */ public function show(TwoFAccount $twofaccount) { return response()->json($twofaccount, 200); } /** * Save new order. * * @param \App\TwoFAccount $twofaccount * @return \Illuminate\Http\Response */ public function reorder(Request $request) { TwoFAccount::setNewOrder($request->orderedIds); return response()->json('order saved', 200); } /** * Generate a TOTP * * @param \Illuminate\Http\Request $request * @return \Illuminate\Http\Response */ public function generateOTP(Request $request) { $isPreview = false; if( is_int($request->data) ) { $twofaccount = TwoFAccount::FindOrFail($request->data); $uri = $twofaccount->uri; } else { $uri = $request->data; $isPreview = true; } return response()->json(OTP::generate($uri, $isPreview), 200); } /** * Update the specified resource in storage. * * @param \Illuminate\Http\Request $request * @param \App\TwoFAccount $twofaccount * @return \Illuminate\Http\Response */ public function update(Request $request, $id) { $this->validate($request, [ 'service' => 'required', ]); // Here we catch a possible missing model exception in order to // delete orphan submited icon try { $twofaccount = TwoFAccount::FindOrFail($id); } catch (\Illuminate\Database\Eloquent\ModelNotFoundException $e) { if( $request->icon ) { Storage::delete('public/icons/' . $request->icon); } throw $e; } if( $twofaccount->type === 'hotp' ) { // HOTP can be desynchronized from the verification // server so we let the user the possibility to force // the counter. $this->validate($request, [ 'counter' => 'required|integer', ]); // we set an OTP object to get the its current counter // and we update it if a new one has been submited $otp = OTP::get($twofaccount->uri); if( $otp->getCounter() !== $request->counter ) { $otp->setParameter( 'counter', $request->counter ); $twofaccount->uri = $otp->getProvisioningUri(); } } $twofaccount->update([ 'service' => $request->service, 'account' => $request->account, 'icon' => $request->icon, 'uri' => $twofaccount->uri, ]); return response()->json($twofaccount, 200); } /** * Remove the specified resource from storage. * * @param \App\TwoFAccount $twofaccount * @return \Illuminate\Http\Response */ public function destroy(TwoFAccount $twofaccount) { $twofaccount->delete(); return response()->json(null, 204); } /** * Remove the specified resources from storage. * * @param \Illuminate\Http\Request $request * @return \Illuminate\Http\Response */ public function batchDestroy(Request $request) { $ids = $request->all(); TwoFAccount::destroy($ids); return response()->json(null, 204); } }