1. Data APIs on a Postgres database
2. Deploy with git-push, or any docker image
3. Expose HTTP services on the API gateway over subdomains/paths
4. Automatic LetsEncrypt SSL cert generation for exposed http services
5. SSH service to get tunnelled access to TCP services on your cluster
6. Auth middleware built into the API gateway, so that upstream services don't have to resolve sessions
7. Out of the box auth APIs for password, email, recaptcha, social login. mobile-OTP stuff
First impressions: very little magics/transparent, reasonable pieces, reasonable architecture, well packaged, nicely automated, descriptive UI, no glaring wtfs, all the bases are covered, looks easy enough to customize at any layer with skills I already have — all very sensible.
Transparency: I felt like it wouldn't be hard to figure out what was going on behind each step. First guess easy vs black box not-so-fun.
Overall easy to grok created app plus Hasura meta data associations and transformation points.
Agreed that built in ACLs and Baas is really fantastic.
* for the host-your-own version are there any HA features for Postgres?
* what language is it written in? GitHub link?
Not right now. This is definitely on our roadmap though.
> what language is it written in? GitHub link?
It's mostly in Haskell, with smatterings of Python. Planning to open source it soon!
I ask because I'm currently using LB for a project and while I actually like it a lot I always like to be aware of alternatives and similar tools that I might need in the future.
Key value-prop differences are that out-of-box APIs are just one part of Hasura. The idea is to make it easy to integrate with community services (containerised) or deploy your own services in whatever language/stack.
Some other specific differences:
1. Hasura Data API is a graphql like query language to Postgres.
2. Deployment is similar to Heroku. So you deploy code in any language/framework
3. Nginx based API gateway behaves like a session middleware, so that any upstrea service can re-use auth
One minor nit: It is quite nice that you provide links to jump to the right place for each step, but I would suggest adding images of the equivalent spot to click in the UI.
So, what's the registration code?
Thanks ! Alas, Tanmai (our CTO) will quote this at us for the foreseeable future, this being his idea.
> So, what's the registration code?
This is just something that is used with the startups and incubators we partner with. You can ignore this.
The logo is by https://twitter.com/shmunday
Cartoons by http://www.sandhyaprabhat.com/
One thing that concerns me is the "Don't make changes to your Postgres schema outside of the UI, it'll mess things up" warning. If I already have a tool to manage database migrations, it sounds like using it with this would be a bad idea?
Edit: Also, what accounts for the speed increase over a bare VM? I'm assuming something Hasura does for you, but it would be nice to know what that is.
Hasura is indeed kind of what you described.
The warning on the UI is mostly for non power-users who probably don't have a good db migration kind of practice. Underneath, the Hasura data API stores its minimal metadata within Postgres itself.
That means that you can always use Postgres directly, and your migration tool works exactly the way it should. Whenever your schema migrations affect a data API, you need to ensure a metadata update for the Data API as well. We're going to be publishing examples of how DB migrations look using just a raw SQL setup, and an alembic setup!
The speed increase for the Data APIs is because of a few reasons:
1) Efficient serialization/deserialization of the JSON queries and responses (https://hackage.haskell.org/package/aeson)
2) Prepared statements
3) JSON aggregations done within Postgres (not generating the JSON)
4) Every client API call needs to be authenticated. The authentication is done by a efficient middleware written inside nginx with redis as the session store. The data API layer, then just does the authorization (this user-id can access this row).
(I'm from postgrest core team, probably competing with hasura in the future here https://graphqlapi.com)
Well actually we do infer directly from the Postgres schema. Only for users not familiar with Postgres directly, we recommend going through the UI so that not only is the table created, but the Data API is also asked to track it and provide an API for it.
There is other metadata that we do need the user to specify, via the UI or the API, and that's for stuff like permissions and relationships.
Regarding, the unrestricted querying, we address it in one of the following ways:
1. Timing out queries running for longer than a specified interval.
2. Cursors and streaming data if the dataset requested is large.
3. Query templates: We allow the developer to create a RESTful API endpoint that has a limited pre-defined surface area (eg: GET data.mysite.com/v1/template/article?limit=10) which internally maps to a pre-defined query.
Our docs are still lagging behind on these unfortunately!
What do you guys do to restrict access? Any suggestions?
timing out - it works up to a point, if you for example set a hard limit to 1s then to an attacker it just means he needs to do a few parallel requests and he still kills your db.
what postgrest does for protection:
a - no fancy joins, joins are only done by a thing we call "embedding" and those are joins between tables that FKs defined between them so they are fast, if you need fancy joins then the user has to define the view doing the join and expose it to the api.
b - no functions applied to the return columns, like you cant generate something like "select md5(bigtextcolumn) ..."
c - the only way to "kill" the database under postgrest is to use a filter on a column that has no index ( name like "hello"), out of the box postgrest does not have protection build in for that, but it's easy to put a proxy in front and whenever there is a url parameter called "name" you just reply with "you are not allowed to filter by this column"
> about metadata: in Postgrest ..
We don't want to restrict the data service to a particular schema. You can add a table from any schema to be tracked, say information_schema or pg_catalog. In fact, that is how introspection works (you can look at the queries made by the console). This means that the schema cache in memory would be quite large because of the number of tables in information_schema/pg_catalog if we were to auto load all these. There is also the issue that you may not want to expose some tables. We can definitely have a console button which will let you import all the tables in public schema.
Sure, you can infer relationships from the foreign key constraints. But, how would you come up with names that do not conflict with the existing columns? What if you add a new column with the same name as an inferred relationship? With the data service, you can also define relationships on/to views across schemas (1). Making metadata explicit goes with one of our core principles, 'no magic'.
> what postgrest does for protection: a - no fancy joins,
explicit joins are not allowed even with our data service. The joins that happen are the implicit ones because of the relationships. We do the same thing if we need any custom joins/aggregations. Define a view and expose it.
> b -
you can't do anything other than selecting columns and relationships with the api.
> c -
the permission layer can be used to prevent these to some extent (like not allowing an anonymous user to filter on a particular column).
- b,c that's good that you don't expose the entire SQL
also there is a way to do it in a single query but that is not yet implemented in postgrest
I guess it might be convenient to do this (determine relationships across views), but the users should be aware of the guarantees offered in this scenario.
True. That would also mean creating a database user for every application user. The auth service needs to attach more metadata to the users and since postgres does not allow you to reference system catalogs, the two user systems have to be kept in sync. We were not quite certain how this idea of mapping users would pan out when we started building the auth service.
Edit - realized that only the IIT talk wasn't a link. On mobile.
Also, creating permissions and roles are all exposed via API calls, in case you have a requirement where you need to create these dynamically.
In this case, say select is allowed if: req_user_id is in article.viewers.user_id. This means, if the request's user_id is in the viewers list of the article.
It depends on the fact, that you have a relationship called viewers which comes from a table that contains article_id, user_id.
The idea is to allow any ACL rule that can be represented as a constraint in your data model.
So if you want to customise the controller, the easiest thing to do is to write a custom API endpoint (which you can deploy to your server using a heroku style git-push or a docker image) which in turn can contact the data APIs or even the Postgres database directly.
If you want to install on your own, we will be releasing docs over the next 2 weeks.