Generating a secure key that restricts a user to a particular radius - algolia

I was thinking of using Algolia's Secured API Keys feature to limit my users' queries to a particular geographic area (e.g., 50 miles around their home location). The idea was that users shouldn't be able to search the entire system, only the part of it that is relevant to them, thus limiting overall exposure of database. Does the API support anything like this, or do I need to use the tagging feature to do something less specific, e.g., tagging records by the user's home state ("New York") and then restricting access based on that tag?

you should be able to do so by generating a specific API key with pre-filled search parameters for each of your user.
Each key will have a specific around lat lng parameter and a specific radius also.
The user will not be able to trick the key to use different pre-filled search parameters. But you can still use different parameters (that were not pre-filled).
First, you need to create a new search only api key in your dashboard.
Then, using the JavaScript (node.js) client for instance:
var public_key = client.generateSecuredApiKey('YourSearchOnlyApiKey', {aroundLatLng: '43.0909,23.99898', aroundRadius: 50 * 1000});
Then on the frontend, in the browser, using this new api key, your user will only be able to search for items around the provided latitude longitude with a 50km radius.
You can use any geo search parameter https://www.algolia.com/doc/rest#geo-search-parameters.
More infos:
https://www.algolia.com/doc/tutorials/security
https://github.com/algolia/algoliasearch-client-js#security--user-api-keys
Every other API client has the same paragraph.

Related

Bing maps Rest API objects not the same

I need to create an API services that calls Bing maps Rest API gets Address, Elevation and latitude and longitude values.
I see that there a Autosuggest that returns an Address object, I also see you have Find location by address api that also returns an Address object. My question is why both address object are not the same? and can it be the address adding the missing fields ?
As I need all the values from the address object from Autosuggest .I would like to call the Find location by address api and get a list of address with the latitude and longitude values as well. Currently I making 3 api calls
The autosuggest and Location APIs, do use the same Address class/object, however this is a lower-level property of the main response from each API.
The autosuggest API returns an autosuggest response that can contain a LocalBusiness, Place, or Address object. All of these have an address property that is an Address object. The __type property in these responses provide an additional insight on the type of result.
The location APIs, return a Location object that has an address property that is the same Address object used in the autosuggest API.
There are some differences in the response objects, but they all include the same Address object.
The autotsuggest responses do not include location details such as latitude/longitude as this information has a higher cost and including this information would mean this service would have to have the same cost per request as the Location API. By separating out this information, the Autosugget API only generates a 1/10th of a transaction per request (10 times cheaper than the Location API). Since in a normal autosuggest experience, a user will likely generate 5 to 10 requests to this service, when typing a single input, this makes the overall cost of this experience significantly cheaper. If each request was charged a full transaction, most companies would quickly find the cost of this experience to be extreme.
For your scenario, the expectation would be atleast 3 requests as defined below.
One or more to the autosuggest API with the users input.
One taking the formattedAddress value from the Address object in the autosuggest response and passing it into the location query API to get the latitude/longitude details.
One taking the latitude/longitude information into the elevation API. Note you can pass in multiple points into this API, and thus get the elevations for an array of address coordinates.

Filtering certain coins based upon name with CoinMarketCap

I'm currently attempting to use the CoinMarketCap API but finding it frustrating.
I'm wanting to use this URL to query their API:
https://pro-api.coinmarketcap.com/v1/cryptocurrency/listings/latest
However, rather than finding all, or just simply filtering based upon the number, I want to find a certain few coins.
So for example, I want to only find Bitcoin, Ethereum and Cardano.
Looking at their docs, it suggests you can sort by name, but it appears this is only listing them alphabetically, which I don't want to do.
So can anyone suggest how to query their API successfully and find just Bitcoin, Ethereum and Cardano using that GET URL above?
Here's the URL to the specific URL for the API request: https://coinmarketcap.com/api/documentation/v1/#operation/getV1CryptocurrencyListingsLatest
For this purpose, you can use the endpoint Quotes Latest:
https://pro-api.coinmarketcap.com/v1/cryptocurrency/quotes/latest
It allows you to pass a list of identifiers in a string as a parameter, like this:
1,1027,328
or a list of slugs:
bitcoin,ethereum,monero
or a list of symbols
BTC,ETH,XMR
If you trying to scrape information about new listings at crypto exchanges, you can be interested in this API:
https://rapidapi.com/Diver44/api/new-cryptocurrencies-listings/
It includes an endpoint with New Listings, New Pairs from the biggest exchanges and a very useful endpoint with information about exchanges where you can buy specific coins and prices for this coin at that exchange. It's a bit paid, but it's worth it!

