I want to use the out-of-the-box Laravel password validation rules. This is possible by using the use Illuminate\Validation\Rules\Password class.
So you can use those rules like so:
\Illuminate\Validation\Rule\Password::min(8)->letters()->numbers()->mixedCase()->uncompromised(3)
However, you can't use those rules inside a config file, like in this package because you get the following error when running
artisan config:cache
❯ artisan config:cache > ─╯
Configuration cache cleared successfully.
LogicException
Your configuration files are not serializable.
at vendor/laravel/framework/src/Illuminate/Foundation/Console/ConfigCacheCommand.php:84
80▕ require $configPath;
81▕ } catch (Throwable $e) {
82▕ $this->files->delete($configPath);
83▕
➜ 84▕ throw new LogicException('Your configuration files are not serializable.', 0, $e);
85▕ }
86▕
87▕ $this->info('Configuration cached successfully.');
88▕ }
1 bootstrap/cache/config.php:859
Error::("Call to undefined method Illuminate\Validation\Rules\Password::__set_state()")
After reading the docs, it seems that you can't use those password rules as strings inside an array like so:
"password_rules" => ['min:8'],
So checking the available rules, the rest of the following rules (letters, mixedCase, uncompromised) are not available.
Then, is there a workaround to set those password rules inside the config file?
(so that, I can avoid the LogicException: Your configuration files are not serializable. after executing the artisan config:cache command).
use Illuminate\Validation\Rules\Password;
$rules = [
'password' => [
'required',
'string',
Password::min(8)
->mixedCase()
->numbers()
->symbols()
->uncompromised(),
'confirmed'
],
]
Try using the above code it should work.
I am not a Laravel person, but you can put the config into an array and then unpack it later in your app with something like this:
// for illustration
class Mock {
public function __call($name, $args) {
printf("called: %s(%s)\n", $name, implode(', ', $args));
return $this;
}
// this is awful. never do this.
// in Laravel the min() function, and only this function, is basically
// an alias to the constructor, which is weird.
public static function __callStatic($name, $args) {
return (new self())->$name(...$args);
}
}
$params = [
'min' => [8],
'letters' => [],
'numbers' => [],
'mixedCase' => [],
'uncompromised' => [3]
];
$o = NULL;
foreach( $params as $func => $args ) {
if( is_null($o) ) {
$o = Mock::$func(...$args);
} else {
$o = $o->$func(...$args);
}
}
Output:
called: min(8)
called: letters()
called: numbers()
called: mixedCase()
called: uncompromised(3)
Related
I would like to separate Tests and Data Providers. Using PHP 8 attributes, I cannot get the following test to run when referencing an external Data Provider:
#[Test]
#[DataProviderExternal(RouterDataProvider::class, 'registerGetRouteData')]
public function itRegistersGetRoute(Route $route, array $expectedResult)
{
$this->router->get($route);
$this->assertEquals($expectedResult, $this->router->getRoutes());
}
My data provider class:
class RouterDataProvider
{
public static function registerGetRouteData(): array
{
return [
$route = new Route('/', ['IndexController', 'index']),
[
'GET' => [
'/' => $route,
],
'POST' => []
]
];
}
}
How could I get this test to run with the desired provider method?
By running PHPUnit with the following flags, I was able to see exactly what my issue was:
./vendor/bin/phpunit --display-deprecations --display-warnings --diplay-errors --display-notices
The data set was invalid. Changing the return to yield and updating the return type for the registerGetRouteData method from array to \Generator resolved this.
I was running phpunit with the --testdox flag, so I'm not sure if this is what stopped me seeing any errors initially and assume the test was being skipped.
I have used the Laravel Auditing plugin (http://www.laravel-auditing.com/docs/3.1) to log the all models changes.Am using different auth system but the Laravel Auditing
getLoggedInUserId()
using laravel core one so need to change that. i have forked this plugin and edited the function directly its worked. But i like to find another ways if you have idea share with me ?
protected function getLoggedInUserId()
{
try {
if (Auth::check()) {
return Auth::user()->getAuthIdentifier();
}
} catch (\Exception $e) {
return;
}
}
Unfortunately, until version 4 of the package, you couldn't change the user resolver without modifying the actual code.
However, from version 4 onwards, you can do so in the configuration file (config/audit.php).
The user resolver can be set in two ways.
As a Closure:
return [
'user' = [
'resolver' => function () {
return Auth::check() ? Auth::user()->getAuthIdentifier() : null;
},
],
];
As a FQCN:
return [
'user' = [
'resolver' => App\User::class,
],
];
TIP: You have to implement the OwenIt\Auditing\Contracts\UserResolver interface in the App\User class for this to work.
See the full documentation here.
I built an API using dingo/api 0.10.0, Laravel 5.1 and lucadegasperi/oauth2-server-laravel": "^5.1".
All my routes work fine in Postman/Paw!
The problem appears when I try to test the API using PHPUnit.
This is part of my route-api.php file
<?php
$api = app('Dingo\Api\Routing\Router');
$api->version(['v1'], function ($api) {
$api->post('oauth/access_token', function () {
return response(
\LucaDegasperi\OAuth2Server\Facades\Authorizer::issueAccessToken()
)->header('Content-Type', 'application/json');
});
$api->group(['middleware' => ['oauth', 'api.auth']], function ($api) {
$api->post('/register', 'YPS\Http\Controllers\Api\UserController#register');
});
And this is my test file UserRegistrationTest.php
class UserRegistrationTest extends ApiTestCase
{
public function setUp()
{
parent::setUp();
parent::afterApplicationCreated();
}
public function testRegisterSuccess()
{
$data = factory(YPS\User::class)->make()->toArray();
$data['password'] = 'password123';
$this->post('api/register', $data, $this->headers)
->seeStatusCode(201)
->seeJson([
'email' => $data['email'],
'first_name' => $data['first_name'],
'last_name' => $data['last_name'],
]);
}
public function testRegisterMissingParams()
{
$this->post('api/register', [], $this->headers, $this->headers, $this->headers)->seeStatusCode(422);
}
}
The ApiTestCase simply retrieves a token and sets the headers.
private function setHeaders()
{
$this->headers = [
'Accept' => 'application/vnd.yps.v1+json',
'Authorization' => 'Bearer ' . $this->OAuthAccessToken,
];
}
Now, the weird part is that the first test testRegisterSuccess runs perfectly and returns the response I expect. But the second one testRegisterMissingParams, even though it's the same route, returns this,
array:2 [
"message" => "The version given was unknown or has no registered routes."
"status_code" => 400
]
I tracked the error and it is in the Laravel adapter here:
public function dispatch(Request $request, $version)
{
// it seems that the second time around can't find any routes with the key 'v1'
if (! isset($this->routes[$version])) {
throw new UnknownVersionException;
}
$routes = $this->mergeExistingRoutes($this->routes[$version]);
$this->router->setRoutes($routes);
return $this->router->dispatch($request);
}
And further more, if i run one test at a time (eg comment one out, run test and then comment the other and run test) i see the result expected in both tests. The problem is when i run multiple tests.
Any thoughts on that?
Thank you!
Run php artisan api:routes to see full path you may have missed something for the URL, also if this working if you request your URL manually?
I had same problem with testing using Dingo & Lumen. This worked for me - remove bootstrap="bootstrap/app.php" from phpunit.xml file and change line processIsolation="false" to processIsolation="true".
In my ConfigServerProvider.php at boot there is a reference to the configs database table. At initial migrate this database table doesn't exist, so I am getting an error. How can I run the first time 'php artisan migrate', while leaving this boot line intact?
public function boot() {
config([
'version' => "1.0.2",
'title' => Config::where('name', 'title')->first()->pluck('value')
]);
}
I added this around the whole config:
if(Schema::hasTable('configs')) { }
And that seems to make all work.
In my app i made this:
try {
$configs = Config::all();
} catch (\Exception $e) {
$configs = [];
}
I am making WebServices tests with Codeception, here is my code:
//Making first query for getting needed parameter
$I->wantTo('Make something');
$I->sendPOST($this->route, [
'token' => Fixtures::get('token'),
'id' => Fixtures::get('some_id')
]);
$I->seeResponseCodeIs(200);
$I->seeResponseIsJson();
$I->seeResponseContains('"error_message"');
//Then I get what I need with regexp
if (preg_match('/^.*\s(?<value_i_need>\d+)\.$/', $I->grabDataFromResponseByJsonPath('$.status.error_message')[0], $matches)) {
$I->sendPOST($this->route, [
'token' => Fixtures::get('token'),
'id' => Fixtures::get('some_id')
]);
$I->seeResponseCodeIs(200);
$I->seeResponseIsJson();
$I->seeResponseContains('"something"');
$I->seeResponseContains('"something_else"');
} else {
//And if I don't get needed parameter with regular expression, here I have to force test fail
}
Does anybody know how to force test fail?
Thanks in advance!
You can use the fail action on your actor. i.e.
$I->fail('this test fails... just because');
You can mark your test as skipped or incomplete. Here is example:
public function tryToMakeAwesomeThings(ApiTester $I, Scenario $scenario)
{
if ( ... ) {
// do something
} elseif ( ... ) {
$scenario->incomplete();
} elseif ( ... ) {
$scenario->skip();
}
}
You can use PHPUnit\Framework\Assert::fail() or throw PHPUnit\Framework\AssertionFailedError exception.
There is another problem with Codeception 4 and upper.
Method fail now in Assertion module https://codeception.com/docs/modules/Asserts
This module not included in codeception by default, you must install it separately.
When you install it, this module must be added in config file, such as "api.suite.yml"
actor: ApiTester
modules:
enabled:
...
- \Codeception\Module\Asserts
After this, you need to rebuild codeception and this method appear to use.
Use assertInstanceOf() from https://codeception.com/docs/modules/Asserts
Example:
public function test_array_result() {
/** #var Demo $demo */
$demo = Common::get_which_class( $this->post_id );
self::assertInstanceOf( Demo::class, $demo, 'Unable to instantiate the Demo class.');
$x = [ 'a', 'b', 'c' ];
$this->assertEqualSetsWithIndex( $x, $demo->get_result() );
}