How to add validation for file type in grails - validation

I have a domain object with following:
class Color {
String name
String fileLocation
static constraints = {
name (nullable: false, blank: false)
}
}
In my controller I'm doing the following:
def save() {
def colorInstance = new Color(params)
if (colorInstance.save(flush: true)) {
def file = request.getFile("myfile")
if (!file.empty && uploadService.isFileAllowed(file)) {
uploadService.uploadFile(file, file.originalName, "folderName")
}
}
else {
render (view: "create", model: [coorInstance: colorInstance])
}
}
This all works fine however, I'm not sure how to throw an error when the uploaded file isn't what is allowed. i.e. uploadService.isFileAllowed(file) returns false ??
How can I throw an error back to the user saying
Uploaded file isn't allowed
when uploadService.isFileAllowed(file) returns false ?
Note:
The isFileAllowed method is reading first few bytes of a file to determine what type of file it is.

What if you save an error message to flash memory and then render it on the page if it exists? See this post for help.
if (!file.empty && uploadService.isFileAllowed(file)) {
uploadService.uploadFile(file, file.originalName, "folderName")
} else {
flash.error = "Uploaded file isn't allowed"
}

apply this login in your controller
String fileName = "something.ext";
int a = fileName.lastIndexOf(".");
String extName = fileName.substring(a);
System.out.println(fileName.substring(a));
ArrayList<String> extList = new ArrayList<String>();
extList.add("jpg");
extList.add("jpeg");
extList.add("png");
if(extList.contains(extName))
{
System.out.println("proceed");
}
else{
System.out.println("throw exception");
}

So if isFileAllowed returns false or the file is empty, it will add an error to the colorInstance to the fileLocation property. It will only upload the file if the colorInstance validates successfully (to prevent files uploaded for unsaved objects).
As a side note, I prefer saving files in tables partly for this reason. It makes validation much less clunky and its impossible to have a disconnect between your objects and the files. - Just my 2c.
def save() {
def colorInstance = new Color(params)
def file = request.getFile("myfile")
if (!file.empty && uploadService.isFileAllowed(file)) {
if (colorInstance.validate()) {
uploadService.uploadFile(file, file.originalName, "folderName")
}
}
else {
colorInstance.errors.rejectValue('fileLocation','error.message.code.here')
}
if (colorInstance.save(flush: true)) {
//do whatever here
}
else {
render (view: "create", model: [coorInstance: colorInstance])
}
}

Related

Laravel help for optimize command script

I'm working with Lumen framework v5.8 (it's the same as Laravel)
I have a command for read a big XML (400Mo) and update datas in database from datas in this file, this is my code :
public function handle()
{
$reader = new XMLReader();
$reader->open(storage_path('app/mesh2019.xml'));
while ($reader->read()) {
switch ($reader->nodeType) {
case (XMLREADER::ELEMENT):
if ($reader->localName === 'DescriptorRecord') {
$node = new SimpleXMLElement($reader->readOuterXML());
$meshId = $node->DescriptorUI;
$name = (string) $node->DescriptorName->String;
$conditionId = Condition::where('mesh_id', $meshId)->first();
if ($conditionId) {
ConditionTranslation::where(['condition_id' => $conditionId->id, 'locale' => 'fr'])->update(['name' => $name]);
$this->info(memory_get_usage());
}
}
}
}
}
So, I have to find in the XML each DescriptorUI element, the value corresponds to the mesh_id attribute of my class Condition.
So, with $conditionId = Condition::where('mesh_id', $meshId)->first(); I get the Condition object.
After that, I need to update a child of Condition => ConditionTranslation. So I just get the element DescriptorName and update the name field of ConditionTranslation
At the end of the script, you can see $this->info(memory_get_usage());, and when I run the command the value increases each time until the script runs very very slowly...and never ends.
How can I optimize this script ?
Thanks !
Edit : Is there a way with Laravel for preupdate multiple object, and save just one time at the end all objects ? Like the flush() method of Symfony
There is a solution with ON DUPLICATE KEY UPDATE
public function handle()
{
$reader = new XMLReader();
$reader->open(storage_path('app/mesh2019.xml'));
$keyValues = [];
while ($reader->read()) {
switch ($reader->nodeType) {
case (XMLREADER::ELEMENT):
if ($reader->localName === 'DescriptorRecord') {
$node = new SimpleXMLElement($reader->readOuterXML());
$meshId = $node->DescriptorUI;
$name = (string) $node->DescriptorName->String;
$conditionId = Condition::where('mesh_id', $meshId)->value('id');
if ($conditionId) {
$keyValues[] = "($conditionId, '".str_replace("'","\'",$name)."')";
}
}
}
}
if (count($keyValues)) {
\DB::query('INSERT into `conditions` (id, name) VALUES '.implode(', ', $keyValues).' ON DUPLICATE KEY UPDATE name = VALUES(name)');
}
}

