I want to make a custom validator that should check the input Url is valid or not.
I want to use the following regex that I tested in expresso, but comes off invalid when used in typescript (the compiler fails to parse it):
(((ht|f)tp(s?))\://)?((([a-zA-Z0-9_\-]{2,}\.)+[a-zA-Z]{2,})|((?:(?:25[0-5]|2[0-4]\d|[01]\d\d|\d?\d)(?(\.?\d)\.)){4}))(:[a-zA-Z0-9]+)?(/[a-zA-Z0-9\-\._\?\,\'/\\\+&%\$#\=~]*)?
The above url checks for optional http:\\\ and also will validate an Ip address
The following url's should be valid :
192.1.1.1
http://abcd.xyz.in
https://192.1.1.126
abcd.jhjhj.lo
The following url's should be invalid:
192.1
http://hjdhfjfh
168.18.5
Kindly assist
The forward slashes / are not escaped in the regex.
What is valid or invalid in Javascript is valid or invalid in Typescript and vice-versa.
There may be another option for you, that relies on the URL class. The idea is to try converting the string into a URL object. If that fails, the string does not contain a valid URL.
public isAValidUrl(value: string): boolean {
try {
const url = new URL(value);
return isValid(url.pathname);
} catch (TypeError) {
return false;
}
}
isValid(value: URL): boolean {
// you may do further tests here, e.g. by checking url.pathname
// for certain patterns
}
Alternatively to returning a boolean you may return the created URL or null instead of a boolean or - if that exists in JavaScript or TypeScript: something like an Optional<URL>. You should adapt the method's name then, of course.
Related
I need a custom validator to ban a specific list of banned words from a textarea field.
I need exactly this type of implementation, I know that it's not logically correct to let the user type part of a query but it's exactly what I need.
I tried with a regExp but it has a strange behaviour.
My RegExp
/(drop|update|truncate|delete|;|alter|insert)+./gi
my Validator
export function forbiddenWordsValidator(sqlRe: RegExp): ValidatorFn {
return (control: AbstractControl): { [key: string]: any } | null => {
const forbidden = sqlRe.test(control.value);
return forbidden ? { forbiddenSql: { value: control.value } } : null;
};
}
my formControl:
whereCondition: new FormControl("", [
Validators.required,
forbiddenWordsValidator(this.BAN_SQL_KEYWORDS)...
It works only in certain cases and I don't understand why does the same string works one time and doesn't work if i delete a char and rewrite it or sometimes if i type a whitespace the validator returns ok.
There are several issues here:
The global g modifier leads to unexpected alternated results when used in RegExp#test and similar methods that move the regex index after a valid match, it must be removed
. at the end requires any 1 char other than line break char, hence it must be removed.
Use
/drop|update|truncate|delete|;|alter|insert/i
Or, to match the words as whole words use
/\b(?:drop|update|truncate|delete|alter|insert)\b|;/i
This way, insert in insertion and drop in dropout won't get "caught" (=matched).
See the regex demo.
it's not a great idea to give such power to the user
I'm developing a web application using Angular 6. I have a question:
I'm creating a custom input component (for text input) such as:
#Component({
selector: 'input-text',
templateUrl: './input-text.component.html'
]
})
export class InputTextComponent {
#Input() pattern?: string;
}
I would like a user can insert a regular expression for the validation of the input field, in this way:
<input-text pattern="^[a-z0-9_-]{8,15}$"></input-text>
The template of my component is defined like this:
<input type="text" [attr.pattern]="pattern"/>
Unfortunately I know absolutely nothing about regular expressions.
I would like to do two things:
1 - Create a method that checks the validity of the regular expression and changes the visual style.
2 - Make sure that if the input (with a pattern field) is inserted into a form, the attribute form.valid remains false until the expression is valid.
Thanks for your help!
Check regex validity
You can simply catch exceptions thrown by the RegExp constructor when instanciating it.
try {
const regex = new RegExp(pattern);
} catch (error) {
// If it goes here, then the regex model is not correct
console.error(error.message)
}
Change the visual style
You can simply use the ngClass attribute to change your input style.
If you enter the catch statement, set a style variable to change the class like so
private hasBadInput: boolean;
// [...]
catch (error) {
hasBadInput= true;
}
Then apply a specific class in that case:
<input-text [ngClass]="{'yourErrorClass': hasBadInput}"><input-text>
Form validity
You did well using [attr.pattern], the form should automatically consider the entered pattern. You should try your form with a hard written regex before, and then use the input one.
Follow this official guideline to create Angular 2+ forms.
We have a simple operator object, which uses spring security to encode the password thusly:
class Operator
transient springSecurityService
def siteService
String username
Site site
String password
def beforeInsert() {
encodePassword()
}
def beforeUpdate() {
if (isDirty('password')) {
encodePassword()
}
}
protected void encodePassword() {
password = springSecurityService?.passwordEncoder ? springSecurityService.encodePassword(password) : password
}
Now we want to validate that the password matches a regexp which is defined at runtime. Operators can be created via the UI (i.e. standard CRUD forms). We have a different regexp for each site. The fact that the password gets overwritten with an ecoded one, and we should not test that, makes it more challenging.
Attempt 1: do the validation in the encodePassword():
def beforeInsert() {
protected void encodePassword() {
String regexp = siteService.getInheritedValue(site, "operatorPasswordRegexp")
if (!password.matches(regexp) {
thrown new RuntimeException "invalid password format"
}
password = springSecurityService?.passwordEncoder ? springSecurityService.encodePassword(password) : password
}
}
This partially works, in that it stops passwords which don't match a regexp found at runtime being created. The problem is it throws an exception, which generates a 500 error page, when we want the operator edit form to highlight the password field with a nice friendly validation message.
Attempt two, using a custom validator
static constraints = {
password password: true, blank:false, validator: { val, obj ->
if (obj.isDirty(val)) {
return true
}
String regexp = obj.siteService.getInheritedValue(obj.operates, "operatorPasswordRegexp")
if (regexp != null && regexp != "") {
return val.matches(regexp)
}
return true
}
This appears to work, but the save always fails silently. It took me some time to realise why - when you do this:
operator.password="valid1"
opertor.save(failonError:true)
No errors are thrown. Even if you remove failonError, and check the return value,its always null (no errors). BUT IT DOES NOT SAVE THE OPERATOR.
The problem is that the beforeInsert is updating the password to an encoded version which does not pass the validator of course (and isnt supposed to), the validator says no at this point, and the save silently fails. I.e. the validiator is being called twice for a single save.
The question is, how to I get the beforeInsert() code to NOT call the validator, or the validator to ignore being called from beforeInsert?
You can achieve your task using both approaches.
1: Do the validation in the encodePassword(): Instead of throwing the exception, add an error to instance. I think your encodePassword() function is in your same domain, so get errors object associated to it using this.errors. ex:
this.errors.rejectValue("password", "user.password.pattern.error")
There are different rejectValue methods, this one accepts the field name and the message code defined in your message.properties file.
2: Custom Validator:
isDirty() is not a static method, call it using the obj provided in the custom validator. isDirty() accepts the property name to be checked for dirtiness not its value.
obj.isDirty(PropertyName)
constraints is a static block, it would not be able to directly access your service. You need to inject your service using static context.
static SiteService siteService;
I would recommend to do it using custom validator.
Is it possible to use the flowVariable inside wildcard or expression filter directly.
I need to stop the flow based on the flow Variable value.
Example: My flow Variable name keyValue have the value like customer/feed/h26/h56 in this 'h26/h56' should set dynamically but customer/feed is constant always. I need to set my filter only after '/feed/' if it contain any characters.
<flow name="testFlow1" doc:name="testFlow1">
<file:inbound-endpoint responseTimeout="10000" doc:name="File" path="c:/in"/>
.......( Many component)
<set-variable variableName="keyValue" value="#[customer/feed/h26/h56]" doc:name="Variable"/>
.......( Many component)
<message-filter doc:name="Message">
<wildcard-filter pattern="customer/feed/+*" caseSensitive="true"/>
</message-filter>
</flow>
Used + in pattern to check whether it contain one or more characters.
Also I used expression filter, not sure how to use flow Variable inside the filter expression. Could you please help me on this.
I don't want to use property filter.
Use expression filter instead, and since your expression is simple just use the startsWith method of String.
for example
<expression-filter expression="flowVars.keyValue.startsWith('customer/feed/')" doc:name="Expression"/>
this will allow messages
First of all, you can't use wildcard-filter on flowVars directly because it applies a wildcard pattern to the message payload. Here is the implementation excerpt from the org.mule.routing.filters.WildcardFilter class
public boolean accept(MuleMessage message) {
try {
return accept(message.getPayloadAsString());
} catch (Exception e) {
logger.warn("An exception occurred while filtering", e);
return false;
}
}
So it is clear that the WildcardFilter converts the payload to a String and applies the filter.
Also, in the case of regex-filter, it applies a regex pattern to the message payload. Here is an implementation excerpt from the org.mule.routing.filters.RegExFilter
public boolean accept(MuleMessage message) {
try {
return accept(message.getPayloadAsString());
} catch (Exception e) {
throw new IllegalArgumentException(e);
}
}
Now coming to your question, you can very well use expression-filter as suggested by Tyrone Villaluna. But you may want to include the expression in start and end signs like ^customer/feed/.+$
And so
<expression-filter expression="flowVars.keyValue.matches('^customer/feed/.+$')" />
I'm attempting to use WebJars-Locator with a Spring-Boot application to map JAR resources. As per their website, I created a RequestMapping like this:
#ResponseBody
#RequestMapping(method = RequestMethod.GET, value = "/webjars-locator/{webjar}/{partialPath:.+}")
public ResponseEntity<ClassPathResource> locateWebjarAsset(#PathVariable String webjar, #PathVariable String partialPath)
{
The problem with this is that the partialPath variable is supposed to include anything after the third slash. What it ends up doing, however, is limiting the mapping itself. This URI is mapped correctly:
http://localhost/webjars-locator/angular-bootstrap-datetimepicker/datetimepicker.js
But this one is not mapped to the handler at all and simply returns a 404:
http://localhost/webjars-locator/datatables-plugins/integration/bootstrap/3/dataTables.bootstrap.css
The fundamental difference is simply the number of components in the path which should be handled by the regular expression (".+") but does not appear to be working when that portion has slashes.
If it helps, this is provided in the logs:
2015-03-03 23:03:53.588 INFO 15324 --- [ main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/webjars-locator/{webjar}/{partialPath:.+}],methods=[GET],params=[],headers=[],consumes=[],produces=[],custom=[]}" onto public org.springframework.http.ResponseEntity app.controllers.WebJarsLocatorController.locateWebjarAsset(java.lang.String,java.lang.String)
2
Is there some type of hidden setting in Spring-Boot to enable regular expression pattern matching on RequestMappings?
The original code in the docs wasn't prepared for the extra slashes, sorry for that!
Please try this code instead:
#ResponseBody
#RequestMapping(value="/webjarslocator/{webjar}/**", method=RequestMethod.GET)
public ResponseEntity<Resource> locateWebjarAsset(#PathVariable String webjar,
WebRequest request) {
try {
String mvcPrefix = "/webjarslocator/" + webjar + "/";
String mvcPath = (String) request.getAttribute(
HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE, RequestAttributes.SCOPE_REQUEST);
String fullPath = assetLocator.getFullPath(webjar,
mvcPath.substring(mvcPrefix.length()));
ClassPathResource res = new ClassPathResource(fullPath);
long lastModified = res.lastModified();
if ((lastModified > 0) && request.checkNotModified(lastModified)) {
return null;
}
return new ResponseEntity<Resource>(res, HttpStatus.OK);
} catch (Exception e) {
return new ResponseEntity<>(HttpStatus.NOT_FOUND);
}
}
I will also provide an update for webjar docs shortly.
Updated 2015/08/05: Added If-Modified-Since handling
It appears that you cannot have a PathVariable to match "the remaining part of the url". You have to use ant-style path patterns, i.e. "**" as described here:
Spring 3 RequestMapping: Get path value
You can then get the entire URL of the request object and extract the "remaining part".