Courses API not returning material sets - google-classroom

I'm calling the courses REST API via the javascript library and I am able to get back the courses correctly, also assignments from the assignments endpoint. But, the course objects do not have a materialSets array field. I've tried using the readonly and read/write auth scopes. The course definitely has materials as I can see them if I log in to Google Classroom as a student. Also note that I'm doing OAuth2 authentication as the same student.

At the current stage Method: courses.courseWork.list will only return you materials that are bound to a course work
Materials that are created independently without being a part of an assignment are not returned by this method.
So currently there is no endpoint to return independent materials.
However, this issue has already been noticed and there is a
feature request on Google's Public Issue Tracker asking to implement this endpoint.
I recommend you to "star" this feature request in order to show that you are also interested in its implementation and thus, increase its visibility.

Related

Is possible to use Oauth2 scopes to scope model data?

Every place I read about Oauth2 scopes it uses examples of read, write, delete, post:read, post:delete, etc... This always representing "actions", like It was a permission...
I am in a situation that I must implement an API that must authenticate the user but limit user's access to data that only belongs to the same corporation he belongs, this user may belong to "N" corporations.
I came with the idea to use the Oauth2 scopes for that purpose then use Laravel's eloquent global scopes in model to filter the data.
I am stuck and dont know How to proceed. Could anyone give some advice?
There are 2 concepts in the requirements you mention:
Scopes are high level privileges that represent an area of data and operations allowed on that data - they are also static values defined as part of the system design. Avoid attempting to use them for dynamic logic.
Claims are where the real authorization happens, and what most domain specific authorization uses. Claims are just extra fields included in JWTs. In your case an array claim of Corporation IDs could be issued and included in JWTs received by APIs.
These two Curity articles explain this in more detail, along with some real world examples. When done well, the result should be simple code in your APIs:
Scope Best Practices
Claims Best Practices

Understanding where to put constraints validation for REST api service using Spring

I'm working on a REST api for a model having the following entities:
A Team cannot exists if it has no relationships with a Course and a Student. At the beginning, I created an endpoint for the teams (API/teams) for the CRUD operations. Now I ended up moving all the CRUD operations for the teams under the following URLs:
/API/courses/{courseId}/teams
The same has been done for Machine that cannot exists without any relationships with a Team and Student, so any CRUD operation should be done to the following:
/API/courses/{courseId}/teams/{teamId}/virtual-machines
This makes sense to me, since every time I need to perform an operation on a Machine I have to verify the constraint for which the Machine is owned by a Team related to a Course. For this reason, If I continued to perform any operation on URLs like /API/teams I should have requested the course and team ids to verify those contraints in the request body.
Having said this, my CourseController invokes a VirtualMachineService for all the operations on the Machine entity. What it seems odd to me is that each signature of every method in the VirtualMachineService need to have the course and the team id to verify the above constraints. This caused to have lots of duplicated code in every method.
Are my design choices correct?
The CourseController only have to invoke the methods of VirtualMachineService and to validate the parameters coming from the requests body.
Should those constraints validation be done inside the controller or inside the service?
Neither Configuration nor Model are entities. Entities are classes from the domain (real world representations related to project, if you will), not every class you use.
REST doesn't directly care about your entity model (meaning graph) but you should follow the guidelines for specifying REST endpoints which is
different endpoint for
/courses/... and /teams/... - don't mix these. Any constraints you would like to apply are applied at the backend and have nothing to do with endpoint definitions.
Validation guide https://www.baeldung.com/spring-mvc-custom-validator

HAL clients or examples of accessing HAL API

