diff --git a/app/Http/Controllers/Shop/InvoiceController.php b/app/Http/Controllers/Shop/InvoiceController.php new file mode 100644 index 000000000000..b0723ae6fb1a --- /dev/null +++ b/app/Http/Controllers/Shop/InvoiceController.php @@ -0,0 +1,83 @@ +invoice_repo = $invoice_repo; + } + + public function show(string $invitation_key) + { + $company_token = CompanyToken::with(['company'])->whereRaw("BINARY `token`= ?", [$request->header('X-API-TOKEN')])->first(); + + $invitation = InvoiceInvitation::with(['invoice']) + ->where('company_id', $company_token->company->id) + ->where('key',$invitation_key) + ->firstOrFail(); + + return $this->itemResponse($invitation->invoice); + } + + /** + * Display a listing of the resource. + * + * @return \Illuminate\Http\Response + */ + public function store(StoreInvoiceRequest $request) + { + $company_token = CompanyToken::with(['company'])->whereRaw("BINARY `token`= ?", [$request->header('X-API-TOKEN')])->first(); + + $client = Client::find($request->input('client_id')); + + $invoice = $this->invoice_repo->save($request->all(), InvoiceFactory::create($company_token->company_id, $company_token->user_id)); + + event(new InvoiceWasCreated($invoice, $invoice->company, Ninja::eventVars())); + + $invoice = $invoice->service()->triggeredActions($request)->save(); + + return $this->itemResponse($invoice); + } + +} diff --git a/app/Http/Controllers/Shop/ProductController.php b/app/Http/Controllers/Shop/ProductController.php new file mode 100644 index 000000000000..c68131d51451 --- /dev/null +++ b/app/Http/Controllers/Shop/ProductController.php @@ -0,0 +1,53 @@ +whereRaw("BINARY `token`= ?", [$request->header('X-API-TOKEN')])->first(); + + $products = Product::where('company_id', $company_token->company->id); + + return $this->listResponse($products); + } + + public function show(string $product_key) + { + $company_token = CompanyToken::with(['company'])->whereRaw("BINARY `token`= ?", [$request->header('X-API-TOKEN')])->first(); + + $product = Product::where('company_id', $company_token->company->id) + ->where('product_key', $product_key) + ->first(); + + return $this->itemResponse($product); + } +} diff --git a/app/Http/Kernel.php b/app/Http/Kernel.php index 4799bf0fc7ab..9ec5e5972e5e 100644 --- a/app/Http/Kernel.php +++ b/app/Http/Kernel.php @@ -73,6 +73,11 @@ class Kernel extends HttpKernel \App\Http\Middleware\StartupCheck::class, \App\Http\Middleware\QueryLogging::class, ], + 'shop' => [ + 'throttle:60,1', + 'bindings', + 'query_logging', + ], ]; /** @@ -108,5 +113,7 @@ class Kernel extends HttpKernel 'api_db' => \App\Http\Middleware\SetDb::class, 'locale' => \App\Http\Middleware\Locale::class, 'contact.register' => \App\Http\Middleware\ContactRegister::class, + 'shop_token_auth' => \App\Http\Middleware\ShopTokenAuth::class, + ]; } diff --git a/app/Http/Middleware/Shop/ShopTokenAuth.php b/app/Http/Middleware/Shop/ShopTokenAuth.php new file mode 100644 index 000000000000..2af0eb0df4de --- /dev/null +++ b/app/Http/Middleware/Shop/ShopTokenAuth.php @@ -0,0 +1,78 @@ +header('X-API-TOKEN') && ($company_token = CompanyToken::with(['user','company'])->whereRaw("BINARY `token`= ?", [$request->header('X-API-TOKEN')])->first())) { + + /* Check if this is a restricted token*/ + if(!$company_token->shop_restricted){ + + $error = [ + 'message' => 'Cannot use a unrestricted token on this route', + 'errors' => [] + ]; + + + return response()->json($error, 403); + + } + + $user = $company_token->user; + + $error = [ + 'message' => 'User inactive', + 'errors' => [] + ]; + + //user who once existed, but has been soft deleted + if (!$user) { + return response()->json($error, 403); + } + + /* + | + | Necessary evil here: As we are authenticating on CompanyToken, + | we need to link the company to the user manually. This allows + | us to decouple a $user and their attached companies completely. + | + */ + $user->setCompany($company_token->company); + + config(['ninja.company_id' => $company_token->company->id]); + + app('queue')->createPayloadUsing(function () use ($company_token) { + return ['db' => $company_token->company->db]; + }); + + } + + return $next($request); + } +} diff --git a/app/Http/Middleware/TokenAuth.php b/app/Http/Middleware/TokenAuth.php index b3f840fa6ece..9b4ebda3e4fd 100644 --- a/app/Http/Middleware/TokenAuth.php +++ b/app/Http/Middleware/TokenAuth.php @@ -29,6 +29,20 @@ class TokenAuth public function handle($request, Closure $next) { if ($request->header('X-API-TOKEN') && ($company_token = CompanyToken::with(['user','company'])->whereRaw("BINARY `token`= ?", [$request->header('X-API-TOKEN')])->first())) { + + if($company_token->shop_restricted){ + + $error = [ + 'message' => 'Cannot use a restricted token on this route', + 'errors' => [] + ]; + + + return response()->json($error, 403); + + } + + $user = $company_token->user; $error = [ diff --git a/app/Models/CompanyUser.php b/app/Models/CompanyUser.php index 5ce07b3efdc7..fa699b40e274 100644 --- a/app/Models/CompanyUser.php +++ b/app/Models/CompanyUser.php @@ -46,6 +46,7 @@ class CompanyUser extends Pivot 'is_owner', 'is_locked', 'slack_webhook_url', + 'shop_restricted' ]; protected $touches = []; diff --git a/app/Providers/RouteServiceProvider.php b/app/Providers/RouteServiceProvider.php index 778e1d5ff03a..feddf0b08bc2 100644 --- a/app/Providers/RouteServiceProvider.php +++ b/app/Providers/RouteServiceProvider.php @@ -57,6 +57,8 @@ class RouteServiceProvider extends ServiceProvider $this->mapContactApiRoutes(); $this->mapClientApiRoutes(); + + $this->mapShopApiRoutes(); } /** @@ -117,4 +119,12 @@ class RouteServiceProvider extends ServiceProvider ->namespace($this->namespace) ->group(base_path('routes/client.php')); } + + protected function mapShopApiRoutes() + { + Route::prefix('') + ->middleware('shop') + ->namespace($this->namespace) + ->group(base_path('routes/shop.php')); + } } diff --git a/database/migrations/2020_07_28_104218_shop_token.php b/database/migrations/2020_07_28_104218_shop_token.php new file mode 100644 index 000000000000..49dadf527b80 --- /dev/null +++ b/database/migrations/2020_07_28_104218_shop_token.php @@ -0,0 +1,30 @@ +boolean('shop_restricted')->default(false); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + // + } +} diff --git a/routes/shop.php b/routes/shop.php new file mode 100644 index 000000000000..783a503a46de --- /dev/null +++ b/routes/shop.php @@ -0,0 +1,14 @@ + ['api_db','shop_token_auth','locale']], function () { + + Route::get('products', 'Shop\ProductController@index'); + Route::get('clients', 'Shop\ClientController@index'); + Route::get('invoices', 'Shop\InvoiceController@index'); + Route::get('client/{contact_key}', 'Shop\ClientController@show'); + Route::get('invoice/{invitation_key}', 'Shop\InvoiceController@show'); + Route::get('product/{product_key}', 'Shop\ProductController@show'); + +}); \ No newline at end of file