Email Validation in a controller Grails - validation

I'm just trying to validate an email address in a Controller which I thought would be simple. The method I've done is as follows:
def emailValidCheck(String emailAddress) {
EmailValidator emailValidator = EmailValidator.getInstance()
if (!emailAddress.isAllWhitespace() || emailAddress!=null) {
String[] email = emailAddress.replaceAll("//s+","").split(",")
email.each {
if (emailValidator.isValid(it)) {
return true
}else {return false}
}
}
}
This is being used with a sendMail function, which my code for that is here:
def emailTheAttendees(String email) {
def user = lookupPerson()
if (!email.isEmpty()) {
def splitEmails = email.replaceAll("//s+","").split(",")
splitEmails.each {
def String currentEmail = it
sendMail {
to currentEmail
System.out.println("what's in to address:"+ currentEmail)
subject "Your Friend ${user.username} has invited you as a task attendee"
html g.render(template:"/emails/Attendees")
}
}
}
}
This works and sends emails to valid email addresses, but if I put in something random that is not an address just breaks with sendMail exception. I can't understand why it's not validating correctly and even going into the emailTheAttendees() method ... which is being called in the save method.

I would suggest using constraints and a command object to achieve this. Example:
Command Object:
#grails.validation.Validateable
class YourCommand {
String email
String otherStuffYouWantToValidate
static constraints = {
email(blank: false, email: true)
...
}
}
Call it like this in your controller:
class YourController {
def yourAction(YourCommand command) {
if (command.hasErrors()) {
// handle errors
return
}
// work with the command object data
}
}

Related

Asp.Net Core MVC - Mailjet is not sending emails

I am using mailjet email service in my website to send emails. I have made sure that my SPF and DKIM records are up to date with my domain. However, when I run the project and register the user, it suppose to send email to the user's email id. It doesn't show any type of error but simply doesn't send the email. I have tried multiple times to change my code but still I am not able to send emails. Is there something I am missing in this context?
here is the code for the EmailSender.cs file :
using Mailjet.Client;
using Mailjet.Client.Resources;
using Microsoft.AspNetCore.Identity.UI.Services;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace Derawala.Models
{
public class EmailSender : IEmailSender
{
public Task SendEmailAsync(string email, string subject, string htmlMessage)
{
return Execute(email, subject, htmlMessage);
}
public async Task Execute(string email, string subject, string body)
{
MailjetClient client = new MailjetClient("******************", "*****************");
MailjetRequest request = new MailjetRequest
{
Resource = Send.Resource,
}
.Property(Send.Messages, new JArray {
new JObject {
{
"From",
new JObject {
{"Email", "*********************"},
{"Name", "Derawala Education & Charitable Trust"}
}
}, {
"To",
new JArray {
new JObject {
{
"Email",
email
}, {
"Name",
"Derawala Trust"
}
}
}
}, {
"Subject",
subject
},
{
"HTMLPart",
body
},
}
});
await client.PostAsync(request);
}
}
}
P.S. - I have hidden public key and secret key for this question only, in program I am using the real ones.
In above image, we can see that SPF and DKIM are up to date with the domain.

How to remove the nested input object in the Graphene Django mutation query (Relay)?

