preaction / Yancy

The Best Web Framework Deserves the Best Content Management System
http://preaction.me/yancy/
Other
54 stars 21 forks source link

TIMESTAMP AND CURRENT_TIMESTAMP problem #88

Closed pavelsr closed 4 years ago

pavelsr commented 4 years ago

Possible duplicate/clarification of issue #79

E.g. I have table

CREATE TABLE users (
  `id` int(4) NOT NULL AUTO_INCREMENT PRIMARY KEY,
  `username` VARCHAR(255) NOT NULL,
  `password` VARCHAR(40) NOT NULL,
  `created` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
  UNIQUE KEY (`username`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci;

I set read_schema => 1 in Yancy config and try to execute

app->yancy->create( users => { username => "admin", password => "admin" } );

If I not provide created explicitly via Perl, like created => '2019-01-01 14:45:12' there will be an error:

app_1  | Use of uninitialized value in sprintf at /usr/local/share/perl5/site_perl/Mojolicious/Plugin/Yancy.pm line 848.
app_1  | [2020-04-01 23:11:42.25123] [33] [error] Error validating new item in schema "users":  (/created)

Seems like yancy.validate not produce any @errors but for some reason failed.

Is it possible to get verbose description of error ? Is that issue related to Mojo::mysql or JSON::Validator?

As temporary solution I generate CURRENT_TIMESTAMP via POSIX::strftime(), like print strftime "%Y-%m-%d %H:%M:%S", localtime time, but still, any way to leave handling timestamp for SQL ?

preaction commented 4 years ago

Ah. Looks like JSON::Validator is saying that the object is invalid because created is missing. That is probably a bug in read_schema: A column that is NOT NULL is marked as required in the validator, but I don't think I check to see if it also has a DEFAULT (which would make it no longer required, since the database will solve the NOT NULL problem).

So, the fix is to make sure that the validator doesn't fail on missing NOT NULL fields that will have a default generated by the database.

As a temporary workaround, the magic string "now" might work to bypass validation: app->yancy->create( users => { username => "admin", password => "admin", created => "now" } );

As another temporary workaround, invoking the backend's method skips validation (but it then also skips filters and schema-defined defaults, so YMMV): app->yancy->backend->create( users => { username => "admin", password => "admin" } );

pavelsr commented 4 years ago

->backend is ok. magic string "now" is not working, same Error validating new item in schema "users": (/created) error.

My Yancy version is 1.047

pavelsr commented 4 years ago

By the way, yancy->backend->create insert password in plain so it's impossible to use this workaround in practise.

preaction commented 4 years ago

Sorry, yes, I forgot that bypasses the filters as well, which is how the digests work... I'm working on reproducing the problem and hope to have a fix soon.

preaction commented 4 years ago

I can't seem to reproduce the error with the Yancy unit tests. Could you send me a dump of the JSON schema of the users schema? You can get it by doing:

./myapp.pl eval -V 'app->yancy->schema( "users" )'