RESTful way of performing validation - web-services

Having worked on SOAP RPC interfaces I'm struggling with how to approach things in a way which fits the RESTful design pattern.
For example. If we have a registration wizard for a new customer which has 3 pages.
The first page for name/DOB
The second page for Address
The third page for other stuff
A final summary page from where the customer completes the registration
The Post of the new customer would be performed from the final summary page so that's obvious, but how would you recommend performing validation of the data entered on each of the pages.
The data on page 1 isn't a customer resource, it's a partial customer resource which requires validation against some server-side business rules (DOB and unique username for example - or something else not easily implemented in JavaScript client validation).
The result of a validation failure may be to offer alternative usernames, so not just a 200/400 status code response.
An RPC design would be a call to a ValidatePage1 method.
But this is thinking of the action 'Validate' on data item and I'm trying to think from a resources and results of an action.
Is it bad design for an API to have REST and RPC type calls, or are there times when this approach is valid when dealing with validation 'actions' which really are actions and not resource posts/gets etc. ValidateDOB, ValidateAge, ValidateAddress etc.

For example. If we have a registration wizard for a new customer which has 3 pages.
The first page for name/DOB The second page for Address The third page for other stuff A final summary page from where the customer completes the registration
If you were to do this as HTML, the protocol would probably look something like this -- you would use a bookmark to find a resource, which would deliver to you a representation of the blank form.
You would fill in the form, submit it; the browser would look at the controls on the form to discover the target resource of the form, construct a representation of your form data, and dispatch that representation to the server. The server would validate your inputs, and either return you (a) a representation of the application state with the errors illustrated, or (b) a representation of the application state with the valid fields locked and a new form to collect the next page of data. The hyperlinks in this new representation might go to the same place as the previous form, or it might go somewhere else.
At some point you deliver a representation of the form with the data complete and valid, and that takes you to some new application state where you don't have to fill out these forms anymore.
If you do that, you've got REST.
What about the status codes? Well, each time the form is submitted, the resource is responding with a representation of a new application state, so it's completely appropriate to respond with 200 (OK), even in the cases where the validation failed and we are sending the work back to the user for a do-over.
Notice, that this design doesn't depend at all on:
What identifiers you use for your resources
Whether the resources involved map to entities in your domain model
Whether the resources involved in form validation mutate your domain state

Related

How to encrypt or Obfuscate REST API URL in Django

Hello Django REST API Experts,
We are building University Course portals where app offers various user types like Professor, Students and Admins using DJANGO/REACT. We are using REST API to connect between backend and frontend.
So, far we are able to perform some basic operation and it really works great. However now I need help from this group to do following:
When students enrolled in course it generates an acknowledge document stating course description, and its prerequisite which needs to get signed by students to ensure student acknowledge they fulfill these requirements.
In order to do this we have following:
Model for each course which contains the Content, Description and Prerequisite for each course.
StudentCourseAck Model which has FK to Course, Signed Boolean field, Binary field to store signed doc.
User flow:
Student logins to portal,
Select the Course, which generate StudentCourseAck entry.
Let Student review document and signed the document (on client side using sign pad).
The Signature gets stored in PDF (as binary field).
So far so good…
Now we want to enhance the featureset which allows admin to email student the link of studentcouseack document incase its not signed before course start. Also this link should only be valid for 48 hours or else it will expire.
So we need some help to enhance these featuresets as follow:
Current the API is exposed to frontend like: mysite.com/courseack/studentid/documentid
However we want to encrypt this so the link look like this: mysite.com/uniqueid
Where uniquid is mapped to /studentid/documented
So I have following design question:
Question 1: Should we enhance StudentCourseAck which store the UUID for each document?
Question 2: If I store UUID for each document, how do I make it expire once its generated?
Question 3: When Student is finished signing, I need to update the document into database to ensure that right document is saved to right student profile, so how can I ensure this security requirement.
I would really appreciate some expert opinion or some guidance so we can proceed this feature implementation. Any other alternative which is simpler and easier to maintain.
Once again thank you for your time and consideration.
Thank You.
Any other alternative which is simpler and easier to maintain.
Keeping the above phrase in mind I propose this solution.
Firstly I will not consider this as a DRF problem but as a general problem and proceed to answer your Questions.
The simple solution lies in 4 steps
Create a UUID field inside StudentCourseACK so that you can map this uuid with your url mysite.com/uniqueid, catch the document id inside the StudentCourseACK record as a foreign key and also create a created_at inside the model (this will be required for expiry timer)
Make a view inside your views.py that takes this StudentCourseACK UUID as a url parameter where you will have to fetch courseack, studentid and documentid from this StudentCourseACK mapping table and redirects it to mysite.com/courseack/studentid/documentid. When you link this view with your url pattern make sure the listing is at the very bottom.
To make an expiry timer you can check the created_at date in your StudentCourseAck record for 48hours limit before redirecting inside Step 2
Finally when the student is redirected to the mysite.com/courseack/studentid/documentid endpoint you will have to follow a simple process of getting the StudentCourseAck data via .filter(studentid="some value", documentid="somevalue") and make changes to this data accordingly.
Another thing that I realise is that you can completely ditch the long mysite.com/courseack/studentid/documentid url and correspond it's logic inside the new view, but I assume that you want to keep it that way.