Confirm email in Magento using the Web-forms

I am using an extension in Magento called web-forms to create all the forms on my website. What I need to do is add the email verification fields (user must enter email twice. Both emails must match) How can I do this? I looked thru the extension but did not see a way to do it.
It looks like the web-forms is using prototype.js for validation.
I got it in case someone in the future has the same problem and in using the web-forms extension here is how you do it.
Assign css class thru the back end in magento->web-forms-(your form name)->the confirm email field(which you should create if you don't have it all ready)design tab->CSS classes for the Input element(put your class name here and remember it you are going to use it later)
Next open up in your root directory of the magento installation the validation.js file. Which is located in js/prototype/
Open the file and paste the code below after the validate-email
['[your class name]', 'Please make sure your emails match.', function(v)
{
var conf = $$('.[your class name]')[0];
var pass = false;
if ($('email')) {
pass = $('email');
}
var emailElements = $$('.validate-email');
for (var i = 0; i < emailElements.size(); i++) {
var emailElement = emailElements[i];
if (emailElement.up('form').id == conf.up('form').id) {
pass = emailElement;
}
}
if ($$('.[your class name]').size()) {
pass = $$('.validate-email')[0];
}
return (pass.value == conf.value);
}],
save it and upload it
Hope that helps somebody you has the same problem.
Above code is not working correctly following part is creating issue
if ($$('.[your class name]').size()) {
pass = $$('.validate-email')[0];
}
at my end following code is working
if ($$('.validate-admin-email').size()) {
pass = $$('.validate-admin-email')[0];
}
so the complete working code can be:
['validate-cemail', 'Please make sure your emails match.', function(v) {
var conf = $$('.validate-cemail')[0];
var pass = false;
if ($('email')) {
pass = $('email');
}
var emailElements = $$('.validate-email');
for (var i = 0; i < emailElements.size(); i++) {
var emailElement = emailElements[i];
if (emailElement.up('form').id == conf.up('form').id) {
pass = emailElement;
}
}
if ($$('.validate-admin-email').size()) {
pass = $$('.validate-admin-email')[0];
}
return (pass.value == conf.value);
}],
.validate-cemail is your defined class in template.
like:
<input type="text" name="email-confirm" id="email-confirm" class="input-text required-entry validate-cemail"/>

optimistic locking issue - rejectValue not working, bad domain being saved anyway

I've seen that others have had this problem, but I have yet to find a solution that works in my case. In my update method of my domain controller, I am trying to implement optimistic locking by checking version and using rejectValue(); however, I am clearly doing something wrong. I have verified that rejectValue() is being called, but it doesn't appear to work.
Also, the domain instance with bad data saves anyway. Any advice or help is appreciated. Here is my update method with the problem:
def update(Cohort cohortInstance) {
if (cohortInstance == null) {
notFound()
return
}
cohortInstance = Cohort.get(params.id)
if (cohortInstance == null) {
notFound()
return
}
if (params.version) {
def version = params.version.toLong()
if (cohortInstance.version > version) {
cohortInstance.errors.rejectValue("version", "default.optimistic.locking.failure",
[message(code: 'cohort.label', default: 'Cohort')] as Object[],
"Another user has updated this Cohort while you were editing")
render(view: "edit", model: [cohortInstance: cohortInstance])
return
}
}
// Bind browser data to this cohort Instance now that we've passed the concurrency check
cohortInstance.properties = params
if (cohortInstance.hasErrors()) {
respond cohortInstance.errors, view:'edit'
return
}
cohortInstance.save flush:true
request.withFormat {
form multipartForm {
flash.message = message(code: 'default.updated.message', args: [message(code: 'Cohort.label', default: 'Cohort'), cohortInstance.proposedCode])
redirect cohortInstance
}
'*'{ respond cohortInstance, [status: OK] }
}
}
In your update method definition (def update(Cohort cohortInstance) {}), you are initializing the instance of Cohort which is a new feature in grails 2.3.x, where grails automatically initializes the instance & do parameter binding for you .
Then again on line 4, you are getting the Cohort instance by using Cohort.get(params.id). So now you have two options: First is that, you can use read method instead of get and remove the auto initialization from the action signature or second is that, you can remove this line (cohortInstance = Cohort.get(params.id)) and add a Transactional annotation at update action like:
import grails.transaction.Transactional
#Transactional(readOnly = true)
def update(Cohort cohortInstance) {
...
}
Any of these work.

Uploading images with redactor to MVC

This might be a bit too specific for here and I may need to contact redactor support but i've seen other questions about redactor here so i figured i'd give it a shot ...
Ok ...
So i'm trying to get get image uploading to work following the example here ...
http://imperavi.com/redactor/docs/images/
My client side code ...
$("textarea").redactor({
focus: true,
imageUpload: '/MyController/UploadImage'
});
My MVC controller action looks like this ...
public JsonResult UploadImage(object image)
{
// Do something with whatever that was i got from redactor
var result = new { filelink = "" };
return Json(result);
}
The problem is ... what did redactor actually give me?
Was it the whole file? a chunk? i can't seem to tell because the object has no type information at all and the raw post information seems way too little to actually be a whole image file.
Has anyone had any experience with this / actually done it before?
I don't really want to setup php on my server for this 1 function.
EDIT:
Ok a bit more digging reveals that if i pull the underlying Request object it has a files property which apparently contains my posted image file.
I think i might be able to figure it out from here.
Where I get a code block in place i'll post it as an answer.
You are receiving a HttpPostedFileBase object. Here is my implementation:
jQuery:
$('#blog-post').redactor(
{
imageUpload: '/blog/images/',
imageGetJson: '/images/locations/blogs/'
});
Then in the controller:
public ActionResult Images(HttpPostedFileBase file)
{
// Verify that the user selected a file
if( file != null && file.ContentLength > 0 )
{
// extract only the fielname
var fileName = Path.GetFileName( file.FileName );
// store the file
var path = Path.Combine( ImageLocation.BlogPicturePath, fileName );
file.SaveAs( path );
}
return Json( new { filelink = ImageLocation.BlogPictureUrl + "/" + file.FileName } );
}
ok um ... i think im there ...
This needs a bit of cleaning up and I don't expect you guys to understand what goes on under the bonnet of my custom DMS code but just assume it takes the stream and returns a FileInfo object and in theory this should work for you too ...
public ActionResult Upload()
{
// this object is specific to my system but all it does is
// stream the file to a path on the server (code not needed for this Q)
var dmsService = _kernel.Get<IDMSFileSystemService>();
List<FileInfo> savedFiles = new List<FileInfo>();
for (int i = 0; i < Request.Files.Count; i++)
{
var file = Request.Files[i];
using (file.InputStream)
{
savedFiles.Add(dmsService.AddFromStream(file.InputStream, file.FileName);
}
}
var result = savedFiles.Select(f => new { filelink = f.Path}).ToArray();
return Json(result);
}
Suprisingly simple right ... :)

Grails - beforeInsert throwing exception null id in entry

I am trying to use beforeInsert in my user domain class.
class User {
String reEnterPassword
static constraints = {
password(blank: false, nullable: false, size:5..50, validator: {password, obj ->
def reEnterPassword = obj.properties['reEnterPassword']
if(reEnterPassword == null) return true
reEnterPassword == password ? true : ['invalid.matchingpasswords']
})
reEnterPassword(bindable:true, blank: false);
}
def beforeInsert = {
password = password.encodeAsSHA()
}
String toString(){
name
}
static transients = ['reEnterPassword']
}
in my controller i have save method ( generated)
def save() {
def userInstance = new User(params)
if (!`userInstance.save(flush: true)`) {
render(view: "create", model: [userInstance: userInstance])
return
}
This is throwing exception
Grails runtime exception, org.hibernate.AssertionFailure: null id in entry (don't flush the Session after an exception occurs), when domain objects save method encounters a SQL Exception
I read in the documentation for auto timestamping that
Do not attempt to flush the session within an event (such as with obj.save(flush:true)). Since events are fired during flushing this will cause a StackOverflowError.
In this case how to save my userInstance.save(flush: true) I tried to remove flush:true but still i am getting same error. if i remove flus:true..then when i need to call. When hibenate will flush all these records.
I tried the solution defined this JIRA ticket
Please help me out. Thank you
Can it be that you have other validation errors?
If you put your code in the beforeValidate method it will work:
def beforeValidate = {
password = password.encodeAsSHA()
}
I guess I'm too late to help you, but I hope it helps others with the same issue.
Greetings, Urs
Change your
def beforeInsert = {
password = password.encodeAsSHA()
}
to
def beforeInsert() {
password = password.encodeAsSHA()
}
and that should do the trick
I believe if the beforeInsert method return false then you get the "null id in entry" exception. Perhaps this is treated as an indication that validation has failed.
e.g. the following will cause the exception
def beforeInsert() {
flag = false
}
however the following should work OK
def beforeInsert() {
flag = false
return true
}

Resources