Cutelyst  2.3.0
Public Types | Public Member Functions | Static Public Member Functions | List of all members
Cutelyst::Validator Class Reference

Validation processor for input data. More...

#include <Cutelyst/Plugins/Utils/Validator>

Public Types

enum  ValidatorFlag {
  NoSpecialBehavior, StopOnFirstError, FillStashOnError, NoTrimming,
  BodyParamsOnly, QueryParamsOnly
}
 Flags that change the behavior of the Validator. More...
 

Public Member Functions

 Validator (QLatin1String translationContext=QLatin1String())
 Constructs a new Validator.
 
 Validator (std::initializer_list< ValidatorRule *> validators, QLatin1String translationContext=QLatin1String())
 Constructs a new Validator using the defined validators. More...
 
 ~Validator ()
 Desconstructs the Validator and all added ValidatorRule objects.
 
void addValidator (ValidatorRule *v)
 Adds a new validator to the list of validators. More...
 
void clear ()
 Clears all internal data. More...
 
ValidatorResult validate (Context *c, ValidatorFlags flags=NoSpecialBehavior) const
 Starts the validation process on Context c and returns a ValidatorResult. More...
 
ValidatorResult validate (Context *c, const ParamsMultiMap &parameters, ValidatorFlags flags=NoSpecialBehavior) const
 Starts the validation process on the parameters and returns true on success. More...
 

Static Public Member Functions

static void loadTranslations (Application *app)
 Loads the translations for the plugin.
 

Detailed Description

Validator can validate input data from the Context or a ParamsMultiMap using validation rules implemented as classes derived from ValidatorRule. As long as the Validator::StopOnFirstError flag is not set, all validations will be performed until the end. Validations will be performed in the order they were added on construction or via addValidator(). Any field can have any amount of validators. The Validator will take ownership of the added validator rules and will delete them on it's own destruction.

Any validator requires at least the name of the field that should be validated. Some validators have additional mandatory parameters that have to be set. The ValidatorSame for example has a mandatory parameter to set the name of the other field to compare the values.

If you are using custom translatable error messages, you have to set the translation context on the Validator on the constructor. The same translation context has than to be used with the custom strings for the validators. See ValidatorMessages for more information about translation of custom messages.

Setting the FillStashOnError flag on the validate() function will add all error information as well as the not sensible (not containing the string "password" in the field name) input data to the stash if validation fails.

If only parameters from the request body or the request URL query should be taken into account by the validator, use the BodyParamsOnly or QueryParamsOnyly flag on the validate() function. If both are set, BodyParamsOnly takes precedence. If nothing is set, all parameters to validate will be taken from both, body and query.

Usage example

In Cutelyst 1.x validator rules were usable standalone without being part of a Validator object - even though they were never meant to be. This changed in Cutelyst 2.0.0 so that only the constructor and destructor of a ValiadtorRule are public anymore. However they now can be used more flexible by pointing them to other input fields or stash keys to get validation data like compare values. Some validator rules like the ValidatorEmail export their validation logic as static function so that it can be used standalone directly on a value without needing a Context.

Most validators will succeed if the input field is empty. You should use them together with one of the required validators if the input field is required. This approach is more flexible than having a simple switch in any validator. There are different validators to require a field that make it possible to have more complex requirements. You can find information about the behavior on empty input fields in the documenation of every validator rule. You can find some more general information at ValidatorRule and for sure in the documentation for every single validator rule. Information about writing your own validators that work with this concept can be found at ValidatorRule.

Validator will return a ValidatorResult after validation has been performed. The result can be used to check the validity of the input data. It will contain error messages from every failed ValidatorRule and a list of field names for which validation failed as well as the extracted values from the fields under validation. If there are no failed validations, the result will be valid, what you can check via ValidatorResult::isValid() or directly with an if statement.

