Codigo para validacao de requisicoes REST multi-store

De Tek-System Wiki
Ir para navegação Ir para pesquisar

O código a seguir é o mais atualizado até o momento. Note que a validação 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.

Código:

    
     /**
     * 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;
        }
    
    }