Strapi: how to create a new model that belongs to a user? - api

I'm just getting started with Strapi.io and I'm currently working on a dummy project to test it out. Note that since I'm using the UI, I don't have any code to share, but I'll try to be as explicit as I can to describe what I want and what I've tried.
I have created a "todo" collection type that has a title, description, category and a user associated with it. The user is a relationship (one user has many todos) to the default user entity created with the Strapi app. When I run http POST http://localhost:1337/todos "Authorization: Bearer <TOKEN>" title="title" description="description" category="category" (I'm doing it with Postman) it works, but I see that the user field is null. I would like it to be automatically assigned based on the user who posted this command. Is that possible to achieve?
Many thanks!

Yes, it's absolutely possible. The way you do this is, you first identify which user actually made this request. This can be done by accessing the ctx.state.user variable. This is a global variable set by Koa so you can access this in the controller. Now to save the relationship of user against the todo collection entry you only need to pass the user id of the user calling this api. This can be retrieved by using ctx.state.user.id. So you can use the code below to create a todo collection correctly:
Sample code:
await strapi.services.todo.create({
title: 'My Todo Title',
description: 'My Description here',
category: 'Work',
user: ctx.state.user.id
})
P.S: You need to make sure you're logged in and are using a bearer token while calling the api or else, ctx.state.user will be null.

Related

Verify reCaptcha Token API Platform

I am hoping some of you can give me the best practice on how to verify my reCaptcha token on the server.
I have a Symfony 6 app with API Platform. I have defined some entities as API Resources, so I can POST data. On the front end I am using Vue with axios to POST to the specific end points.
I would like to verify the reCaptcha token, before the data from my form is posted, and came up with the below 3 options (Not really sure if any of these are the correct way to go about this)
Create a separate end point for reCaptcha, that I post data to and depending on the response run axios post request for form or not.
Create an up mapped property on the entities I want to use reCaptcha with and set a custom validator on this that validates if the response on token is success. I can then send the reCaptcha token as part of the post request.
Create an event listener for PRE_POST and somehow validate there???
I'm not sure if I'm on the right track with any of the above, the documentation I have been able to find is pretty non existent.
I would really appreciate being pointed in the right direction, or perhaps an example of best practice on this with my current set up?
For those of you coming across this with the same issue I solved it with the following steps: (I would still like to know from someone with more knowledge, if this would be considered best practice or if there is a better way).
Added an unmapped field (No #[ORM\Column annotation) to the Symfony entity I was posting data to, called reCaptchaToken. Added the set method to my denormalizationContext group.
Created ReCaptchaConstraint (class extending Constraint) and set validatedBy method to ReCaptchaConstraintValidator::class
Created ReCaptchaConstraintValidator (class extending ConstraintValidator), added HttpClientInterface to constructor and in validate method posted to recaptcha API (details of this end point can be found in reCaptcha documentation) to validate token and score. If validation failed or score too low, added violation.
Back in Symfony entity, added #[ReCaptchaConstraint] annotation to reCaptchaToken field.
Then from front end, created Vue method:
validateCaptcha() {
return new Promise((res) => {
grecaptcha.ready(() => {
grecaptcha.execute('YOUR_SITE_KEY', {action:
'addContact'}).then((token) => {
return res(token);
})
})
})
}
In .then() method of validateCaptcha() add token to my JSON object and posted to API end point normally.
Now if there is an issue with my token or score, I will get a validation violation returned from POST.
Hope this helps someone else struggling.

How can a webhook identify USER_IDs?

I'm developing a webhook, and I want it to be able to #mention specific users. The simple message format specifies using the format of <users/123456789012345> to #mention a specific users. Since this is not a bot, it is not processing an incoming message and cannot pull the from the sender field, as suggested in the note on the developer site linked above.
How can I get the USER_ID of a user on my domain?
I am in the same boat as you. Trying to use a Webhook to mention a user.
If you inspect the HTML on https://chat.google.com, using web/dev tools, you can actually see user ID under tag data-member-id="user/bot/123456789012345"
Using the above I tried to form a webhook that mentioned the user (in my case another bot).
Unfortunately it didn't work. Passing in the string <users/123456789012345> please test came through to chat as a string literal.
It's strange because the html links and markup DO get interpreted. As mentioned here. Edit: so does <users/all>.
I'm leaving this here since your question asks for how to elicit the ID. While it may not be pretty, or much automatable, it helped me get the user ID at least.
Edit 2: It works, just not to mention my other bot for some reason. But using this method I was able to mention a human user :)
I use this for find the USER_ID but if you have another way let me know
Right click on the user and select inspect
Search for data-member-id this is your USER_ID
A webhook will not be able to pull the USER_ID of a user. As a workaround for this, you can create a service account and a bot that has access to the room and use the REST API spaces.members.list() and spaces.members.get() method.
Note: The bot will need to be added to the room.
Okay, so in order to get the UserID without having to do all of the things that you're trying to do here you need to use the Admin SDK API in google app script. Basically what you'll want to do is use your google app script as an intermediary for what you're trying to do. So you'll post something to google app script via their web exec functions on a deployed app and then have that app communicate to the google chat API via something like this:
var googlewebhookurl = 'https://chat.googleapis.com/v1/spaces/ASDFLKAJHEPQIHEWFQOEWNQWEFOINQ';
var options = {
'method': 'post',
'contentType': 'application/json',
'payload' : JSON.stringify({ text: "<users/000000000001> I see you!" })
}
UrlFetchApp.fetch(googlewebhookurl, options);
To start, you'll need to add the Admin SDK API to the services in your google app script services area. So click the plus next to "Services" and then select the Admin SDK API and click add to add it to the services, it winds up showing up in the list as "AdminDirectory" once it has been added to the services.
This is an image showing what it looks like once you've added it to the services.
Here is a link to the documentation for the Admin SDK API getting user information: https://developers.google.com/apps-script/advanced/admin-sdk-directory#get_user
You should be able to copy and paste that example function to get the information you're looking for regarding the user. I'm pasting the example code below in case something happens to this link:
/**
* Get a user by their email address and logs all of their data as a JSON string.
*/
function getUser() {
var userEmail = 'liz#example.com';
var user = AdminDirectory.Users.get(userEmail);
Logger.log('User data:\n %s', JSON.stringify(user, null, 2));
}
In order to get the user id, take the user variable that comes back and access user.id and voila! You have the ID you're looking for. From there just plaster it into a text message in google chat and you should be in business. I haven't gotten it to work with cards at all yet. I'm not seeing any documentation saying that it's supported in cards at all. For more information regarding chat messages and cards take a look at these:
https://developers.google.com/chat/api/guides/message-formats/basic
https://developers.google.com/chat/api/guides/message-formats/cards

