How to authorize POST form upload in Ktor? - kotlin

I want to create a simple form where user enters some string (key that authorizes them to upload a file) and the file they want to upload (no size limit, can be even 10GB or more).
The problem I have is that I don't know how to verify the code BEFORE accepting the file.
So far I have this code that disallows any upload even with a valid code since the uploaded file seems to be always the first form element to be checked.
(when I reversed the order of elements in the form this code didn't handle the request at all)
var isAuth = false
multipart.forEachPart { part ->
when (part) {
is PartData.FormItem -> {
val name = part.name
if(name != null && name == "key")
isAuth = isKeyValid(part.value)
}
is PartData.FileItem -> {
if(!isAuth) {
call.respond("Request not authorized")
call.response.status(HttpStatusCode.Forbidden)
part.dispose
return#forEachPart
}
if(part.originalFileName.isNullOrEmpty() || part.originalFileName!!.isBlank()) {
call.respond("Illegal filename")
call.response.status(HttpStatusCode.BadRequest)
return#forEachPart
}
val targetDir = File(uploadDir.path + File.separator + randomId)
targetDir.mkdir()
val targetFile = File(targetDir.path + File.separator + part.originalFileName)
targetFile.createNewFile()
sb.append(randomId)
sb.append("/")
sb.append(part.originalFileName)
sb.append("\n")
part.streamProvider().use { input -> targetFile.outputStream().buffered().use { output -> input.copyToSuspend(output) } }
}
}
part.dispose
}
HTML form I'm using:
<html>
<body>
<form action="/upload" method="POST" enctype="multipart/form-data">
<input type="file" name="file">
<input type="text" name="key">
<input type="submit" value="upload" name="submit">
</form>
</body>
</html>

Add Authentication feature
implementation "io.ktor:ktor-auth:$ktor_version"
Install the feature
install(Authentication) { //set type of authenction here }
Wrap your call in authenticate {} block
authenticate("auth") {
post(FORM) {
}
}
More Info: Ktor Authentication

Related

Salesforce Marketing Cloud code resource can't process an XHR request from an amp-form component

I am using an amp-form inside a dynamic mail and want it to send some data to a code resource sitting on a Salesforce Marketing Cloud org. The request seems to be fine, but it never reaches the code resource. There is always the same error saying that the "Access-Control-Allow-Origin" header is missing. The content of the code resource is taken straight from the AMP documentation on CORS.
Code Resource
<script runat="server" executioncontexttype="post" executioncontextname=corsinampforemail>
Platform.Load("core", "1");
if (Platform.Request.GetRequestHeader("AMP-Email-Sender")) {
var senderEmail = Platform.Request.GetRequestHeader("AMP-Email-Sender")
if (isValidSender(senderEmail)) {
HTTPHeader.SetValue("AMP-Email-Allow-Sender", senderEmail)
} else {
Platform.Function.RaiseError("Sender Not Allowed",true,"statusCode","3");
}
} else if (Platform.Request.GetRequestHeader("Origin")) {
var requestOrigin = Platform.Request.GetRequestHeader("Origin")
if (Platform.Request.GetQueryStringParameter("__amp_source_origin")) {
var senderEmail = Platform.Request.GetQueryStringParameter("__amp_source_origin");
if (isValidSender(senderEmail)) {
HTTPHeader.SetValue("Access-Control-Allow-Origin", requestOrigin);
HTTPHeader.SetValue("Access-Control-Expose-Headers", "AMP-Access-Control-Allow-Source-Origin");
HTTPHeader.SetValue("AMP-Access-Control-Allow-Source-Origin", senderEmail);
} else {
Platform.Function.RaiseError("Invalid Source Origin",true,"statusCode","3");
}
} else {
Platform.Function.RaiseError("Source Origin Not Present",true,"statusCode","3");
}
} else {
Platform.Function.RaiseError("Origin and Sender Not Present",true,"statusCode","3");
}
</script>
amp-form
<form id="test-form" method="post"
action-xhr="https://.../..."
enctype="multipart/form-data">
<input type="submit" value="Submit">
<div submit-success>
<span>Submit successful</span>
</div>
<div submitting>
<span>Submitting...</span>
</div>
<div submit-error>
<span>Error</span>
</div>
</form>
Does anyone know what the problem is here?

Image upload for multiple fields Angular 5

I have a scenario where i have to create multiple file upload fields dynamically using reactive forms with form array and upload multiple image for that particular field in angular 5 or angular reactive forms and the image needs to be displayed parallel to that form field name .
Please help with me with any sample code in stack blitz or from any links. Also
thanks.
You can do the file upload part using formData.
const formData: FormData = new FormData();
formData.append('file1', file1, file1.name);
formData.append('file2', file2, file2);
this.http.post(url, formData);
And using the change event in the
<input type="file" (chnage)="onChange($event)"> you can get the image source of the file you select.
Here
public fileList: FileList;
public imageUrls: any[];
public files: any[];
public onChange(event) {
if (event.target.files.length === 0) {
return;
}
this.fileList = event.target.files;
for (let i = 0; i < this.fileList.length; i++) {
const file = this.fileList[i];
if (!file.type.match('image')) {
continue;
}
this.files.push(file);
const picReader = new FileReader();
picReader.onload = (e: any) => {
const picFile = e.target;
this.imageUrls.push(picFile.result);
};
picReader.readAsDataURL(file);
}
}
And in the template
<input type="file"
(change)="onChange($event)"
placeholder="Upload file"
accept="image/*" multiple>
<p>(You may choose more than one file to upload.)</p>
<ng-container *ngFor="let item of imageUrls; let i = index">
<img [src]="item" height="100" class="img-thumbnail">
</ng-container>
This is just a idea. Just give it a try.

Passing value from textbox to http adapter failed mobilefirst platform

I'm trying to pass some values from a textbox to an http adapter and it have the following error:
Here is the index.html
Username:<br>
<input type="text" name="username" id="username"><br>
Password:<br>
<input type="text" name="password" id="password"><br>
<button onclick="mobgetVerify()">Login</button>
<p>
<p id="demo"></p> <br />
<br />
<br />
mains.js
function mobgetVerify() {
alert("Hi" + $('#username').val() + $('#password').val());
var invocationData = {
adapter : 'LoginAdapter',
procedure : 'getVerify',
parameters : [ $('#username').val() , $('#password').val() ]
};
WL.Client.invokeProcedure(invocationData, {
onSuccess : getVerifySuccess,
onFailure : getVerifyFailure,
});
};
function getVerifySuccess(res) {
var httpStatusCode = res.status;
if (200 == httpStatusCode) {
var invocationResult = res.invocationResult;
var isSuccessful = invocationResult.isSuccessful;
if (true == isSuccessful) {
$("#demo").html(JSON.stringify(res.responseJSON.data));
if (res.responseJSON.data== "True "){
window.location="pages/view.html";
}
alert("Success: Value= " + res.responseJSON.data);
} else {
alert("Error. isSuccessful=" + isSuccessful);
}
} else {
alert("Error. httpStatusCode=" + httpStatusCode);
}
};
function getVerifyFailure(result){
alert("Verification Failure");
};
I would highly appreciate if i can get some help. Thank you.
The provided sample application worked just fine... I received an alert dialog with the text: "Success: Value=False".
The only difference I can think of, which relates every time in each of your questions... if the IP address. In your provided LogCat, it shows the server's IP address is "10.0.0.3", whereas mine is my actual IP address (9.148.x.y in my case).
As you were previously advised - use the correct IP address of the server in wlclient.properties.
To check for mine, I typed the following in Terminal: ifconfig (in Windows - "ipconfig").

Prestashop: display "Choose language" inline in admin

I wanna simplify my life and display language flags inline next to input fields in admin panel.
Example:
Turn this:
into this:
I tried override
abstract class ModuleCore { public function displayFlags() }
but no effect.
Then I modify admin\themes\default\template\helpers\options\options.tpl to:
<div class="displayed_flag">
{foreach $languages as $language}
<img src="../img/l/{$language.id_lang}.jpg"
class="pointer"
alt="{$language.name}"
title="{$language.name}"
onclick="changeLanguage('{$key}', '{if isset($custom_key)}{$custom_key}{else}{$key}{/if}', {$language.id_lang}, '{$language.iso_code}');" />
{/foreach}
</div>
But still nothing.
Of course I deleted class_index.php, clear cache etc...
I am using Prestashop 1.5.5 and default theme.
You're searching for the displayFlags function inside /js/admin.js file.
Here it works on my installation with this changes:
function displayFlags(languages, defaultLanguageID, employee_cookie)
{
if ($('.translatable'))
{
$('.translatable').each(function() {
if (!$(this).find('.displayed_flag').length > 0) {
$.each(languages, function(key, language) {
if (language['id_lang'] == defaultLanguageID)
{
defaultLanguage = language;
return false;
}
});
var displayFlags = $('<div></div>')
.addClass('displayed_flag');
$.each(languages, function(key, language) {
var img = $('<img>')
.addClass('pointer')
.css('margin', '0 2px')
.attr('src', '../img/l/' + language['id_lang'] + '.jpg')
.attr('alt', language['name'])
.click(function() {
changeFormLanguage(language['id_lang'], language['iso_code'], employee_cookie);
});
displayFlags.append(img);
});
if ($(this).find('p:last-child').hasClass('clear'))
$(this).find('p:last-child').before(displayFlags);
else
$(this).append(displayFlags);
}
});
}
}

jQuery Form plugin submit several forms but wait until previous has ended

Users are abled to add new forms which are all submited with one button click and "jQuery Form plugin". To submit each form I iterate over forms which have a certain class.
As the users can submit images and the server has to do some work with each Image I´d like to wait until the previous submit has finished with a success statusText. Currently (I just do a timeout of 2000 which is nothing more than a "hackish" solution.)
I think I can use success function for this but do not know how I connect my submit loop with the returned success statusText. Here is a fiddle.
Here what I have:
var userform = '<form class="myForm" action="up.php" method="post"> ' +
'Name: <input type="text" name="name" />' +
'file: <input type="file" name="img[]" multiple />' +
'Comment: <textarea name="comment"></textarea>' +
'<input type="submit" value="Submit Comment" />' +
'</form>';
function showResponse(responseText, statusText, xhr, form) {
if (statusText === "success") {
console.log("the submit ended with success");
//submit next form should happen
}
}
var options = {
success: showResponse
};
$('#add').click(function() {
$(userform).appendTo('.append').each(function() {
$('.myForm').ajaxForm(options);
});
});
$("#all").click(function() {
var collection = $('.myForm');
if (collection.length > 0) {
var i = 0;
var fn = function() {
var element = $(collection[i]);
$(element).submit().addClass('done').hide("slow");
if (++i < collection.length) {
setTimeout(fn, 2000);
}
};
fn();
}
});
Thanks!
The submit handler simply does a std POST/GET so you aren't going to get a response back. You are going to want to change your code to use ajax and then have the server return a response of success = true/false or whatever you prefer
https://jsfiddle.net/mj9dbLh1/3/
Change this...
var element = $(collection[i]);
$(element).submit().addClass('done').hide("slow");
if (++i < collection.length) {
setTimeout(fn, 2000);
}
To something like...
var element = $(collection[i]);
$(element).addClass('done').hide("slow");
$.post("ajax/test.html", function( data ) {
fn(); // DO SUCCESS ACTION HERE
});
Keep in mind this will execute on each success SO you may want to first get a count of the number of forms (which gives you the number of ajax calls). Then increment that count for each success action. Once you get your total you can Display ALL SUCCESS.
Take a look at these docs for more clues on how to handle errors and what not.
http://api.jquery.com/jquery.post/