Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Exception in json post! #427

Open
rafinhaa opened this issue Aug 30, 2021 · 8 comments
Open

Exception in json post! #427

rafinhaa opened this issue Aug 30, 2021 · 8 comments

Comments

@rafinhaa
Copy link
Contributor

rafinhaa commented Aug 30, 2021

Hi, i implemented myth auth in a test api and when i try to create a new user via "application/json" i get an exception

{
  "title": "ErrorException",
  "type": "ErrorException",
  "code": 500,
  "message": "Undefined offset: 1",
  "file": "/var/www/html/vendor/myth/auth/src/Authentication/Passwords/NothingPersonalValidator.php",
  "line": 90,
  "trace": [
    {
      "file": "/var/www/html/vendor/myth/auth/src/Authentication/Passwords/NothingPersonalValidator.php",
      "line": 90,
      "function": "errorHandler",
      "class": "CodeIgniter\\Debug\\Exceptions",
      "type": "->",
      "args": [
        8,
        "Undefined offset: 1",
        "/var/www/html/vendor/myth/auth/src/Authentication/Passwords/NothingPersonalValidator.php",
        90,
        {
          "password": "gilmar@ar.com",
          "user": [],
          "userName": "",
          "email": "",
          "valid": true,
          "needles": [
            ""
          ],
          "localPart": ""
        }
      ]
    },
    {
      "file": "/var/www/html/vendor/myth/auth/src/Authentication/Passwords/NothingPersonalValidator.php",
      "line": 39,
      "function": "isNotPersonal",
      "class": "Myth\\Auth\\Authentication\\Passwords\\NothingPersonalValidator",
      "type": "->",
      "args": [
        "gilmar@ar.com",
        []
      ]
    },
    {
      "file": "/var/www/html/vendor/myth/auth/src/Authentication/Passwords/PasswordValidator.php",
      "line": 55,
      "function": "check",
      "class": "Myth\\Auth\\Authentication\\Passwords\\NothingPersonalValidator",
      "type": "->",
      "args": [
        "gilmar@ar.com",
        []
      ]
    },
    {
      "file": "/var/www/html/vendor/myth/auth/src/Authentication/Passwords/ValidationRules.php",
      "line": 45,
      "function": "check",
      "class": "Myth\\Auth\\Authentication\\Passwords\\PasswordValidator",
      "type": "->",
      "args": [
        "gilmar@ar.com",
        []
      ]
    },
    {
      "file": "/var/www/html/vendor/codeigniter4/framework/system/Validation/Validation.php",
      "line": 312,
      "function": "strong_password",
      "class": "Myth\\Auth\\Authentication\\Passwords\\ValidationRules",
      "type": "->",
      "args": [
        "gilmar@ar.com",
        null
      ]
    },
    {
      "file": "/var/www/html/vendor/codeigniter4/framework/system/Validation/Validation.php",
      "line": 159,
      "function": "processRules",
      "class": "CodeIgniter\\Validation\\Validation",
      "type": "->",
      "args": [
        "password",
        "password",
        "gilmar@ar.com",
        [
          "required",
          "strong_password"
        ],
        {
          "name": "rafael",
          "lastname": "sonicne",
          "email": "gilmar@ar.com",
          "password": "gilmar@ar.com",
          "cpassword": "gilmar@ar.com",
          "DBGroup": null
        }
      ]
    },
    {
      "file": "/var/www/html/vendor/codeigniter4/framework/system/Controller.php",
      "line": 183,
      "function": "run",
      "class": "CodeIgniter\\Validation\\Validation",
      "type": "->",
      "args": []
    },
    {
      "file": "/var/www/html/app/Controllers/Api/V1/Users.php",
      "line": 99,
      "function": "validate",
      "class": "CodeIgniter\\Controller",
      "type": "->",
      "args": [
        {
          "email": {
            "rules": "required|valid_email|is_unique[users.email]",
            "errors": {
              "required": "O e-mail é necessário",
              "valid_email": "Você deve inserir um email válido",
              "is_unique": "Esse e-mail já está cadastrado"
            }
          },
          "name": {
            "rules": "required|min_length[2]",
            "errors": {
              "required": "Seu nome é necessário",
              "min_length": "Seu nome deve ter pelo menos 2 caracteres"
            }
          },
          "lastname": {
            "rules": "required|min_length[2]",
            "errors": {
              "required": "Seu sobrenome é necessário",
              "min_length": "Seu sobrenome deve ter pelo menos 2 caracteres"
            }
          },
          "password": {
            "rules": "required|strong_password",
            "errors": {
              "required": "A senha é necessário",
              "strong_password": "Essa senha está facil demais"
            }
          },
          "cpassword": {
            "rules": "required|matches[password]",
            "errors": {
              "required": "Você não digitou a confirmação da senha",
              "matches": "As senhas não são iguais"
            }
          }
        }
      ]
    },
    {
      "file": "/var/www/html/vendor/codeigniter4/framework/system/CodeIgniter.php",
      "line": 928,
      "function": "create",
      "class": "App\\Controllers\\Api\\V1\\Users",
      "type": "->",
      "args": []
    },
    {
      "file": "/var/www/html/vendor/codeigniter4/framework/system/CodeIgniter.php",
      "line": 436,
      "function": "runController",
      "class": "CodeIgniter\\CodeIgniter",
      "type": "->",
      "args": [
        {}
      ]
    },
    {
      "file": "/var/www/html/vendor/codeigniter4/framework/system/CodeIgniter.php",
      "line": 336,
      "function": "handleRequest",
      "class": "CodeIgniter\\CodeIgniter",
      "type": "->",
      "args": [
        null,
        {
          "handler": "file",
          "backupHandler": "dummy",
          "storePath": "/var/www/html/writable/cache/",
          "cacheQueryString": false,
          "prefix": "",
          "ttl": 60,
          "file": {
            "storePath": "/var/www/html/writable/cache/",
            "mode": 416
          },
          "memcached": {
            "host": "127.0.0.1",
            "port": 11211,
            "weight": 1,
            "raw": false
          },
          "redis": {
            "host": "127.0.0.1",
            "password": null,
            "port": 6379,
            "timeout": 0,
            "database": 0
          },
          "validHandlers": {
            "dummy": "CodeIgniter\\Cache\\Handlers\\DummyHandler",
            "file": "CodeIgniter\\Cache\\Handlers\\FileHandler",
            "memcached": "CodeIgniter\\Cache\\Handlers\\MemcachedHandler",
            "predis": "CodeIgniter\\Cache\\Handlers\\PredisHandler",
            "redis": "CodeIgniter\\Cache\\Handlers\\RedisHandler",
            "wincache": "CodeIgniter\\Cache\\Handlers\\WincacheHandler"
          }
        },
        false
      ]
    },
    {
      "file": "/var/www/html/public/index.php",
      "line": 37,
      "function": "run",
      "class": "CodeIgniter\\CodeIgniter",
      "type": "->",
      "args": []
    }
  ]
}