Question: Any HAL clients or examples of accessing HAL API with admin-on-rest ?
I got started because HAL was mentioned in the first paragraph of the introduction, but now I'm having trouble finding any examples or anyone else using HAL rest client, so I am winding up for now just writing a bunch of simple findAll repositories on top of the already robust existing HAL API.
Adding a more concise answer here that isn't polluted with my thought process now that I've got it all figured out (for anyone's future reference)... Again assuming the HAL API was made with Spring Data Rest.
The four major keys to this integration are:
Exposing foreign key attributes in your JPA entities, which is required in several places by admin-on-rest #Column(name="parentEntity", updatable=false, insertable=false) private Integer parentEntityId;
Exposing all your entity IDs using RepositoryRestConfiguration.exposeIdsFor( MyEntity.class )
Annotate your repositories as #RepositoryRestResource and have them extend PagingAndSortingRepository<MyEntity, Integer>, QueryDslPredicateExecutor<MyEntity> to expose extremely useful search filters by attribute name (e.g. /api/myEntitys?field1=foo&field2=bar).
When submitting create and save requests with foreign keys make sure to adjust your params.data to include the linked resource (e.g. 'http://myserver.com/api/myEntitys/19') on top of (or in place of, HAL has no use for it) the foreign key you exposed in 1. (e.g. myEntityId=19)
Other small items of note:
use PATCH instead of PUT when updating (you may be able to use PUT if you are more of a hibernate expert and can map your entities better than I can but I had trouble getting it mapped perfectly and HAL's PATCH will take partial entities)
When submitting GET_LIST and GET_MANY_REFERENCE you get the total number of items and pagination parameters from the 'page' section of the response, and you use 'size' and 'page' query params in your API requests. (so, no need for headers and stuff)
To change the default 'equals' filter for any string entries (from 3. above) to a 'contains' filter, you will have to also extend QuerydslBinderCustomizer<QMyEntity> and provide your own customize method in each of your repositories. For example:
default void customize( QuerydslBindings bindings, QChampion champion )
{
bindings.bind( String.class ).first( ( StringPath path, String value ) -> path.contains( value ) );
}
We don't have any examples for HAL specifically. However, the point of this introduction was that admin-on-rest is backend agnostic.
You can create your own custom rest client by following the documentation. Read the code of existing ones for inspiration.
For anyone referencing this in the future, if you happen to be in control of your API through Spring Data Rest you can consider the use of an excerptProjection on every one of your existing repositories that shows an inline version of your entity. This would work if there were absolutely nothing besides admin-on-rest accessing your API.
For my case I am planning on writing a custom projection for every rest resource that has entities and naming it the same thing: "inline". Then in the admin-on-rest restClient, just always asking for the inline projection on every GET_MANY or GET_MANY_REFERENCE request.
This is the best I have at the moment. It's not perfect but for the amount of entities I have it's still many weeks faster than building a CRUD interface from scratch so I highly recommend admin-on-rest.

Spring data rest and custom representation

I am using the current version of Spring Data Rest (SDR) and Spring Security (SS) and have following entities:
User: contains a List of teams joined and another for teams managed.
Team: contains a List for members and another for admins.
What I would like to do is customize the information returned for the entities by SDR given permissions of the current User. I'm aware of Projections in SDR but I believe they're not suitable for my current problem since this should be done transparently without having the User specify the projection in the request.
Given the following:
(1) /teams/{team_id}/members
(2) /teams/{team_id}/members/{member_id}
(3) /users/{user_id}/teamsJoined
Here is what I want to implement:
Visiting (1) by a normal member of the team would return different fields than when done by an admin.
Visiting (2) would return additional fields not returned by (1)
Visiting (3):
by the user with {user_id} should return all teams.
by another member should return only the intersection of their teams.
I was thinking about maybe using AOP but I'm not really sure if it would work. What would be the best way to implement this?
I'm not sure exposing various representations of a resource (at the same uri) based on the requesting user follows the REST philosophy. You should use another uri for that.
Maybe you could split the data visible by only some kind of users from the original entity into another 'sub'entity (1-1 relation) and restrict the access to theses related resources endpoints. You can make use of #PreAuthorize and #PostFilter annotations on your repositories methods to restrict access on your resources based on the identified user.

Code Design. How to access your api-key in your business logic?

It's a code design question :)
I have a DelegatingHandler which takes the http request header and validates the API-key. Pretty common task I guess. In my controller I call my business logic and pass along all business-relevant information. However now I'm challenged with the task to change behavior inside my business logic (separate assemblies) depending on certain api-keys.
Various possible solutions come to my mind...
Change business logic method signatures to ask for an api-key, too.
public void SomeUseCase(Entity1 e1, Entity2 e2, string apiKey);
Use HttpContext.Current to access the current request context. However I read somewhere that using HttpContext restrict my hosting options to IIS. Is there any better suited option for that?
var request = HttpContext.Current.Request; // next extract header information
Use Sessions (don't really want to go that road...)
What's your opinion on that topic?
I'd go for #1 although I don't like the idea of mixing in enivonmental stuff in business logic methods. But depending on your point of view you might argue the api-key is in fact logic-relevant.
Update #1:
I'm using a delegatingHandler to validate the apiKey and once it is validated I add it to the Request's Properties Collection.
The part in question is how the "api-key" or RegisteredIdentifier is passed along to the business logic layer. Right now I am passing the object (e.g. IRegisteredIdentifier) as a parameter to the business logic classes' constructors. I understand there is no more elegant way to solve this(?). I thought about changing the method signatures but I'm not sure whether it's interface pollution or not. Some methods need to work with the api-key, most don't. Experience tells me that the number will more likely grow than drop :) So keeping a reference to it in my bl classes seems to be a good choice.
Thank you for your answers - I think all of them are part of my solution. I'm new to StackOverflow.. but as far as I can see - I cannot rate answers yet. Rest assured I'm still thankful :)
I would suggest two different options.
Promote the value into a custom HTTP header (e.g. something like mycompany-api-key: XXXX ). This makes your delegating handler work more like a standard HTTP intermediary. This would be handy if you ever hand off your request to some secondary internal server.
Put the api-key into the request.Properties dictionary. The idea of the the Properties dictionary is to provide a place to put custom meta information about the request.
HTTP works hard to make sure authentication/authorization is a orthogonal concern to the actual request, which is why I would try and keep it out of the action signature.
I would go for option 1.
But you could introduce the entity RegisteredIdentifier (Enterprise Patterns and MDA by Jim Arlow and Ila Neustadt) in your business logic.
The api-key can be converted to a RegisteredIdentifier.
RegisteredIdentifier id = new RegisteredIdentitief(api-key);
public void SomeUseCase(Entity1 e1, Entity2 e2, RegisteredIdentifier id);
The business logic layer has a dependency on the API key. So I would suggest:
interface IApiKeyProvider
{
string ApiGet { get; }
}
..then have your BLL require that an object implementing that interface is supplied to it (in constructor, setup, or even each method that requires it).
Since in the future it might not be one API key. The key point is that this identifies the BLL is dependent on something, and defining a contract for the something.
Real-world example:
Then, in your DI container (Ninject etc), bind your own ConfigFileApiKeyProvider (or whatever) implementation to that interface, in the "place" (layer) that DOES have the API key. So the app that calls the BLL specifies/configures how the API key is specified.
Edit: I misunderstood the part about this being a "how-to-do-it-over-HTTP" question and not a code architecture/code design question. So:
HTTP header is the way to go in terms of transport

Resources