How should I structure requests with side effects when using Django Rest Framework?

I'm using Django Rest Framework and it's integrated with an external service. I'm using an endpoint to receive a callback from a webhook whenever a new task is created in the external service.
When the callback request comes in, my code needs to create at least one object. But it's possible that multiple objects will need to be created from multiple different models. For example, if a new task is created it's possible that it was created by a new user, in which I also need to create a new user object to reflect this.
In total, there could be up to 5 additional objects made as side effects. I'm aware of multiple different places that this logic could be added (e.g. service layers, serializers, models, managers, views). But there seem to be issues with all of these.
Has anyone dealt with this issue before? If so, how did you solve it?
First of all, it is important to understand the difference between an RPC-style API and a RESTful API. Simply put, you can imagine an RPC API to be "methods" that are "actions", while a RESTful API represents the state of your models.
For example, let's say we want to create an endpoint to handle user registration.
A RPC style endpoint might be /api/register. A register function that might do X number of things.
A REST style endpoint might be /api/users. Not an action, but simply just an endpoint that give us the state of the users that exist. A GET request would list the users and a POST request would create a new user.
With that said, it might be a bit more clear that in general, creating endpoints that do X number of actions might not be very "restful", and using a framework specifically named "Django REST Framework" might not be the right choice.
So in your particular case. I suggest that you avoid creating endpoints that work as methods, and instead treat them as the resources that they represent. This means that if you need to create a new user, you do a request to the user-endpoint, then if you need to create a new article with that user, you do a second request to the article-endpoint.
Using Signals for Side Effects
I think if you do want side effects, they should be managed using signals. For example, let's say that you want to send out emails using a contact form. Instead of having a /api/send_email endpoint, you instead do a /api/messages/ endpoint that represent a Message model, and then you use signals to send out emails whenever a new message is created.
By doing things this way, it still means that the API endpoint itself just represent the state of the model, while the side effect of modifying the state (sending a message on creation of a new message) is moved to the signal's responsibility.

RESTful API: how to tell whether an object retrieved by GET is editable (e.g, PUT-able) by the current user?

Currently I set up a RESTful API backend using Django and I can list a set of articles by the following GET:
api/articles/
Also, I can get a single article by:
api/article/1/
Each article is owned by a certain user, and one user could have multiple articles of course.
On the frond end side, I present all the articles at loading of the page, and I hope the user who is logged in currently could see the articles that they own in a different style, e.g, outlined by a box, and has a associated "delete" or "edit" button.
This requires me to tell, after the retrieval of the articles, which ones are owned by the current user programmatically. One way of doing this is to check the current user id with the owner id. However I feel this is not a good choice as the user id is the check is done fully on the client side and may be not consistent with the actual server judgement.
Therefore, is there a way, to tell by looking at the response of the GET, (say, let the server return a property "editable=true/false") to get whether the current user could edit(PUT) the resource?
I understand that this could be done at the server side, by attaching such a property manually. However, I am just asking whether there is better/common practice.
I just started learning web development and I am sorry if the question sounds trivial. Thank you!
You can attach propriety manually as you suggested. The advance of this approach is that you dont need any other http request.
Second possibility might be, that your client intentionally request information about endpoint permissions. In this case I would suggest to use OPTIONS HTTP method. You send OPTIONS HTTP request to api/articles/1 and backend returns wanted info. This might be exactly what OPTIONS method and DRF metadata were made for.
http://www.django-rest-framework.org/api-guide/metadata/
I think that this is a very interesting question.
Several options that come to me:
You can add to the GET api/article/1 response a HTTP header with this information i.e. HTTP_METHODS_ALLOWED=PUT,PATH,DELETE. Doing this way helps the API client because it does not need to know anything else. I think that this is not a good approach when more than one entity is returned.
call to OPTIONS api/article/1. Allowed methods for that user on that resource can be returned but notice that, in my opinion, this approach is not very good in terms of performance, because it duplicates the number of requests to the server.
But what if the entity returned also contains information on the owner or it? can, in this case the client know which policy apply and try to figure out it by itself? notice that the policy can be obtained from another endpoint (just one call would be needed) or even with the login response. If your entities do not contain that kind of information, it could be also returned as a HTTP header (like first option above)

Possible to log form submission?

