Authenticating/authorizing access to tastypie top level API schema - tastypie

I know how to setup authentication/authortization for tastypie resources: via settings in the resource Meta class. How do I authenticate/authorize access to the top-level schema though?
For example, I can authenticate/authorize the resource at /api/v1/resource, but how do I authenticate/authorize the schema at /api/v1?

There is no easy way to do this by default with tastypie's default mechanisms. If you look inside api.py file you will see that the top_level method doesn't have the authentication/authorization mechanism applied.
I think the cleanest way to achieve what you want would be by extending the Api class and overriding the top_level method to check that the user is allowed to see the result.
This however may be overcomplicated becuase the Api itself doesn't use the autorisation and authentication methods. So you may want to override the Api's urls method by removing the top_level definition there and putting it inside the urls in your Resources.

I had to solve this problem as well. Here's a code example of Anna's suggestion:
class ApiWithAuth(Api):
def top_level(self, request, api_name=None):
auth = MyAuthentication()
r = auth.is_authenticated(request)
if r != True:
return r
return super(ApiWithAuth, self).top_level(request, api_name)
api = ApiWithAuth(api_name='v2')
api.register(MyResource())
api.register(MyOtherResource())
...

Related

Spring Data Rest does not support post for item resource according to docs, but it does?

https://docs.spring.io/spring-data/rest/docs/3.2.1.RELEASE/reference/html/#repository-resources.item-resource
According to that, the only methods supported for a single item resource are GET, PUT, PATCH, and DELETE.
But I created a simple resource with an example project and it accepts POST for a single resource. Why?
It shouldn't. The RepositoryEntityController class is responsible for handling the repository endpoints, and there is no POST endpoit for BASE_MAPPING + "/{id}" in it.
Are you sure you didn't create any custom endpoints?
I had a similar problem using MongoRepository: on a single item resource, POST operations returned 200, although the body showed an error message.
I solved the problem by removing getter and setter methods from the id field.

Swagger UI generation for generic REST calls

What do I want:
I want to be able to generate swagger documentation that passes a key/value into the URL. This so that I can use generic arguments controller to handle my requests like Dictionary.
If swagger can't generate it, is there a way to generate the documentation by using reflection on my objects? This so that I can still use generic methods
If not, what would be the best way to let everyone know what the correct approach would be.
Why do I want it
I'm developing a new API and I'm using swagger to create the documentation. In this API I want to work with some generic methods to prevent hardcoding things. For example on the PATCH method I use a Dictionary<string, string> to get the property/value combination and in the GET I use a custom object as the argument. In both cases, swagger can't generate the correct parameter fields, because it takes the argument as url key.
Example action & form - incorrect
public async Task<IActionResult> Patch(int id, Dictionary<string, string> viewModel)
{
return await ConnectionWrapper(() => connector.Patch(id, viewModel));
}
This uses the body, not the query
Other examples - incorrect
In the GET I have a model with a custom modelbinder to handle all the rest URL arguments. The problem is because the model is defined it sees the filter as a property.
Then it is in the URL, but it will look like http://example.com/controller/method/id?sort=prop_asc&filter=propTwo%3D=value, instead of http://example.com/controller/method/id?sort=prop_asc&propTwo=value
Desired output
I've modified the HTML to simulate what I would like in the picture above. The URL that would be called would be http://example.com/controller/method/id?propertyName=propertyValue.
I don't mind if there would be only one option to add a generic key/value pair because with it I can demonstrate what I want.
Expected solution
I think the solution lies in the MapType startup method of swagger or in an implementation of the IOperationFilter, but I haven't been able to figure it out.

How correctly implement a RESTful WS architecture using Spring MVC\Boot?