HTTP request to search for multiple ObjectIds in a Mongo-based API?

I'm looking to add search functionality to an API, on a resource called Organizations. Organizations can have different Location and Audience ids tagged onto them (which I would like to use in searching). Since these ids are MongoDB ObjectIds, they are quite long and I'm worried about reaching the max query string limit of the browser with a GET request. For example:
GET http://my-site.com/api/organizations?locations=5afa54e5516c5b57c0d43227,5afa54e5516c5b57c0d43226,5afa54e5516c5b57c0d43225,5afa54e5516c5b57c0d43224&audiences=5afa54e5516c5b57c0d43223,5afa54e5516c5b57c0d43222
Which would probably be about an average search, however I don't want it to break if users select many Locations or Audiences.
Any advice on how I could handle this situation?
I've ran into your situation before. You can change your method to POST
For a input of locations and audiences, your resource is not already sitting there. You have to compute it.
By the definition of POST:
Perform resource-specific processing on the request payload.
Providing a block of data, such as the fields entered into an HTML
form, to a data-handling process;
You have to compute and create new resource for response. So it's REST-compliance to do so.

How to efficiently check database object based on location/proximity to user's location?

I am constructing an app (in XCode) which, in a general sense, displays information to users. The information is stored as individual objects in a database (happens to be a Parse-server hosted by heroku). The user can elect to "see" information that has been created within a set distance from their current location. (The information, when saved to the DB, is saved along with its lat and long based on the location of the user when they initiated the save). I know I can filter the pieces of information by comparing their lat and long to the viewing user's current lat and long and only display those which are close in enough. Roughly/generally:
var currentUserLat = latitude //latitude of user's current location
var infoSet = [Objects] //set of all pulled info from DB
for info in infoSet{
if info.lat-currentUserLat < 3{//arbitrary value
//display the info
}else{
//don't display
}
}
This is set up decently enough, and it works fine. The reason it works fine, though, is because of the small number of entries in the DB at this current time (the app is in development). Under practical usage (ie many users) the DB may be full of information objects (lets say, a thousand). In my opinion, to individually pull and compare the latitude of the information and compare it to the current user's latitude for each and every DB entry would take too long. I know there must be a way to do it in a timely manner (think tinder... they only display profiles of people who are in the near vicinity and it doesn't take that long for them to do so despite millions of profiles) but I do not know what is most efficient. I thought of creating separate sections for different geographical regions in the DB and then only searching those particular section of the DB depending on where the user's current location is, but this seems unsophisticated and would still lead to large amounts of info being pulled. What is the best way to do this?
Per Deploying a Parse Server to Heroku you can Install a MongoDB add-on or another of the Data Stores in the Add-on Category in which you can use Geospatial Indexes and Queries which are specifically intended for this sort of application.
Is there a reason you need to do that sort of checking on the client side? I would suggest sending your coordinates to your server and then having the server query your database with those coordinates and figure out which items to pull based on the given coordinates respectively. Then you can have the server return back to the client side whichever items were "close" to that user
EDIT: reworded

Multi-tenant Algolia index

I would like to offer full-text search to my users through their data - and make sure that they can only access the data they own. Are there any patterns allowing to do that on Algolia ? None of the solutions I've considered seem a good fit, so i was wondering if I had overlooked some other options.
We could host each user's data in a separate Algolia app, so that each API key would give access to only the relevant data, but that would quickly become unaffordable, as many would hit the 10000 records limit.
We could host each user's data in a separate index and use team index restrictions, but there does not seem to be an API to manage those, and that would anyway require an Algolia account for each customer, which seems like a misuse of the service (we could e.g. generate email addresses at our domain name).
Finally we could filter queries with some userId to retrieve only the relevant data, but that wouldn't be secure, as someone could use the apikey to query algolia without the filter.
We could proxy algolia calls to inject the filter and the api key - but the perf penalty would probably be high.
Any other suggestions ? Thanks!
I got a great answer from rayrutjes at Algolia, so I'm pasting it here in case :
The best approach for your use case is to use what we call generated API keys. Here is the documentation for the JavaScript client: https://www.algolia.com/doc/api-client/javascript/api-keys/#generate-key
The usage is fairly simple, you generate an API key on the fly based on your search API key + some additional query params.
The resulting API key can be used like a standard search API key, with the difference that it can be scoped on a given set of parameters.
Note that the generation of such a scoped API key does not require an actual call to the API.
Also be sure to generate those scoped API keys in the backend as in that case you don't want to expose the search API key you use for their generation.