Is there a way to conditionally validate with class-validator? - validation

I'm building a CRUD for users using Nest.js
I'd like to have the POST and PATCH receive the same DTO but have some fields optional in PATCH but mandatory in POST.
I couldn't find a way to do this other than keep all properties #IsOptional and manually write the validation in the code for POST requests.
Is there a better way to do it with class-validator ?

NestJS Provides a beautiful solution for your problem,
you can use PartialType, To create a type with the same fields, but with each one optional, use PartialType() passing the class reference (PsotDto) as an argument:
export class PatchDto extends PartialType(PostDto) {}

you can use Custom validation classes,
Because nestjs uses it you can make it too.

You can try #ValidateIf conditional validation
If ValidateIf return true then the other validation will run
examle : in this case if o.otherProperty === 'value' then the #IsNotEmpty will run otherwise it will not run
export class Post {
otherProperty: string;
#ValidateIf(o => o.otherProperty === 'value')
#IsNotEmpty()
example: string;
}

Related

laravel: function in model must return a relationship instance

I try to build a path for a model on laravel
I created a function in my model:
public function path()
{
return App\Helper\GeneralController::getURL($this);
}
with dd(App\Helper\GeneralController::getURL($this)) test I got the right answer. (output is a URL)
but in view with the call: $article->path I get this error:
App\Article:: path must return a relationship instance.
What is wrong?
You need to call it:
$article->path()
When you do $article->path, you're trying to use Eloquent relationship which you don't have.
I know this has already been answered and accepted. However, if the OP did want to use a property accessor rather than a method use the "get{property name}Attribute" syntax of Laravel to create a custom attribute.
Here is what it would look like for this specific case:
public function getPathAttribute()
{
return App\Helper\GeneralController::getURL($this);
}
using this approach "path" can now be called as an attribute and will not be resolved to a relationship using the syntax:
$article->path;
You're calling a relationship.
$article->path
To call the method, use '()', like so,
$article->path()
I faced that error when I forgot to write return before relation in the model!
check it out now!
path() is method not object element you need to call as method
$article->path();
Laravel 9 introduced a new way to define accessors/mutators within a model using Illuminate\Database\Eloquent\Casts\Attribute.
https://laravel.com/docs/9.x/eloquent-mutators#defining-an-accessor
public function path(): Attribute
{
return new Attribute(fn () => GeneralController::getURL($this));
}
For future visitors from Google, all the other answers can be applicable in certain scenarios, but you might want to also look if your method access modifier, if your method is protected and you try to call it you will be welcome with this error. You need change your method to public.

Returning extended custom object parameter from function in TypeScript and have VS intellisense show the extended properties

