I've made an application that creates pull requests to update the dependencies in all of my org's repos when the repo "Alpha" gets a new tag. The process is triggered by our CI flow on Alpha. Other engineers here would like to upgrade this application so that whoever made the tag is also automatically added as a requested reviewer to all of the associated pull requests. I do not see any way to do this with the github REST api. So far I have:
GET tag by name -> tag object sha
GET tag (with obj sha) -> tagger name & tagger email
*************GAP**************
POST requested reviewer (with username) -> completed!
I can't see any good way to get a username from the REST api with the name and/or email. I could query commits from Alpha and filter them, BUT "person who tagged" != "person who made last commit AND I know that at least one of our more prolific taggers is sometimes logged in from different emails (web vs cli vs home machine, etc), so the app might miss them from time to time.
I think it may be possible to get what I want via the GraphQL api, but I'd really like to exhaust REST possibilities before I go down that road. Please shoot any ideas my way!
After gathering more information, it looks like it's possible, and even slightly more elegant than I anticipated. If I have the name of the tag (the 'ref'), I can get a specific commit with that rather than the SHA. the response for this commit includes author information that gives the login. I can then use this along with the pull number to request a reviewer.
Related
In my application, I will have clients trying to book some slots. For this, the client will give some input and based on that input, I have to first create these slots and then return them to the client. Then after getting the slots, the user will book one of these slots. This "book" action is not creating any new resource but simply modifying 2 existing resources.
How do I design my URIs and what methods should I use?
EDIT:
I have 1 existing resource whose URI is: /api/v1/vehicle/id
Using the application front-end a user will fill some form data, with fields date and booking-type and submit it. Then this data will be used by the backend to "calculate" (no resource called slots exists currently) booking slots available to the user. These calculated slots will then be saved in the DB and returned as a response to the user. Out of these slots, the user will book a slot. However, this book action will not create any new resource, instead it will simply modify an existing vehicle resource (add booking related data to it) and the slots object returned by the previous request. I want to create a REST API for this.
I was thinking of doing it like this:
POST /api/v1/slot (1)
PUT/PATCH /api/v1/vehicle/id (2)
PUT/PATCH /api/v1/slot/id (3)
First, I am not sure if I should use PUT or PATCH here, in both (2) and (3). I will only be supplying partial updates to the request. Second, when the user selects a slot and clicks on book button, the front end can only send 1 request to the server. But here, I need to modify 2 resources. How do I do this? I guess I should create 1 URI like /api/v1/createbooking and use the POST method. Then in my backend call 2 different methods to update vehicle and slot objects. Is this URI structure and naming good?
How do I design my URIs and what methods should I use?
How would you do it with web pages?
It sounds like you would have the user navigate to a form which collects the date, booking type, etc. The user submits the form, and the information is sent to the server; because this is not an essentially read-only operation, we'd expect the form to indicate that the POST method should be used.
The server would make its local changes, and present to the user a new form, with the input controls presenting the available options. Once again, choosing a slot doesn't seem to have read-only semantics (we're passing information to the server), so we would see POST again.
What are the URI targets? One way to choose which resources should handle the POST requests is to consider the implications of cache invalidation; because caches know to invalidate the target-uri of a successful POST request, it can be useful to target a resource that is likely to change when the request is successful.
My guess would be that first post would go to the resource that presents the slot choices (since what we are doing is generating new choices for the customer).
For the second submission, since the representation of the vehicle is what is going to be changed by selecting a slot, it makes sense to send that POST request to the vehicle uri.
In general, think about how you read (GET) the changing information from the server; you change that information by sending some request to the same URI.
I am not sure if I should use PUT or PATCH here
PUT and PATCH are typically available together, not as distinct things. They are two different methods for sending a replacement representation of a resource.
A simple example: if you wanted to change the title of /home.html, you could either PUT the entire HTML document with the new title, or you could PATCH the HTML document by sending a patch-document in some format that the server understands.
In other words, both of these methods have remote authoring semantics; we normally would choose between them based on considerations unrelated to your domain model (if the document is small relative to the size of the HTTP headers, a client would usually choose PUT for the additional idempotent semantic guarantees. If the document is really big, but the change is small, we might prefer PATCH).
I need to modify 2 resources.
There's no rule that says a request may only modify one resource. The side effects of the changes may impact the representations of several resources (see 4.3.3 and 4.3.4 of RFC 7231).
What's tricky is telling general purpose clients (and intermediate components) which cached representations are invalidated by the change. Out of the box, we only have semantics for the effective request uri, the Location and the Content-Location. Location and Content-Location already mean something, so you can't just hijack them without the potential of introducing a big mess).
You could do it with Linked Cache Invalidation, using "well known" link relations to identify other documents that have been changed by the request. Unfortunately, LCI doesn't seem to have achieved the status of a "standard", so we may be out of luck for the time being.
I've been using Netlify for storing 100% of my app (both frontend and backend) for the last three months. So far, so good.
The only problem now is that I need to store a custom property for each user (say, the phone number), and apparently Netlify Identity doesn't support this (only email, name and roles https://www.netlify.com/docs/identity/).
I don't want to change the whole app to migrate to another hosting provider just for this detail (actually, I can't, it's for a client and I just don't have time), because it works great, but at the same time I need it.
Can you think of any workaround to this? The less "hackish", the better, but I understand that I'm going beyond the intended use of Netlify Identity.
So it actually does look like Netlify's GoTrue API has a specific endpoint for updating custom user data. After a user is created, you can update metadata by including it as "data" within an authenticated PUT request to /user.
PUT /user
{
"data" {
"custom_key": "value",
}
}
See https://github.com/netlify/gotrue for more info.
There are dozens of ways to do this, so I'll talk about two generally applicable ways now:
the most "generally capable" one is probably using lambda functions: https://www.netlify.com/docs/functions . This lets you run dynamic code, such as "store to database hosted elsewhere" or "email to our office manager to update a spreadsheet" or even "commit to our closed git repo so it's available in-code" (last one is probably a worst practice, but is possible). You can similarly use a function to read that data back out without exposing API tokens (code example: https://github.com/netlify/code-examples/tree/master/function_examples/token-hider)
you could have the data gathered via a form submission (https://www.netlify.com/docs/form-handling). I'd probably use zapier.com to receive a notification of the form submission (https://www.netlify.com/docs/form-handling/#notifications). Zapier can of course connect to just about anything on the planet :) . Getting the data back out if you want to show it in your UI is a bit more of a challenge, but you could use the above mentioned functions if you need to connect to some private data store to pull it out. Or for an MVP, just not show it, only let people enter/update it ;)
In Liferay 7 Enterprise Edition,
I want to log user info like user_name in external log files automatically in each request to track user activities, how to do that?
without using auditing plugin
when I tried to log post request for example (login), it doesn't contain any info about user ?!
This kind of thing is much harder than you might think...
Getting access to the current user is really easy. As Victor pointed out, you can use the ThemeDisplay object to get current user. If you don't have the request around, you can use the PrincipalThreadLocal to find the current user id.
That gives you the who, but certainly not the "what is user doing" aspects. Since the portal aggregates the HTML fragments of many portlets, from a servlet filter perspective it would be hard to gleam which one of the available portlets on an incoming URL is actually being interacted with. You could try a portlet filter to narrow the field, but this will just tell you what portlet is being accessed but not what they are doing with it.
Although you rejected the built in audit functionality available in DXP, it really is the answer for tracking who did what in the portal because it has the necessary touch points to get those two pieces and put them together.
Now if you rejected the built in audit functionality because you want a file and not a database entry, that is easy to solve. Go to the System Settings control panel and find the Logging Audit Message Processor and enable it. It will write the audit events out to a file in CSV format, but you should have the source for modules/apps/foundation/portal-security-audit/portal-security-audit-router/src/main/java/com/liferay/portal/security/audit/router/internal/LoggingAuditMessageProcessor.java so you can use this as a basis to write your own format.
Look at this code:
https://github.com/amusarra/liferay-portal-security-audit
in particular the portal-security-audit-capture-events module that catch the login events.
This seems a job for a filter, the user information is normally extracted from the themeDysplay, like in:
ThemeDisplay themeDisplay = ( ThemeDisplay ) request.getAttribute( THEME_DISPLAY );
long userId = themeDisplay.getRealUserId();
If you want to track specific portlets, an OSGi portlet filter would do the job.
Lets consider the following flow to a RESTfull API:
API root
|
v
user list
|
v
user details
|
v
user messages
Suppose I have a client to consume the API, and I want to retrieve messages from a user with ID 42.
From what I've been studying, my client is not supposed to know how to "build" urls, and it should follow the links given by the API.
How should I do to retrieve messages for the user with ID 42?
The only way I can think is "walk" the whole API from it's root to user messages, which doesn't look very pretty or efficient to me.
Eg:
1 - GET / and get the link to the list of users
2 - GET /user/?id=42 and get the link to details of the user with the ID 42
3 - GET /user/42/ and get the link to user 42 list of messages
4 - GET /user/42/messages/ and finally get the user messages
Did I get something wrong? Is this the right way according to Roy's Fielding paper?
Or is it ok to just assume the messages url is "/user/{id}/messages/" and make the request directly?
Use URL templates in your API root. Let the client consume the API root at runtime. It should look for a URL template named something like "user-messages" with the value of "/user/{userid}/messages/". Then let the client substitute "42" for "{userid}" in the template and do a GET on the resulting URL. You can add as many of these URL templates you want for all of the required, often used, use cases.
The difference between this solution and a "classic" web API is the late binding of URLs: the client reads the API root with its templates at runtime - as opposed to compiling the client with the knowledge of the URL templates.
Take a look at the HAL media type for some information about URL templates: http://stateless.co/hal_specification.html
I wrote this piece here some time ago to explain the benefits of hypermedia: http://soabits.blogspot.dk/2013/12/selling-benefits-of-hypermedia.html
I believe what your real concern is should you go about implementing HATEOAS or not. Now as it's an integral part of REST specifications, it is recommended that each entity should have a link to it's child entity that it encompasses. In your case, API ROOT should show list of users with each "user" having a link (/root/users/{id}) to corresponding user's details. And each User details entity will contain a link to the list of "messages" (/root/users/{id}/messages) which, finally, inturn encompass the link to the actual message detail as well (/root/users/{id}/messages/{messageId}). This concept is extremely useful (and thus a part of the specifications) because the client doesn't need to know the url to where your entity is exposed. For example, if your users were on http://users.abc.com/rest/users/{id} but your messages were on http://messages.abc.com/rest/{userId}/messages/{messageId}, the user entity that encompasses the list of "messages" will already have link embedded to point to the right resource on a different server.
Now that being said, I haven't actually seen many REST implementations out there (I must admit I do not have TOO MUCH of an experience, but enough to give an opinion) where HATEOAS is being used widespread. In most cases the resources are almost always on the same server (environment) and the paths to resources are almost always relative to the root url.Thus, it doesn't make sense for the clients to parse out the embedded links from the object when they can generate one by themselves, especially when the client would like to provide access to a resource directly (View the message directly without getting the user entity provided you already know what the messageId is).
In the end, it all depends on how close do you want your REST implementations to that of specifications and what kind of clients are you going to have. My 2 cents would be: if you have time, implement REST with HATEOAS and feel proud about it :). There are libraries out there that will make this implementation (HATEOAS) somewhat transparent to you REST implementation (I believe spring has one, although not very mature. You can look at it here). If you are like me and don't have much time to go that route, I think you can continue with a normal REST implementation without HATEOAS and your clients will still be OK with it (or so I hope!)
Hope this helps!
I found this article about hacking urls: Avoid hackable URLs.
There is a very interesting discussion about the topic of this question in the comments section.
I don't quite grok how to sensibly structure a REST (or REST-like) API.
Imagine an API for creating and sending out newsletter emails. You might have the following nouns/resources: newsletters (subject, body, etc.), mailing lists (collections of recipients), and recipients (email addresses and associated data).
So you could use PUT to create a resource and be returned its ID:
/newsletter
/list
/user
You could obtain information on a resource using GET:
/newsletter/[id]
/list/[id]
/user/[id]
You can update an existing resource using PATCH (or should this be POST?):
/newsletter/[id]
/list/[id]
/user/[id]
You can delete a resource using DELETE:
/newsletter/[id]
/list/[id]
/user/[id]
Is the above correct?
What endpoints are sensible for actions like sending a newsletter to a list, adding a user to a list?
Does the following make sense, and is it RESTfull?
/newsletter/[newsletter_id]/send/[mailinglist_id]
/list/[list_id]/add/[user_id]
/list/[list_id]/remove/[user_id]
Is it redundant or unhelpful to have list/[id]/add/[id] and list/[id]/remove/[id] endpoints for lists, when users could be added or removed via PATCH at /list/[id] ?
What about searching for a users' ID via a property like email address or name? Or getting a list via an identifier like its name or when it was created?
You pretty much nailed it, except with the /list/[list_id]/add/[user_id] and /list/[list_id]/remove[user_id], because you have verbs in the URL - that is the purpose of the HTTP methods. Change them to, for example:
PUT (or POST) to /list/[list_id]/users/ for adding a user to the list
and
DELETE to /list/[list_id]/users/[user_id]
For search, I'd go with parameterized url for the list of resources, like:
/newsletter/?name=dfjkhskdfh
These verbs are often confused:
To create an entity you use POST
To update - PUT
These things could be treated in the following way:
POST /newsletters/[newsletter_id]/mailinglists/[mailinglist_id]/mailingfacts - performs sending the letters, it's like adding a fact of mailing to the collection
/lists/[list_id]/[user_id] - adds a user to the list
/lists/[list_id]/[user_id] - deletes the user from the list.
Is it redundant or unhelpful to have list/[id]/add/[id] and list/[id]/remove/[id] endpoints for lists, when users could be added or removed via PATCH at /list/[id] ?
It is bad/unhelpful. One of the ideas of REST is that the end points are resources and not a Remote Procedure Call (RPC). add or remove is suggesting a procedure to call.
Further GET requests should be side-effect free, that is, they don't do any updates. Further Roy Fielding explains GET as:
retrieval of information that should be a representation of some resource
So GET is only for retrieval, not for sending data (i.e. which user to add/remove).
The other very dangerous problem with list/[id]/remove/[id] is that if a spider or your test framework is going around your site it could start deleting items.