Say we have a entity called Timesheet. For simplicity, let's assume the Timesheet entity has three properties (TimesheetID, Status and Hours).
We currently allows the owners of Timesheet objects to submit their Timesheets via this end point -
POST: /Users/{UserID}/Timesheets/{TimesheetID}
With {UserID} currently is the owner of the Timesheet object. With {TimesheetID} I can also trace back the owner of the Timesheet in the database.
OK, now here is the question -
Now we'd like to have their managers to be able to update the Timesheet objects of the employees to that report to them (such as approve/reject Timesheets by changing the Status, or override Hours).
However, there are different levels of Manager Permissions. Some managers are only allow to update Status and some of them are allowed to update both Status and Hours.
Should I reuse the existing end point for both regular user submissions and managers update (I prefer)? Or should I create a different end point for each of the "Manager Level"?
If I hope to reuse the existing end point for all user submissions and manager updates, how do I handle the errors such as if a manager is configured to only update the Status, but the TimeSheet object posted to the REST service has both Status and Hours changed. Should I respond with a 403 with a detailed error description to tell the Manager that you can't change the Hours property or update the Status and ignore Hours?
If you're following the HATEOAS constraint, then a GET on the Timesheet resource will provide the hypermedia controls (links and forms) that can currently be used to interact with it. While this can be done a number of ways, the one that provides the lowest form of coupling, will include in the form they valid parameters.
For your example, I would include two manager forms with the same endpoint /Users/{UserID}/Timesheets/{TimesheetID}. The first one would have a status as a required field, the second one would have status (status could be optional) and hours (hours would be required).
You could then either have the second form respond with 403 Forbidden if the submitter is not permitted to submit hours. Or alternatively, you could filter the forms included in the GET, so that only the forms the user is permitted to submit are shown.
Update
For example and GET on /Users/1234/Timesheets/24 might currently produce
<Timesheet>
<TimesheetID>24</TimesheetID>
<Status>Submitted</Status>
<Hours>40</Hours>
</Timesheet>
To apply the HATEOAS constraint, we need to add the hypermedia controls. We'll ignore the URLs for the moment, because they are implementation details. This might give us something like
<Timesheet>
<TimesheetID>24</TimesheetID>
<Status>Submitted</Status>
<Hours>40</Hours>
<link rel="self" href="{{selfUrl}}"/>
<form id="approve" action="{{approveUrl}}" method="PUT">
<Status cardinality="required">
<option value="Approve"/>
</Status>
</form>
<form id="reject" action="{{rejectUrl}}" method="PUT">
<Status cardinality="required">
<option value="Reject"/>
</Status>
</form>
<form id="update" action="{{updateUrl}}" method="PUT">
<Status cardinality="required">
<option value="Approve"/>
<option value="Reject"/>
</Status>
<Hours type="decimal" cardinality="required"/>
</form>
... there might be other forms too, like ...
<form id="cancel" action="{{cancelUrl}}" method="DELETE"/>
</Timesheet>
What the forms do (and how to recognise a form) are what get's documented in the media type. For instance:
The cancel form on a Timesheet resource will cancel the timesheet, updating it's status to "Cancelled". Once a Timesheet has been cancelled, it will no longer be possible to update approve or reject the timesheet.
Also in the media type you would document the properties of the resources. e.g.,
The Timesheet resource has a the following properties:
TimesheetID A unique identifier for the timesheet
Status The current status of the timesheet. Status may include
Submitted The timesheet has been submitted, but not approved
Approved The timesheet has been approved
Rejected The timesheet has been rejected
Cancelled The timesheet has been cancelled
Hours The number of hours (decimal) recorded for the timesheet
While this could be specified by a schema, this should be avoided as doing so can may it very difficult to extent the resources later on. For instance, you might decide to add a "WeekEnding" date property. Existing callers should not care about the new property, which is fine if they are just plucking out the data they are interested in. However, if you've specified the schema without thoughts of extension, then adding properties can cause validation errors in the callers when you add properties.
Now, in terms of who can do what we have a couple of options. One option is to just include all the controls and respond with 403 for any requests made that the caller is not authorised to invoke. Another option is to filter the controls, so they can only see the ones they can invoke. e.g. for the manager that can approve/reject, they might get the following response
<Timesheet>
<TimesheetID>24</TimesheetID>
<Status>Submitted</Status>
<Hours>40</Hours>
<link rel="self" href="{{selfUrl}}"/>
<form id="approve" action="{{approveUrl}}" method="PUT">
<Status cardinality="required">
<option value="Approve"/>
</Status>
</form>
<form id="reject" action="{{rejectUrl}}" method="PUT">
<Status cardinality="required">
<option value="Reject"/>
</Status>
</form>
</Timesheet>
Whereas a manager that can update the hours might get
<Timesheet>
<TimesheetID>24</TimesheetID>
<Status>Submitted</Status>
<Hours>40</Hours>
<link rel="self" href="{{selfUrl}}"/>
<form id="approve" action="{{approveUrl}}" method="PUT">
<Status cardinality="required">
<option value="Approve"/>
</Status>
</form>
<form id="reject" action="{{rejectUrl}}" method="PUT">
<Status cardinality="required">
<option value="Reject"/>
</Status>
</form>
<form id="update" action="{{updateUrl}}" method="PUT">
<Status cardinality="required">
<option value="Approve"/>
<option value="Reject"/>
</Status>
<Hours type="decimal" cardinality="required"/>
</form>
</Timesheet>
Alternatively, you can include all the forms for all the users, but add an indicator that they are not authorised to invoke it. e.g. for the manager that can't update hours:
<Timesheet>
<TimesheetID>24</TimesheetID>
<Status>Submitted</Status>
<Hours>40</Hours>
<link rel="self" href="{{selfUrl}}"/>
<form id="approve" action="{{approveUrl}}" method="PUT">
<Status cardinality="required">
<option value="Approve"/>
</Status>
</form>
<form id="reject" action="{{rejectUrl}}" method="PUT">
<Status cardinality="required">
<option value="Reject"/>
</Status>
</form>
<form id="update" action="{{updateUrl}}" method="PUT" authorised="false">
<Status cardinality="required">
<option value="Approve"/>
<option value="Reject"/>
</Status>
<Hours type="decimal" cardinality="required"/>
</form>
</Timesheet>
I prefer this later approach as you don't end up with support calls for your API, with developers complaining that a particular form doesn't exist. Either way (included or filtered), if the caller invokes a form they are not permitted to, you would still respond with 403.
A bit off topic, but for completeness, HATEOAS really comes to the fore because it communicates the valid set of hypermedia controls based on the current state of the resource. e.g., when a Timesheet has been cancelled, it's not longer valid to approve/reject or update it, so a GET on a cancelled Timesheet might return
<Timesheet>
<TimesheetID>24</TimesheetID>
<Status>Cancelled</Status>
<Hours>40</Hours>
<link rel="self" href="{{selfUrl}}"/>
</Timesheet>
This clearly communicates to the caller that no further actions are permitted on this particular Timesheet.
The other thing you'll have noticed is that we haven't actually specified any or the URLs yet. They might all be all the same (e.g. /Users/{UserID}/Timesheets/{TimesheetID}) or they might be different (e.g. selfUrl=/Users/{UserID}/Timesheets/{TimesheetID}, updateURL=/Users/{UserID}/Timesheets/{TimesheetID}/update, etc).
Ultimately the caller should not care as it will use whatever is in the form/link. This provides you with great flexibility as you can change these to suit your implementation needs. For instance, if you are using Command Query Responsibility Segregation (CQRS), it might make sense to send GET requests to //readonly.myserver.com/Users/{UserID}/Timesheets/{TimesheetID} and POST, PUT and DELETE requests to //readwrite.myserver.com/Users/{UserID}/Timesheets/{TimesheetID}.
Yes, go with 403 Forbidden. I matches the scenario you describe. RFC 7231 says:
The 403 (Forbidden) status code indicates that the server understood
the request but refuses to authorize it. A server that wishes to
make public why the request has been forbidden can describe that
reason in the response payload (if any).
As an alternative, the server could perform those actions the current user is allowed to and ignore everything else. If this is a good idea depends on your scenarion. I woul prefer to deny the whole request and return 403 Forbidden.
1) You use POST to create, so you can use PUT on the same endpoint to update the data (providing the new data in the content of the request). To limit/log who updates the data you can pass their user/manager ID as a query parameter, or inside the body
2) 403 Forbidden sound better so that it's more clear for the user(manager) what has happened instead of letting him think the data was updated correctly but it was only partially updated actually
Related
We have website developers redesigning the whole site in Django, and these are questions from our website developers I don't have any real knowledge of how to answer, so I thought someone here might be able to help.
We ran into a few problems with the web to lead and having it map to Salesforce which I HOPE we resolved.
Here's the code snippet:
<!-- ---------------------------------------------------------------------- -->
<!-- NOTE: Please add the following <META> element to your page <HEAD>. -->
<!-- If necessary, please modify the charset parameter to specify the -->
<!-- character set of your HTML page. -->
<!-- ---------------------------------------------------------------------- -->
<META HTTP-EQUIV="Content-type" CONTENT="text/html; charset=UTF-8">
<!-- ---------------------------------------------------------------------- -->
<!-- NOTE: Please add the following <FORM> element to your page. -->
<!-- ---------------------------------------------------------------------- -->
<form action="https://www.salesforce.com/servlet/servlet.WebToLead?encoding=UTF-8" method="POST">
<input type=hidden name="oid" value="SFDCidhere">
<input type=hidden name="retURL" value="http://">
<!-- ---------------------------------------------------------------------- -->
<!-- NOTE: These fields are optional debugging elements. Please uncomment -->
<!-- these lines if you wish to test in debug mode. -->
<!-- <input type="hidden" name="debug" value=1> -->
<!-- <input type="hidden" name="debugEmail" -->
<!-- value="emailaddresshere"> -->
<!-- ---------------------------------------------------------------------- -->
<label for="first_name">First Name</label><input id="first_name" maxlength="40" name="first_name" size="20" type="text" /><br>
<label for="last_name">Last Name</label><input id="last_name" maxlength="80" name="last_name" size="20" type="text" /><br>
<label for="email">Email</label><input id="email" maxlength="80" name="email" size="20" type="text" /><br>
<label for="company">Company</label><input id="company" maxlength="40" name="company" size="20" type="text" /><br>
<label for="phone">Phone</label><input id="phone" maxlength="40" name="phone" size="20" type="text" /><br>
Subject:<textarea id="00N1600000EgFuw" name="00N1600000EgFuw" rows="3" type="text" wrap="soft"></textarea><br>
Contact me:<input id="00N1600000EvgRY" name="00N1600000EvgRY" type="checkbox" value="1" /><br>
newsletter:<input id="00N1600000EvgRd" name="00N1600000EvgRd" type="checkbox" value="1" /><br>
<input type="submit" name="submit">
</form>
That's what the web-to-lead from SFDC generates, and seems to work now.
However they have 2 questions I am not certain about and would love assistance with:
1) The specs for the new site require that the return page be the one the form was sent from (I.e., no redirection; we’re intending to do the equivalent of a “thanks” page as a pop-up onClick() — how is that accomplished through the API? I’d EXPECT that sending an empty retURL value should do it, but we just get back a blank page with a salesforce.com URL;
2) is it possible to customize the “name” parameter for the two checkbox fields (if not then we have to hack the entire form in the Django template without making it possible for Django to render the form natively since you can’t have a model form field name start with a digit…). This isn’t THAT problematic, but I’d like to know for future reference.
If anyone has any insight, I'd love to hear it and pass it along to them!
Many thanks.
Not sure your solution.
The common way that you could using the Partner WSDL or Enterprise WSDL to insert,update,upsert ,delete your data
Parnter WSDL:
not custom from your salesforce org, but it could be common way to get your data.
In python your could use this package
https://pypi.python.org/pypi/pyforce/1.4
And reference by this
https://developer.salesforce.com/docs/atlas.en-us.api.meta/api/sforce_api_partner.htm
Enterprise WSDL will show your salesforce org status (including field and object) . But one your objects or fields are changing that it might be error.
So i suggest using api to control the redirect function and the action.
My solution is as follows in an example
from captcha.fields import ReCaptchaField
from django.conf import settings
def set_field_html_name(cls, new_name):
"""
This creates wrapper around the normal widget rendering,
allowing for a custom field name (new_name).
"""
old_render = cls.widget.render
def _widget_render_wrapper(name, value, attrs=None):
return old_render(new_name, value, attrs)
cls.widget.render = _widget_render_wrapper
class WebToLeadForm(forms.Form):
# <keep all fields here>
# example field below
referred_by = forms.CharField(label="Referred By", required=False)
# The reCAPTCHA in this form uses keys from settings.
captcha = ReCaptchaField()
set_field_html_name(referred_by, settings.SF_REFERRED_BY)
settings.py
SF_REFERRED_BY = '00xxxxxxxxxxxx'
How can i create a html form that action attribute have 2 destination.I want when user click on submit bottom , check if user entered wrong data the page goes to another pages with window.location and if user insert the correct input goes to main page with the same instruction.
First of all, what do you mean by correct input?
Main form data validation occurs in server side, not client side. you'd better use client side just for simple verification, like for typos.
There is no need for 2 destination pages (as you call it so).
You may use the standard action attribute which is the page on the server to which you are sending your form data.
there, You have the option to decide which condition needs what action and send the data (and then the user) to the desired page / action.
Sample code for the form
<form id='myform' action='action.php' method='POST' target='formresponse'>
<label for='name' >Your Full Name*: </label><br/>
<input type='text' name='name' id='name' maxlength="50" /><br/>
<label for='email' >Email Address*:</label><br/>
<input type='text' name='email' id='email' maxlength="50" /><br/>
<input type='button' name='Submit' value='Submit' />
</form>
<iframe name='formresponse' width='300' height='200'></frame>
Multiple action
function SubmitForm()
{
document.forms['contactus'].action='action1.php';
document.forms['contactus'].target='frame_result1';
document.forms['contactus'].submit();
document.forms['contactus'].action='action2.php';
document.forms['contactus'].target='frame_result2';
document.forms['contactus'].submit();
return true;
}
I added a PayPal Donate button on my site, with that code
<form action="https://www.paypal.com/cgi-bin/webscr" method="post">
<input type="hidden" name="business" value="pro-email#gmail.com">
<input type="hidden" name="cmd" value="_donations">
<input type="hidden" name="item_name" value="Donation">
<input type="hidden" name="item_number" value="Donation">
<select name="amount"><option value="2.00">$2.00</option><option value="5.00">$5.00</option><option value="10.00">$10.00</option></select>
<input type="hidden" name="currency_code" value="EUR">
<input type="image" name="submit" border="0" src="https://www.paypal.com/en_US/i/btn/btn_donate_LG.gif" alt="PayPal - The safer, easier way to pay online">
</form>
I want add and show Donators names or emails with the $$ amount on list on my website after then when someone pays. How can i do this?
I would set something like up using PayPal Instant Payment Notification (IPN).
It will automatically POST data about transactions to a listener script you have on your server. That script can receive the data and load it into a database table called "donors" or whatever you want to call it.
Then on your site you can simply pull the data from the donors table and display it accordingly.
Since you're using WordPress I'd recommend taking a look at this PayPal IPN for WordPress plugin. It's free and it will get you up and running with IPN very quickly. It logs all of the IPN data in WordPress and allows you to easily extend the plugin using a number of hooks to trigger events based on different IPN types or payment status.
One of my table is saving an HTML form which contains ColdFusion variables. In my code I am querying this table and need to display this form in the front end. But while displaying I am getting the ColdFusion variable names instead of the values of the variables.
HTML Form saved in the db table:
<form action="" name="ci_entry_form" id="ci_entry_form" method="post">
<table width="100%" height="100%" border="0">
<tr>
<td align="right"><b style="color:red">*</b> <label class="pop_up_letter_font">G/L # :</label></td>
<td> <input class="pop_up_textbox" type="text" name="gl_number_text" id="gl_number_text" maxlength="21" value="#ARGUMENTS.chkDetails.GL_ACCT_NBR#" required/>
<select class="pop_up_dd" name="gl_number_drop" id="gl_number_drop" onChange="enableDisableGL()">
<option value="">---Select---</option>
<option value="new">Enter a new G/L number</option>
<cfoutput query="glNumbers">
<option value="#glNumbers.GL_ACCT_NBR#">#glNumbers.GL_ACCT_NBR#</option>
</cfoutput>
</select>
</td>
</tr>
</table>
</form>
Method (cffunction) contains below code to query this html form from db table and return the html form.
<cfquery name="qry_getTemplate" datasource="#APPLICATION.dsn#">
select FORM_TXT from HTML_FORMS where REQ_ID = 172
</cfquery>
<cfsavecontent variable="form_content">
<cfoutput>#qry_getTemplate.FORM_TXT #</cfoutput>
</cfsavecontent>
But when I dump the cfcontent variable form_content I am getting the HTML Form without processing the coldfusion variables #ARGUMENTS.chkDetails.GL_ACCT_NBR#, #glNumbers.GL_ACCT_NBR#.
Am I missing something? Can any one help me out resolve this?
I'm pretty sure if you searched this site or via Google a bit you could have found the answer to this already posted somewhere, given it comes up all the time (about once every 3-4 months).
You can't output CFML and somehow hope that it will execute.
I've summarised the CFML request / compile / response process on my blog: "The ColdFusion request/response process".
Bottom line: CFML source code needs to be loaded from the file system at compile time not at runtime. So your code needs to be in the file system when you want it to execute, not in the DB or in a variable.
You can write the code to file and then include it, though. This is detailed in that blog article.
The following piece of code in my JSP caused a cross site scripting vulnerability on the input tag.
<form name="acctFrm" method="post" action="<%=contextPath%>/form/acctSummary?rpt_nm=FIMM_ACCT_SUMM_RPT">
<table>
<tr>
<td>Account Id:</td>
<td>
<input class="tbl1" type="text" id="acctId" name="acctId" size="20" maxlength="10" value="<%=rptBean.getAcctId()%>"/>
<img class="tbl1" src="<%=contextPath%>/img/Submit.gif" border="0" />
</td>
</tr>
</table>
</form>
During Penetration testing they were able to alert some random message to the user by injecting a alert script in the value attribute of the tag as follows
<input class="tbl1" type="text" id="acctId" name="acctId" size="20" maxlength="10" value="1"><script>alert(12345)</script>" />
What is the problem here, and what would be the fix.
I was reading through some online references on XSS still I wasnt 100% sure on what could be the issue.
Any help would be greatly appreciated.
Thanks,
Deena
I have used the following solution,
The scriplet in the value attribute is the problem, I replaced it with jstl tag, I read somewhere that jstl tags have inbuild escaping mechanism to avoid xss issues.
<input class="tbl1" type="text" id="acctId" name="acctId" size="20" maxlength="10" value="<c:out value=${rptBean.acctId}"/>"/>
This works good for my issue.
Thanks
It seems the penetration testers were able to manipulate their session such that rptBean.getAcctId() would return an arbitrary string. If they could inject quotes and a right bracket, they could "force close" the input tag and insert their own script tag.
It looks like penetration testers got the method to return the string 1"><script>alert(12345)</script>.
This indicates that you need to escape the data when writing to the page. I would suggest taking a look at the answer on escaping HTML in jsp.
Also, remember that code does not have to be "perfectly" formatted for a browser to render it "correctly". Here are some links on how attackers may try evade XSS filters:
http://blog.whitehatsec.com/tag/filter-evasion/
http://ha.ckers.org/xss.html
Always treat user data as "dangerous" and take care when rendering it on a page.
It seems using jstl tag <c:out value=""> in value attribute will cause errors in jstl <form options> tags,
more info
XSS prevention in JSP/Servlet web application
if getAcctId() returned data come from DB you can filter before sending to client. for example check is data should be a number.