I am not so into RESTful web service and I have the following doubt about how to correctly implement RESTful style in my servics working on a Spring Boot application (Spring MVC is the same thing).
So basically I have some controller class like this:
#RestController
#RequestMapping("/RoomMedia")
public class RoomMediaController {
private static final Logger log = LoggerFactory.getLogger(RoomMediaController.class);
#Autowired
private RoomMediaService roomMediaService;
public RoomMediaController() {
log.debug("RoomMediaController init");
}
#RequestMapping(value = "getAllImagesByRoomId",
method = RequestMethod.GET,
produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<List<byte[]>> getAllImagesByRoomId(Long roomId) throws DataAccessException {
log.debug("getAllImagesByRoomId START");
List<byte[]> result = roomMediaService.getRoomImageListById(roomId);
log.debug(result.toString());
log.debug("getAllImagesByRoomId END");
return ResponseEntity.ok(result);
}
}
I think that, also if the base idea is RESTful like, it can't be considered a true RESTful WS.
I think that the main problem is related to the endpoint: the getAllImagesByRoomId() method handle HTTP GET request toward URL like this: /RoomMedia/getAllImagesByRoomId?roomId=7
From what I have understand reading some tutorial this is not RESTful style because I have to access to a resource without passing parameter, I have to do someting like this:
/RoomMedia/Images/7
Is it my reasoning correct?
Moreover I think that the previous method is pretty trivial also in the implementation: this method return the list of all the images associated to a room having id=7(it is an application related to hotels).
From what I have understand also its logic is againts RESTful principles.
Is it better organize in the following way?
Doing a GET request like this:
/RoomMedia/7/Images/: I have to obtain the list of all the images associated to the room having id=7 as URI (or maybe is better handle a path like /7/RoomMedia/Images/ ?).
/RoomMedia/7/Images/1 I obtain the image with the id=1 associated to the room having id=7.
Are al these reasoning correct or am I missing something?
your assumtions are correct. Which of the mapping that you suggest, is deppending totaly on how your model is. Martin Fowler has a nice article about the Richardson Maturity Model which is sum up as:
Level 1 tackles the question of handling complexity by using divide and conquer, breaking a large service endpoint down into multiple resources.
Level 2 introduces a standard set of verbs so that we handle similar situations in the same way, removing unnecessary variation.
Level 3 introduces discoverability, providing a way of making a protocol more self-documenting.
For your project you could use jhipster because its offer you the best of spring with angular under a REST-ful design.
URLs must not contain a verb. The verb is provided by the method, in your case - surprise, surprise - GET.
ByRoomId is pointless as well, because that's what ?roomId= says.
That leaves AllImages, where All is superfluous.
Which results in the URL /RoomMedia/Images?roomId=7. What's unclear is the relationship between RoomMedia and Images, if there is any. If RoomMedia refers to a room, then your suggestion /RoomMedia/7/Images/ would be correct.
/RoomMedia/7/Images/1 is questionable. It should rather be /Images/1. It's irrelevant in which room the image with the id 1 is in.
When you design a REST API, then the first thing to do is to think about all resources you want to expose and their relationships. After that the URLs will reveal themselves automatically, so to speak.

Foreign Keys in Web API 2 - Best practices?

Basically I'm writing an API using Web API 2 and Entity Framework on the backend.
The thing I'm unsure about is what to do in regards to foreign keys on my models.
Say I got a person property with a foreign key to an order property.
Sometimes the client needs the person property, sometimes it does not. How should I go about this?
Should I create 2 methods:
/api/person/1 <-- returns person without order
/api/personwithorder/1 <-- returns person with order
Seems like an awful lot of methods in my opinion.
I know the queryable attribute exists as well which provides support for the client to use the $extend argument to include properties at will - however I would rather not use the queryable attribute if I can avoid it.
What are your suggestions?
Off the top of my head, here are some options.
Option 1
Multiple methods in API
public Person GetPerson() { ... }
public Person GetPersonWithOrders() { ... }
Option 2
Pass a flag to the method:
public Person GetPerson(bool getOrders) { ... }
Option 3
You could use OData to allow the caller to query the data.
To expand on DavidG's option 3 of using OData, here is how you'd do it:
Install-package Microsoft.AspNet.WebApi.OData
Create a PeopleController inheriting from ODataController
Configure the Web API OData model like so:
modelBuilder.EntitySet<Person>("People");
Define your Get method as returning an IQueryable<Person>
In your calling code, add the expand clause to the URL to specify the child object you would like to expose, like this: /api/People(1)?$expand=Orders
There's a little bit more to it around registering the OData route, but this is all standard configuration that you can find in any sample project.
OData is really very flexible and takes care of tonnes of issues about how you should build your URLs.

JAX-RS generic response and interface proxy

is there any way how to return generic describing entity type with the JAX-RS Response? Something like REST-Easy ClientReponse but JAX-RS standard and not implementation-specific class.
The thing is I want to call my REST service via its shared interface (created by some proxy provider) and returning only object does not allow add information I need. E.g. for creating resource via POST, I would like to return also URL to newly created resource and so on. Returing simple Response does not show what type of entity is stored within such response.
Response<MyObject> getMyObject(#PathParam("id" Integer id)
So far it seems that I will have to return simple Response and then create adapter which will simply call Response.getEntity(.class)
There is probably no such option...
GenericEntity allows you to return a generic. The actual type is held at runtime by GenericEntity, allowing the object to be serialized.
Here's a contrived example of how it can be used.
GenericEntity entity = new GenericEntity<Employee>(new Employee());
return Response.ok(entity).build();