Codigo para validacao de requisicoes REST multi-store
Revisão de 19h12min de 21 de fevereiro de 2018 por Rafael Padovani (discussão | contribs)
O codigo a seguir é o mais atualizado até o momento. Note que a validacao possuiAcessoANovosPedidos() é falha e vai precisar ser refeita. O ideal é encontrar um padrão para as seguintes requisições:
Path_Categorias = 'categories'; Path_CategoriasMove = 'categories/%d/move'; Path_Produtos = 'products'; Path_Atributos = 'products/attributes'; Pesquisa_Atributos = '?searchCriteria[filterGroups][0][filters][0][field]=is_filterable_in_search&searchCriteria[filterGroups][0][filters][0][value]=1&searchCriteria[filterGroups][0][filters][0][conditionType]=eq&' + 'searchCriteria[filterGroups][1][filters][1][field]=attribute_code&searchCriteria[filterGroups][1][filters][1][value]=cor,variacao,acabamento,tamanho,grade,tecido&searchCriteria[filterGroups][1][filters][1][conditionType]=nin'; Path_OpcoesAtributos = 'products/attributes/%s/options'; Path_AtributoConfiguracao = 'products/attribute-sets/sets/list?searchCriteria'; Path_ProdutoConfiguravel = 'configurable-products/%s/child'; Path_EstoqueProduto = 'products/%s/stockItems/1'; Path_ProdutosMedia = 'products/%s/media'; Path_DeletaProdutosMedia = 'products/%s/media/%s'; Path_AprovacaoPgtoPedido = 'order/%s/invoice'; Path_PedidosNovos = 'orders?&searchCriteria[filterGroups][1][filters][1][field]=status&searchCriteria[filterGroups][1][filters][1][value]='+Integracao_CodStatusMagentoDocPagtoAprovado+'&searchCriteria[filterGroups][1][filters][1][conditionType]=eq&' + 'searchCriteria[filterGroups][2][filters][2][field]=store_id&searchCriteria[filterGroups][2][filters][2][value]=%s&searchCriteria[filterGroups][2][filters][2][conditionType]=in'; Path_DadosPostagemPedido = 'order/%s/ship'; Path_Comentarios = 'orders/%s/comments'; 'orders?&searchCriteria[filterGroups][1][filters][1][conditionType]=eq&' + 'searchCriteria[filterGroups][2][filters][2][field]=store_id&searchCriteria[filterGroups][2][filters][2][value]=%s&searchCriteria[filterGroups][2][filters][2][conditionType]=in';
O grande desafio é criar um padrão para as requisições acima. Note também que eh muito provável que novas requisições sejam necessários para liberação no futuro.
O código deve ser robusto e extremamente otimizado, já que toda requisição de url vai passar pela validação.
Codigo:
/** * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ namespace Magento\Webapi\Controller\Rest; use Magento\Framework\Webapi\Rest\Request as RestRequest; use Magento\Webapi\Controller\Rest\Router; use Magento\Store\Model\StoreManagerInterface; use Magento\Store\Model\Store; use Magento\Framework\Webapi\Authorization; use Magento\Framework\Exception\AuthorizationException; use PhpParser\Node\Expr\Array_; /** * This class is responsible for validating the request */ class RequestValidator { /** * @var RestRequest */ private $request; /** * @var Router */ private $router; /** * @var StoreManagerInterface */ private $storeManager; /** * @var Authorization */ private $authorization; /** * Initialize dependencies * * @param RestRequest $request * @param Router $router * @param StoreManagerInterface $storeManager * @param Authorization $authorization */ public function __construct( RestRequest $request, Router $router, StoreManagerInterface $storeManager, Authorization $authorization ) { $this->request = $request; $this->router = $router; $this->storeManager = $storeManager; $this->authorization = $authorization; } /** * Validate request * * @throws AuthorizationException * @throws \Magento\Framework\Webapi\Exception * @return void */ public function validate() { $this->checkPermissions(); $route = $this->router->match($this->request); if ($route->isSecure() && !$this->request->isSecure()) { throw new \Magento\Framework\Webapi\Exception(__('Operation allowed only in HTTPS')); } } /** * Perform authentication and authorization. * * @throws \Magento\Framework\Exception\AuthorizationException * @return void */ private function checkPermissions() { $route = $this->router->match($this->request); if (!$this->authorization->isAllowed($route->getAclResources())) { // SE NAO ESTA AUTORIZADO $params = ['resources' => implode(', ', $route->getAclResources())]; throw new AuthorizationException( __(AuthorizationException::NOT_AUTHORIZED, $params) ); }else { // SE ESTA AUTORIZADO $naoAutorizado = ["Não autorizado" => "Voce nao possui autorizacao"]; $requisicaoCompleta = $this->request->getUriString(); $strRequisicaoCompleta = (string)$requisicaoCompleta; $userName = $this->request->get("username"); if($this->possuiAcessoParaGerarToken($requisicaoCompleta)){ $lojaDeAcessoPermitido = $this->verificaLojaDeAcessoDoCliente($userName); $this->gravaUserNameNaSessao($userName,$lojaDeAcessoPermitido ); return; } if($this->possuiAcessoANovosPedidos($requisicaoCompleta,3)){return; } throw new AuthorizationException( __(AuthorizationException::NOT_AUTHORIZED, $naoAutorizado) ); } } private function possuiAcessoParaGerarToken($url){ return ( ( strpos($url, '/rest/V1/integration/admin/token') !== false ) ); } private function possuiAcessoANovosPedidos($url,$lojaQueEstaTentandoAcessar){ //NOTA: Essa url tem que ser completamente reestruturada. return ( ( strpos($url, 'orders') !== false ) && ( strpos($url, 'store_id') !== false ) && ($_SESSION["lojaAcessoPermitido"] == $lojaQueEstaTentandoAcessar) ); } private function verificaLojaDeAcessoDoCliente($userName){ // CRIAMOS UM NOVO CAMPO NA TABELA ADMIN_USER, ESTE SE CHAMA STORE_ID_SOLUCAO PARA INFORMAR QUAL LOJA ESTE USUARIO TEM ACESSO. $objectManager = \Magento\Framework\App\ObjectManager::getInstance(); $resource = $objectManager->get('Magento\Framework\App\ResourceConnection'); $connection = $resource->getConnection(); $tableName = $resource->getTableName('admin_user'); $sql = $connection->select() ->from($tableName) ->where('admin_user.username = ?', $userName); $result = $connection->fetchRow($sql); $arr = $result["store_id_solucao"]; //retorna a loja que o usuario tem acesso return $arr; } private function gravaUserNameNaSessao($userName, $lojaComAcessoPermitido){ //grava username na sessao, pois so temos acesso a ela na geracao do token //talvez seja interessante encriptar estes dois dados futuramente $_SESSION["usuario"]= $userName; $_SESSION["lojaAcessoPermitido"] = $lojaComAcessoPermitido; } }