The only way I can properly explain what I'm trying to do is by example:
function CustomExtend(myParam: Object): Object {
return $.extend(myParam, { extraParameter: 'extraParam' });
}
I want intellisense when using the CustomExtend function to provide all the properties and methods of the object passed in plus the extraParameter property added inside the function. The closest I could get to getting this to work was by using generics and an interface:
interface IMyParamStructure {
extraParameter?: string;
}
function CustomExtend<TParam extends IMyParamStructure>(myParam: TParam): TParam {
myParam.extraParameter='extraParam';
return myParam;
}
This works to a degree, it has intellisense correctly of all the properties and methods of the object passed in (myParam) but it still doesn't have the extraParameter property on the result. I expect this is because I made it optional and it wasn't passed in (because I don't want to have to pass it in). Is this just not possible with the TypeScript compiler?
EDIT: Forgot to add that the generic parameter should be inferred, not given, i.e. it would be used in this way:
var result=CustomExtend({ param1: 'something', param2: 'something else' });
What I want is for intellisense to show param1, param2 and extraParameter.
In TypeScript all type inference needs to be at compile time. TypeScript cannot modify interface definitions based on calling context.
This would require the ability to write code that runs within the compiler context with access to the AST which is not a planned feature at the moment.
Here is a related stackoverflow question : Is it possible to model jQuery.fn.extend using TypeScript

How to enforce Grails command objects have been validated?

We use the following general pattern with Grails controllers and command objects
SomeController {
def someAction() {
SomeCommandObject co = SomeCommandObject.valueOf(params)
if(!co.validate()) {
// return bad request
}
someService.doWork(co)
// return ok
}
SomeService {
def doWork(SomeCommandObject co) {
notTrue(!co.hasErrors(), 'cant have errors') // Commons validation
// do actual work
}
}
Apparently, if co.validate() has not been called, .hasErrors() will always return false. Is there a better way to enforce that .validate() has been called before a command object is passed between application layers? We don't want to pass around invalid command objects but we don't want to force every new method to re-validate the command object either.
Note: We aren't using the default controller/command object creation pattern because we need to do some custom parameter map checking, we use a static valueOf method instead to create the command object. Answers that change that practice are also welcome.
EDIT: A little more info on why we aren't using the 'default' controller/command object creation. Specifically why we aren't doing ..
def someAction(SomeCommandObject co) {
}
We have a requirement to disallow random query parameters, eg. endpoint/object?color=blue. To do that we need access to the parameter map in the command object to verify that it doesn't contain any 'unexpected' parameter keys. As I understand it, the default way would just create a member on the CO named color, and I don't see how to prevent arbitrary members using even custom validators. I'd happily entertain suggestions for doing so, thereby allowing us to use this default means.
Yes; what you can do is pass the command object as a parameter to the controller, and then the command will always be validated automatically.
Also, what you can do, is to make a filter or similar, so that you don't have to check for the hasErrors() each time, but handle all the cases in the same way (for example, by throwing an error, or returning with a specific response).
In an application we created, we had something like:
withValidCommand(cmd) {
// do work
}
Which worked pretty well. But maybe you can come up something even more elegant.
You should be doing this:
def someAction(SomeCommandObject co) {
if (!co.hasErrors()) {
someService.doWork(co)
}
}
By passing SomeCommandObject in as the argument grails will automatically populate it from params and validate. No need to do it manually.

Encoding in UTF-8 instead of ASCII - SilverStripe

I'm using 2.4.7 and I want to include some validation for two fields which take in prices (e.g. €1 or 2 for €3). Originally I thought that perhaps I would need to resort to validating user input but as the answer suggests it was a database issue.
The encoding within SilverStripe was defaulting to ASCII which converted the symbols such as the euro symbol. In the end I need to add
$this->response->addHeader("Content-Type", "application/json; charset='utf-8'");
to the init method in the controller. This corrected the encoding issue and prevented a hacky workaround taking place. Many thanks for the insight on this one.
Thanks
I'm assuming you want to do this in the CMS. If that's the case, the easiest way is probably to create a new class which extends the TextField class and adds a public function validate() method which performs your validation (see the CreditCardField class for an example).
class FancyCurrencyField extends TextField {
public function validate($validator) {
// Do your validation
if ($invalid) {
$validator->validationError(
$this->name,
"Please don't use currency symbols.",
"validation",
false
);
return false;
}
return true;
}
}
Once you've created your class, you can modify the form fields in your getCMSFields() function on the DataObject and use the new class in place of TextField.
Having said that, it feels like output encoding and not input validation is the root cause of your problem. I'd check to make sure that everything is setup to use UTF-8.
I encountered a problem with the PHP function substr. I just used mb_substr instead and it solved my issue.
Please view http://www.silverstripe.org/general-questions/show/11797#post369831

Turn off required field validation based on query string value?

I have a registration form with about 30 fields (yes.. I know.. insanity). I need some of these fields to be required by certain types of people. What I'd like to do is just use a query string like example.com/user/register/?type=notrequired. If type = notrequired then I'd like to make to make the fields not required. Is this possible? I tried using the jQuery Validate plugin but its not working.. I'm thinking the built in Drupal validation is conflicting with it :(
The required flag is set server side so I doubt you'll be able to affect it using javascript. You'll have to hook into the form and make the changes in PHP, something like this in a custom module:
function mymodule_form_user_register_form_alter(&$form, &$form_state, $form_id) {
if (isset($_GET['element_name']) && $_GET['element_name'] == 'notrequired') {
$form['element_name']['#required'] = FALSE;
}
}
Hope that helps

Resources