#include <Cutelyst/Plugins/Utils/Validator> // includes the main validator
#include <Cutelyst/Plugins/Utils/Validators> // includes all validator rules
#include <Cutelyst/Plugins/Utils/ValidatorResult> // includes the validator result
void MyController::myform(Context *c)
{
if (c->req()->isPost()) {
// create a new static Validator with a set of rules and a translation context
static Validator v({
// this one will require the username to be present and not empty
new ValidatorRequired(QStringLiteral("username")),
// this one will require the username, if present (it has to be, see above),
// to have a length between 3 and 255 characters
new ValidatorBetween(QStringLiteral("username"), QMetaType::QString, 3, 255),
// username can be long, but we dont want have anything else than ASCII alpha-numeric characters,
// dashes and underscores in it
new ValidatorAlphaDash(QStringLiteral("username"), true),
// we also require an email address
new ValidatorRequired(QStringLiteral("email")),
// and damn sure, the email address should be valid, at least it should look like valid
// we are using a custom validation error message without a label
new ValidatorEmail(QStringLiteral("email"),
ValidatorEmail::Valid, // really strict validation
false, // we will not perform a DNS check
ValidatorMessages(nullptr, QT_TRANSLATE_NOOP("MyController", "The email address in the Email field is not valid."))
),
// seems like we are building a registration form, so lets require a password
new ValidatorRequired(QStringLiteral("password")),
// the password should have a niminum length of 10 characters
new ValidatorMin(QStringLiteral("password"), QMetaType::QString, 10),
// the user should confirm the password in another field
// and here we are using a custom error message
new ValidatorConfirmed(QStringLiteral("password"),
ValidatorMessages(QT_TRANSLATE_NOOP("MyController", "Password"),
QT_TRANSLATE_NOOP("MyController", "Please enter the same password again in the confirmation field."))
);
}, QLatin1String("MyController"));
// ok, now we have all our validators in place - let the games begin
// we will set the FillStashOnError flag to automatically fill the context stash with error data
// and as you can see, we can directly use the ValidatorResult in an if statement, because of it's
// bool operator in this situation, because we are filling the stash directly in the Valiator
if (v.validate(c, FillStashOnError)) {
// ok everything is valid, we can now process the input data and advance to the next
// step for example
c->response()->redirect(uriFor("nextstep"));
// but what happens if the input data was not valid?
// because we set FillStashOnError, the Validator will automatically fill the stash
// with error information so that our user can enter them correclty now
}
}
c->setStash({QStringLiteral("template), QStringLiteral("myform.html")});
}

Automatically filling the stash

If you set the FillStashOnError flag on the validate() function, the Validator will automatically fill the stash of the Context with error information and field values that are not sensible (field names that do not contain "password").

Beside the field values added with their field names, Validator will add two more entries to the stash:

Let's assume that a user enters the following values into the form fields from the example above:

The validation will fail, because the email address is not completely valid (it uses a TLD as domain, what is allowed according to RFC5321, but we set the ValidatorEmail::Valid category as threshold for the validation, thas does not allow TLDs as domain part) and the password confirmation does not match the password.

Validator will add the following entries to the stash :

The sensible data of the password fields is not part of the stash, but the other values can be used to prefill the form fields for the next attempt of our little Schalke fan and can give him some hints what was wrong.

Usage with Grantlee

The following example shows possible usage of the error data with Grantlee and the Bootstrap3 framework.

{% if validationErrorStrings.count %}
<div class="alert alert-warning" role="alert">
<h4 class="alert-heading">Errors in input data</h4>
<p>
<ul>
{% for errorString in validationErrorStrings %}
<li>{{ errorString }}</li>
{% endfor %}
</ul>
</p>
</div>
{% endif %}
<form>
<div class="form-group{% if validationErrors.email.count %} has-warning{% endif %}">
<label for="email">Email</label>
<input type="email" id="email" name="email" maxlength="255" class="form-control{% if validationErrors.email.count %} form-control-warning{% endif %}" placeholder="Email" aria-describedby="emailHelpBlock" required value="{{ email }}">
<small id="emailHelpBlock" class="form-text text-muted">The email address will be used to send notifications and to restore lost passwords. Maximum length: 255</small>
</div>
</form>

Translations

Use Validator::loadTranslations(this) in your reimplementation of Application::init() if you are using the Validator plugin and want to use translated generic messages.

Definition at line 239 of file validator.h.

Member Enumeration Documentation

◆ ValidatorFlag

Enumerator
NoSpecialBehavior 

No special behavior, the default.

StopOnFirstError 

Will stop the validation process on the first failed validation.

FillStashOnError 

Will fill the context's stash with error information.

NoTrimming 

Will set trimBefore() to false on every validator. (default behavior is true)

BodyParamsOnly 

Will only check for parameters that are send in the request body. (since Cutelyst 2.0.0)

QueryParamsOnly 

Will only check for parameters that are part of the request URL query. (since Cutelyst 2.0.0)

Definition at line 245 of file validator.h.

Constructor & Destructor Documentation

◆ Validator()

Validator::Validator ( std::initializer_list< ValidatorRule *>  validators,
QLatin1String  translationContext = QLatin1String() 
)
explicit
Parameters
validatorsList of validators that should be performed on the input fields. The Validator will take ownerhip of them and will destroy them on it's own destruction.

This constructor is only available if the compiler supports C++11 std::initializer_list.

Definition at line 35 of file validator.cpp.

Member Function Documentation

◆ addValidator()

void Validator::addValidator ( ValidatorRule v)

Adds a new ValidatorRule to the list of validators. On destruction of the Validator, all added rules will get destroyed, too.

Definition at line 135 of file validator.cpp.

◆ clear()

void Validator::clear ( )

Will clear the parameters and the used validators. ValidatorRule objects that have been added to the Validator will get destroyed.

Definition at line 45 of file validator.cpp.

◆ validate() [1/2]

Cutelyst::ValidatorResult Validator::validate ( Context c,
ValidatorFlags  flags = NoSpecialBehavior 
) const

Requests the input parameters from Context c and processes any validator added through the constructor or via addValidator() (unless Validator::StopOnFirstError is set). Returns a ValidatorResult that contains information about validation errors, if any. The result can be checked directly in if statements.

If Validator::FillStashOnError is set, it will fill the stash of Context with error data and not sensible input values.

Definition at line 55 of file validator.cpp.

References Cutelyst::Request::bodyParameters(), BodyParamsOnly, Cutelyst::Request::queryParameters(), and QueryParamsOnly.

◆ validate() [2/2]

ValidatorResult Validator::validate ( Context c,
const ParamsMultiMap parameters,
ValidatorFlags  flags = NoSpecialBehavior 
) const