When I send the request through "multipart/form-data" I get the registration successfully!

I investigated the myth files to find a solution to this problem, but I couldn't.

Below are the classes I used as a test:

<?php

namespace App\Controllers\Api\V1;

use CodeIgniter\RESTful\ResourceController;

class Users extends ResourceController
{
    protected $modelName = 'App\Models\UserModel';
    protected $format    = 'json';

	public function create(){
		$rules = [
			'email' => [
				'rules' => 'required|valid_email|is_unique[users.email]',				
				'errors' => [
					'required' => 'O e-mail é necessário',
					'valid_email' => 'Você deve inserir um email válido',
					'is_unique' => 'Esse e-mail já está cadastrado',
				],
			],
			'name' => [
				'rules' => 'required|min_length[2]',
				'errors' => [
					'required' => 'Seu nome é necessário',
					'min_length' => 'Seu nome deve ter pelo menos 2 caracteres',
				],
			],
			'lastname' => [
				'rules' => 'required|min_length[2]',
				'errors' => [
					'required' => 'Seu sobrenome é necessário',
					'min_length' => 'Seu sobrenome deve ter pelo menos 2 caracteres',
				],
			],
			'password' => [
				'rules' => 'required|strong_password',
				'errors' => [
					'required' => 'A senha é necessário',
					'strong_password' => 'Essa senha está facil demais',
				],                
			],			
			'cpassword' => [
				'rules' => 'required|matches[password]',
				'errors' => [
					'required' => 'Você não digitou a confirmação da senha',
					'matches' => 'As senhas não são iguais',
				],                
			],
		];

		if (! $this->validate($rules)){
			return $this->respond([
				'status' => 500,
				'error' => true,
				'message' => $this->validator->getErrors(),
				'data' => []
			],500);
		}
        die('registration ok');
	}


}

Routes:
$routes->resource('api/v1/users');

Prints:
fail
ok

Codeigniter 4.1.3
PHP 7.3

@rafinhaa
Copy link
Contributor Author

rafinhaa commented Aug 31, 2021

I found the cause of the problem, I had to modify the buildUserFromRequest method in the /src/Authentication/Passwords/ValidationRules.php file

protected function buildUserFromRequest()
{
    $fields = $this->prepareValidFields();

    if (strpos(service('request')->getHeaderLine('Content-Type'), 'application/json') !== false)
    {
        $data = (array) service('request')->getJSON();
	$data = array_intersect_key($data, array_fill_keys($fields, null));
    }else{
        $data = array_filter(service('request')->getPost($fields));
    }
    return new User($data);
}

Is this modification acceptable?

@rafinhaa
Copy link
Contributor Author

rafinhaa commented Sep 1, 2021

protected function buildUserFromRequest()
{
    $fields = $this->prepareValidFields();

    $data = array_filter(service('request')->getPost($fields));
    if (empty($data)) {
        //convert request body to associative array
        $data = array_intersect_key(
            json_decode(service('request')->getBody(), true), 
            array_fill_keys($fields, null)
        );
    }
    return new User($data);
}

so it should be better!

@lonnieezell
Copy link
Owner

I think that is likely fine. If you can submit a PR for it, that would be awesome.

@Sparking2
Copy link

Hi, no news about adding this issue to the release?

@MGatner
Copy link
Collaborator

MGatner commented Jul 12, 2022

If someone wants to take this on as a PR please do.

@MGatner MGatner added the bug label Jul 12, 2022
@manageruz
Copy link
Collaborator

I'll do

@manageruz
Copy link
Collaborator

Maybe just like this?

protected function buildUserFromRequest()
 {
        $fields = $this->prepareValidFields();

        // $data = array_filter(service('request')->getPost($fields));
       
        // pulling data from $_REQUEST, get rid of NULL values
        // works fine with both 'form-multipart' and 'application/json' content-types
        // return type is array
        $data = array_filter(service('request')->getVar($fields));

        return new User($data);
 }

@manageruz
Copy link
Collaborator

And what about Shield? Shield's code is same as Myth.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants