Using Hashids to protect the id in database - node.js

People get the data from url like http://domain/api/user/1 and the 1 is the id(primary key) in the database. We want to avoid this to prevent people detect the ids.
Then I found Hashids which can encode/decode the id to string, the url may change to http://domain/api/user/D42dhDLdk
It is a wonderful solution at the first glance, however how to use it in the real application?
1 encode
When records are retrieved from the database, we should encode the id to string, which is the right place to do this job? The only right place I can thought is the deserialization of the records, for example, when you serve data of json, you can encode the related ids to string, but you have to make sure which fields should be encoded.
For example:
{user:{id:1,name:'xx',projects:[{id:1,name:'p1',id:2,name:'p2'}]},icon_id:1}}
The id of the user project and the icon_id should be encoded, there are no clear rules to abstract that.
2 decode
You have to decode the string to id when retrieve the data from db, I think we can do this in the route or controller layer, however there are still no clear rules to make a abstract middleware to hanlde this, since the encoded string may exist in the url or the query params.
I have not find any general solution from google, so I wonder how do you handle this kind of problem?
Update:
I am using Mysql, and Express with sequelzie as the ORM tool.

Related

Contentful: How to get an entry using nothing but one of its fields? Or, how to set the entryId in web app?

I am needing to make some sharable blog post URLs. To do that, the URL must be something like webpage.com/blog-post-title. It cannot be webpage.com/5GFd5GDSg2345WD.
Since I am using dynamic routing, I need to get a Contentful entry using nothing but what is on the URL. There should not be any queries because queries are ugly and reduce shareability, like webpage.com/blog-post-title?query=queriesAreUgly.
Unfortunately, I need the entryId to get the entry. Also unfortunately, the entryIds are all very ugly and therefore completely useless/unusable. I wish I could set my own entryId, but this does not appear to be possible for mysterious reasons.
I could make a lookup table that pairs URLs with entryIds, but I'm going to be handing this contentful project to someone who is not tech savy, and they should not have to manage a lookup table.
I could get all blog entries then filter by blog title, but, very obviously, this is inefficient, as I would be loading thousands of lines of text for no reason at all.
I could create my own backend API and doing all this myself, but this is also a bad solution because it would take too much time and I could not give it to my non-tech-savvy client.
There are seemingly no solutions to this problem which created by Contentful's inherent needless inflexibility.
The only efficient way to get this to work is to find the entry not by its ID but by one of its fields. Is there a performant/efficient way to do this, or am I just going to have to filter through every single blog post until I find the one with the correct title?
How about adding a 'slug' field to the blog post content type, which you can auto-generate from the title using the field settings (so you don't have to type it out manually?)
You can then filter on the slug field in the query.
If you're using the JavaScript SDK (which it sounds like you are), you can use getEntries() and filter by the slug field to get a single blog post. Like so:
import { createClient } from "contentful";
const client = createClient({
space: {SPACE_ID},
accessToken: {ACCESS_TOKEN},
});
const response = await client
.getEntries({
content_type: "blogPost",
limit: 1,
"fields.slug": "blog-post-title",
})
.then((entry) => entry)
.catch(console.error);

Difference between operators in a URL

What's the difference between using : and ? in a URL? For example /products/:id and /products?id=1? I am trying to get the values from the URL like this Product.findById (req.params.id) but I was wondering which one is most suitable. I know using : do I have to use req.params and ? req.query but I don't understand the difference between them, are they the same?
in my point of view, it is totally different if you are using RESTFUL API pattern
/products/:id called path parameters
The path parameters determine the resource you’re requesting for. Think of it like an automatic answering machine that asks you to press 1 for service, press 2 for another service, 3 for yet another service and so on.
Path parameters are part of the endpoint itself and are not optional
but query parameters
Technically, query parameters are not part of the REST architecture, and they used to help you completely understand how to read and use API’s Query parameters give you the option to modify your request with key-value pairs.
Having your parameters in the query is conceptually optional to the router, query parameters are more of properties and descriptions of the request itself, like when saying GET /users?sort=asc, in this case, the sort attribute was more of a description to the request and the request could complete the fetch without it, that might not always be the case, but a query parameter still describes its request even if it was mandatory.
On the other hand, URL parameters are part of the request itself, the URL without the parameter doesn't make sense, like GET /users/:userID, in this case, not supplying userID will supply unexpected data (A list of users for example) if it didn't break the router completely. URL parameters play part in defining the request rather than just describing it, and they can't be optional.

When to use query and params to get url data in express

It seems that /patient/123 and /patient?id=123 will both work fine at the backend of my application.
I could do req.param.id and do req.query.id as well.
But I'm getting confused on when to use then. What are the cases that you should use params and what are the cases that you should use query. Because in the answer here, j_mcnally only mentioned that they're interchangeable.
Url params and url path are somewhat interchangeable. People usually use url path for describing restful resources...
So what are the possible pros and cons of using them.
The query string is usually modifiers to the resource you're running, while the path should give just enough info to let your back-end indentify the data you're requesting.
/patients/123 - patients in this case would be the namespace, and 123 would be the identifier. You can also extend this with:
/patients/123/profile where profile would be an identifier for a pre-defined collection of data.
Query string usually offers fine-grained control over what and how your resource presents data, for example:
/patients/123?fields=firstname,lastname,age - This is pretty self-explanatory, but basically the query string in this case modifies what data is returned.
/patients?orderby=age&order=desc&fields=firstname,lastname&limit=25 - This query string modifies both how and what data is returned, and that's the purpose of the query string in RESTful API's.

Looking up types from Freebase

I am trying to find a list of relevant types to a certain string from Freebase, lets say for example i enter Jordan, then i will have a list with types country, person, athlete .. etc.
I have found several ways for the query, for example:
First Query
trying to get the JSON fails, using:
$.getJSON('http://api.freebase.com/api/service/search?query=jordan',function (data) {
console.log(data);
});
There is another query that gives me better result, as i only get the types here but i also cannot get the JSON file from it.
Will appreciate any help.
Your problem has probably less to do with freebase and more to do the fact that you can't do cross domain http requests. You are requesting data from api.freebase.com but you are probably hosting this page in another domain.
You can use the JSONP mechanism to circumvent that restriction, here is some documentation:
http://api.jquery.com/jQuery.getJSON/
Read the section JSONP.
Another couple of points:
Are you trying to search for all entities that somehow match the word "jordan" or are you looking for exactly all the entities that are named "jordan" ? Your best bet is to use the /search API instead of /mqlread which is for structured database queries.
You are also using the legacy API that is deprecated. Here is some docs on the new API:
http://wiki.freebase.com/wiki/API
Here's how your request will look (note that you 'll need an API key for production):
https://www.googleapis.com/freebase/v1/search?query=jordan&mql_output=[{%22name%22%20:%20null,%22type%22:[]}]

Short and unique keys in CouchDB

I want to write a URL shortener as a standalone CouchApp, but I'm wondering if it is possible.
Obviously, a core requirement for a URL shortener is to have short and unique keys.
What I want is to POST a long URL to CouchDB and get a shortened URL. I thought about using an update handler, but it would have to query the DB to check if the key is unique, which seems not to be possible.
Is there a way to generate short and unique keys with CouchDB? Or do I need a thin wrapper around CouchDB?
I would go for a thin wrapper, based on documents with the following structure:
{ _id : short_url , url : long_url }
Inserting of a new long URL could be done in a single step: have the wrapper generate a new _id, attempt a PUT, and try again with a new _id until it succeeds. This will guarantee that every short URL is only used once.
I'm afraid this "generate, attempt, retry" approach is the only strategy that ensures uniqueness, and it's not available without a wrapper.
If you wish the same long URL to reuse the same short URL, you can also add a view that echo(doc.url,null) and grab the _id for your URL if it does exist. This means that, unless several clients try to add the same long URL at the exact same time, only one short URL will be used for that long URL.

Resources