Here is the situation. My company has an e-commerce store, but we don't gather or process credit card information ourselves. When a user selects "Pay with credit card", they are immediately taken to the payment site, and then that site processes their credit card and sends the status back to us so that the order can be marked paid. Our site runs on ColdFusion, and it receives the data from the site as form data, processes the form variables, and creates an order for the customer, marked as paid. The credit card site only sends the information once, and there is no "handshake".
In the last month and a half we have been having an issue where occasionally we are not getting the information from the credit card processing site, although they say they have sent it. Hence orders are not being created, and products are sitting in customers' carts, even though the credit card has been charged. This problem is intermittent. We can't tie it to any server changes on our side, and the credit card site denies changes on their side.
So among the things we are trying to do is to log when the customers are actually trying to pay by credit card (so we can catch the missed ones more easily). So I want to somehow log the event when someone clicks "Pay with credit card." Issue is that form action submits the data to the credit card site. The only way I can think of to do this, is to change the form action to a page on our site, log the payment attempt, and then submit the form again to the credit card company. I know I can submit a form automatically with JavaScript, but that seems like a bad solution (what if JS is turned off?), but don't know how it would be possible to do server-side.
Please try to avoid solutions that involve AJAX if possible, as I know very little about it (I am a very rookie web developer in general, and just inherited this whole set-up).
Better solutions for how to log this event, or suggestions in general for this mess, will be greatly appreciated!
Responses to comments:
To Sam Dufel:
Would love to change to another provider like Paypal. Unfortunately my company is actually part of a university and we all have to use the same payment gateway.
To flup:
Would using a 301 or 302 status code preserve the form data? I tried looking this up, and it looks like it works with "get", but I need it to be sent with "post", since that is what the payment gateway is expecting.
To imthepitts:
We receive it as form data.
To Revent:
The issue is that orders aren't getting created at all (so customer and order information is just sitting in the temporary basket/customer/order tables). It seems like the page that is supposed to process the form data from the payment gateway isn't being accessed. I have added some logging to that page, but my company is so freaked out that they have disabled credit card payments and so I am not getting any data. If I can convince them that I have implemented a good logging solution to identify bugged orders quickly, they will turn it back on.
To Laksma:
We are using a unique identifier that is sent back. What I meant by handshake is some way of the payment gateway verifying that they have made a connection with our server. Maybe I was using the word incorrectly. Thank you for the suggestion of the log on the receiving page- I have added that.
To Nenotlep:
I know I said no AJAX, but I would like to hear more about your idea. Would the call to the logging page interfere with the form submission at all? I'm assuming it would be set up so that the function would trigger on the "onclick" event for the form button, and then form submission would proceed as normal? If it is easy to set up, then maybe that would be a good way of doing it.
I'm thinking of trying Sanjeev's solution, since that is similar to what I was planning to do anyway, but I actually would like to hear more about the AJAX idea if it is really that simple, mainly because it won't change the customer experience at all (unlike seeing the redirecting screen).
Additional response to steve:
I appreciate your input, and normally I love teaching myself new things, but I am just way too overwhelmed right now to even think about tackling a new technology.
I work on a payment gateway and had the same problem as yours. This was my solution -
Post the values to a intermediate page called as 'requestHandler.cfm'.
requestHandler.cfm saves the values into database table.
Continue to creates a <form> with all the required values as <input hidden>. Place a submit button and also JavaScript to fire 'submit' in say 2 seconds. Also put a note that, "If the page does not refresh in some time, click the submit button". As you are not going to do any validation on the form, a 'submit' button will just submit the form with or without JavaScript being active.
The Creditcard company will process the information and reply back with the values to a 'responseHandler.cfm' page.
I shall update my data based on the 'primarykeyvalue' sent to them. (Or just any reference that can identify the user)
Database table sample
The TransactionID will be '0' by default and will change to the number given by the credit card company
The paid flag which is default 'N' shall change to 'Y'
The Actual amount is what I have sent to be charged on the user credit card.
The Paid Amount should match the actual amount. This is to help me find if the details are tampered in any case by the user or middle man.
Handshake:
When a user is taken to the payment site, you should include a unique identifier to distingush the order, such as OrderID. Your payment provider must have some custom fields for your own use. Then, when the user is taken back to your site, the payment site response data should include the OrderID. That way you can match them. In other words, "handshake" is occured.
Intermittent successful payment:
On the listener, the page where the payment provider returns form data, you should implement a log to record from where the page is called and what data is sent.
"... is to change the form action to a page on our site, log the payment attempt, and then submit the form again to the credit card company." This is a doable solution.

Django: Handling post transaction logic

Common use case:
User select item to add to cart
User makes payment via off site payment gateway such as paypal or
worldpay
User gets redirect to payment page and makes payment
Payment portal sends a POST request to a callback URL
User gets redirected back to your page
On Step 4, typically the following things happen:
Error handling and anti fraud checking
Updating of order/cart models and additional logic
My question is pertaining to this step 4:
In apps like Django-Paypal, rather than do all the logic processing on the callback url view function, signals are used instead. Is there a good reason for this? Why not just do all the logic on the callback url view function?
The use of signals decouples django-paypal from your own apps. You can have all kinds of crazy custom stuff happening on payment success or failure in your projects and still use the default provided view.
The class based views in Django 1.3 do make it possible to extend views, and provide an alternative way to decoupling an apps view.
Other considerations you should have before putting logic in views is time; if logic could take a long time (like any I/O), ask yourself if they are crucial to the Response at hand and consider putting it in a task queue, so you can handle the Request quickly, without blocking.