I want to create a Mutation in Relay. I'm using InputObjectType pattern to separate the input and make it reusable.
In mutation class I'm using Input class and there I'm passing the InputObjectType
In general it works but the final query at the client side is very ugly.
I need to pass arguments in this way
query( input : { input : { ...arguments } } )
and to be honest I don't like it. I think it looks ugly.
So the question is: Is it possible to avoid to use a lot of these input objects?
It's ok to use 1 input object, but the nested one is redundant and I'd like to avoid to use it.
Thanks for any help!
Here is the example
class FuelTypeInput(graphene.InputObjectType):
id = graphene.Int()
label = graphene.String()
class FuelSubtypeInput(graphene.InputObjectType):
id = graphene.ID()
label = graphene.String()
fuel_type = graphene.Field(FuelTypeInput)
class CreateFuelSubType(relay.ClientIDMutation):
class Input:
input = FuelSubtypeInput(required=True)
fuel_subtype = Field(FuelSubTypeNode)
ok = graphene.Boolean()
def mutate_and_get_payload(root, info, input):
label = input.label
fuel_type = FuelType.objects.get(pk=input.fuel_type.id)
fuel_subtype = FuelSubType(label=label, fuel_type=fuel_type)
ok = True
return CreateFuelSubType(fuel_subtype=fuel_subtype, ok=ok)
The mutation query is:
mutation MyMutations {
createFuelSubtype( input: { input : { label: "Mutation Subtype", fuelType: {
id: 3
}} } ) {
fuelSubtype {
label
}
ok
}
}
It works fine, here is the result. But I'd like to remove the nested input things
{
"data": {
"createFuelSubtype": {
"fuelSubtype": {
"label": "Mutation Subtype"
},
"ok": true
}
}
}
you can fix with this:
class FuelTypeInput(graphene.AbstractType):
id = graphene.Int()
label = graphene.String()
class CreateFuelSubType(relay.ClientIDMutation):
Input = FuelSubtypeInput
fuel_subtype = Field(FuelSubTypeNode)
ok = graphene.Boolean()
# Other Code ...

Publish events with MassTransit

I'm trying to publish message in one microservice and get it in another one, but cannot implement this using MassTransit 5.5.3 with RabbitMQ.
As far as I know we don't have to create a ReceiveEndpoint to be able to publish event so I'm just creating the same message interface in both services and publish a message, but as I can see in RabbitMQ it either goes to nowhere (if doesn't mapped to a queue) or goes to "_skipped" queue.
Publisher:
namespace Publisher
{
class Program
{
static async Task Main(string[] args)
{
var bus = Bus.Factory.CreateUsingRabbitMq(cfg =>
{
IRabbitMqHost host = cfg.Host("host", "vhost", h =>
{
h.Username("xxx");
h.Password("yyy");
});
});
bus.Start();
await bus.Publish<Message>(new { Text = "Hello World" });
Console.ReadKey();
bus.Stop();
}
}
public interface Message
{
string Text { get; set; }
}
}
Consumer:
namespace Consumer
{
class Program
{
static async Task Main(string[] args)
{
var bus = Bus.Factory.CreateUsingRabbitMq(cfg =>
{
IRabbitMqHost host = cfg.Host("host", "vhost", h =>
{
h.Username("xxx");
h.Password("yyy");
});
cfg.ReceiveEndpoint(host, e =>
{
e.Consumer<MbConsumer>();
});
});
bus.Start();
bool finish = false;
while(!finish)
{
await Task.Delay(1000);
}
bus.Stop();
}
}
public interface Message
{
string Text { get; set; }
}
public class MbConsumer : IConsumer<Message>
{
public async Task Consume(ConsumeContext<Message> context)
{
await Console.Out.WriteLineAsync(context.Message.Text);
}
}
}
I'm expeting the consumer to get the message once it's been published but it doesn't get it. I think this is because the full message types are different ("Publisher.Message" vs. "Consumer.Message") so message contract is different. How should I fix this code to get the event in the consumer? Looks like I'm missing some fundamental thing about RabbitMQ or MassTransit.
Your guess is correct. MassTransit uses the fully qualified class name as the message contract name. MassTransit also uses type-based routing, so FQCNs are used to create exchanges and bindings.
So, if you move your message class to a separate namespace like:
namespace Messages
{
public interface Message
{
string Text { get; set; }
}
}
You then can reference this type when you publish a message
await bus.Publish<Messages.Message>(new { Text = "Hello World" });
and define your consumer
public class MbConsumer : IConsumer<Messages.Message>
{
public async Task Consume(ConsumeContext<Message> context)
{
await Console.Out.WriteLineAsync(context.Message.Text);
}
}
it will work.
You might want also to look at RMQ management UI to find out about MassTransit topology. With your code, you will see two exchanges, one Publisher.Message and another one Consumer.Message where your consumer queue is bound to the Consumer.Message exchange, but you publish messages to the Publisher.Message exchange and they just vanish.
I would also suggest specifying a meaningful endpoint name for your receive endpoint:
cfg.ReceiveEndpoint(host, "MyConsumer", e =>
{
e.Consumer<MbConsumer>();
});

How can I validate a Grails domain class field based on its previous value?

First off: As far as I can tell, this is not a duplicate. The question “Grails: Custom validator based on a previous value of the field” got an answer suggesting the method getPersistentValue().
I am using Grails 2.2.3. The context is a “current password” field, where a user enters his current password before being allowed to change it to a new one.
So I have tried using getPersistentValue(), by means of something like this as a custom validator:
previousPassword(validator: { val, obj ->
def previous = obj.getPersistentValue('password')
if(val != previous) {
return ['yoErrorCode']
}
})
When I now try to update the user’s password in a controller action:
def changePassword() {
User user = User.get(springSecurityService?.currentUser?.id)
user.validate(["previousPassword"])
user.password = springSecurityService.encodePassword(params.updatedPassword)
if (user.errors.allErrors.size() == 0) {
try {
user.save(failOnError: true)
}
catch(Exception e) {
flash.message = "An error occurred"
render(view: "password_change", model: [user: user])
return
}
flash.message = "Updated password"
render(view: "password_change", model: [user: user])
return
} else {
render(view: "password_change", model: [user: user])
return
}
}
I get an error:
java.lang.IllegalArgumentException: object is not an instance of declaring class
Am I doing this wrong (the correct answer is probably “Yes”)? Or is there some other way of doing this?

grails domain object unexpectedly saved during validation

Considering the following domain classes :
class EnrichmentConfig {
String name
String description
String concept
List fields = []
static hasMany = [fields: FieldConfig]
static constraints = {
name(maxSize: 60, blank: false, nullable: false, unique: true)
concept(maxSize: 255, blank: false, nullable: false)
description(nullable: true, blank: true)
fields(nullable: false, validator: { fields, enrichmentConfig ->
if (fields?.isEmpty()) {
return ['empty']
} else {
return true
}
})
}
static mapping = {
description(type: 'text')
fields(cascade: "all-delete-orphan")
sort('name')
}
}
and
class FieldConfig {
List providers = []
static hasMany = [providers: String]
static belongsTo = [mainConfig: EnrichmentConfig]
static constraints = {
providers(nullable: false, validator: { providers, fieldConfig ->
// some custom validation
})
}
static mapping = {
providers(cascade: 'all-delete-orphan', lazy: false)
}
}
Here the code I use to update an EnrichmentConfig instance in the associated controller:
def update = {
def enrichmentConfig = EnrichmentConfig.get(params.long('id'))
if (enrichmentConfig) {
enrichmentConfig.properties = params
if (enrichmentConfig.validate()) {
if (enrichmentConfig.save(flush: true, failOnError: true)) {
flash.message = "${message(code: 'enrichmentConfig.updated.message', args: [enrichmentConfig.name])}"
redirect(controller: 'enrichment')
}
} else {
// re-validation to attach an error object to each eroneous fieldConfig
enrichmentConfig.fields?.each { it.validate() }
}
render(view: 'fields', model: getFieldsModel(enrichmentConfig))
return
} else {
flash.message = "${message(code: 'enrichmentConfig.not.found.message', args: [params.id])}"
redirect(controller: 'enrichment')
}
}
I've noticed that when I validate an instance of EnrichmentConfig to be updated, associated FieldConfig instances are unexpectedly saved in the database even though they are invalid.
In fact, in debug ste-by-step mode, while enrichmentConfig.validate() is executed, the following appears in the console:
Hibernate:
update
field_config_providers
set
providers_string=?
where
field_config_id=?
and providers_idx=?
How can this be happening? What am I doing wrong?
I should specify that I use grails 1.3.7.
Thanks in advance for your help.
This is just a guess but possibly someplace to start. I don't pretend to understand when Hibernate decides to flush sessions and partially save data and the like. But what I do know is that putting all write related calls in a service saves me a ton of grief over time.
Try moving some of your update method to a service and see if you have better luck. My hunch is that possibly, hibernate needs to persist some of the data to do other stuff and if it were in a transactional service, that write would rollback once the RuntimeException is thrown.
I suggest using a service to save your objects. First, check all the objects for validity using the validate() method.
Then, save the objects in the order in which they depend or in the hierarchy they follow.

Resources