Possible to create Rally TimeEntryItem for other user?

Is there a way to create a TimeEntryItem for another user?
I can persist the 'User' field before creating a new TimeEntryItem and see the User information being passed to Rally, but so far I get the following warning in the response, and the create request is treated as being for the calling user...
Warnings:["Ignored JSON element TimeEntryItem.User during processing
of this request."]
I don't think this is currently possible via the api. The warning you are getting above indicates that the User field is not writable, even on initial creation. So it is always just populated with the value of the current user making the request.

How do get userIdentity of current login request from list of all login users identities?

I want to restrict user for multiple login at a same time. Am following custom authentication method from below link
https://mobilefirstplatform.ibmcloud.com/tutorials/en/foundation/7.1/authentication-security/custom-authentication/
To achieve, I wanted know whether current login request is already logged in or not from some other device(session). Where or from which method am going get these details?
Please let me know how to get and return error custom message from this java file to adapter's calling method.
I don't believe any of the built-in APIs will provide what you are looking for.
Instead, I think you need to create your own implementation from scratch. Meaning, create some database to store the current status of each user. Update it every time, check the status whenever someone tries to login ...

RESTful API: How to model 'request new password'?

I am designing a RESTful API for a booking application and was quite happy to see I could map all details of the application to the 4 HTTP methods.
/users - GET, POST
/users/({id}|myself) - GET, POST, PUT, DELETE
/users/({id}|myself)/bookings - GET, POST
/users/({id}|myself)/bookings/{id} - GET, POST, PUT, DELETE
Example: Updating my own user uses a PUT to /users/myself.
But now I found out that one thing is missing: The possibility to request a new password if I forgot my old one. Any idea how I could add this?
Since the action is essentially an update -- a new password will generated -- I would use the POST verb. You'll have to figure out an alternative way of delivering the password unless you have already arranged some challenge/response protocol based on shared secrets that can be used to validate the requester in the absence of the password. The easiest way is probably to email the user at the account of record with a link that can be used to effect the change and display their new password.
Assuming by requesting a new password, you are referring to the typical action of the system assigning a new temporary password and then allowing the user to reset it, I would do somethign along the lines of:
POST : /users/myself/resetPassword
and then return the temporary password, send an email to the user or some other method of passing the new temp password back to the user.
/users/({id}|myself)/forgottenpassword/, GET or PUT
or just implement some way of telling the user to go to the website.