Skip to content

Multilayer API Private maps (draft)

javi santana edited this page Dec 4, 2013 · 13 revisions

introduction

This document describes the API to access tiles of protected tables. Before that there is an overview of different access types and how they are used from CartoDB point of view.

access types from user point of view

There are 3 kinds of access for maps, these permissions are different from table permissions names (public/private):

  • (A) public:

    1. a table is public and can be accessed by the tiler and sql api (implemented)
  • (B) private:

    1. a table is private and can be accessed only using api_key (implemented, used only by CartoDB UI)
  • (C) protected:

    1. a table is private and can be accesed by the tiler only with some access token (!= api_key) (not implemented)

Use cases from CartoDB perspective

CartoDB uses visualizations that allow cartodb user to publish the map. There are some usecases we want to provide and tiler should be able to manage with its API:

  1. Anyone on Internet can see a visualization and access the data (public access)
  2. Anyone on Internet can see a visualization (public access)
  3. Only those with a link: Only those who receive the link. (public access)
  4. Only people with a link and a password: You will set a password (protected access)
  5. Only other users of your organization (protected access)
  6. Only you (private or protected access)

so all the proposed use cases are covered by the 3 access models.

Windshaft API

In this section the API for using protected(C) access is described. private and public access are already described in https://github.com/CartoDB/Windshaft/wiki/Multilayer-API.

protected layergroup (C)

A protected layergroup is a layergroup that is created with admin permissions and whose access is managed by access token. Let's call them 'named layergroups'

// layergroup.json 
{
  "version": "1.1.0",
  // Variables not listed here are not substituted
  // Required variable not provided at instantiation time trigger an error
  // A default is required for optional variables
  // Specifying a type serves the purpose of proper quoting, to avoid injections
  "template_variables": {
      color: { type:'string', default:'red' }, // required:false by default
      cartodb_id: { type:'number', required:true, default: 1 } // default still required for map validation
  },
  "auth": {
      tokens: [
        'abcdef',
        '123456',
        'asdasd',
      ]
  },
  "layers": [{
    "type": "cartodb",
    "options": {
      "cartocss_version": "2.1.1", 
      "cartocss": "#layer { polygon-fill: #FFF; line-color: <%= color %> }",
      "sql": "select * from european_countries_e where cartodb_id = <%= cartodb_id %> }"
    }
  }]
}

creating named layergroup

to create the same call is used but api_key is needed (only https endpoint)

curl 'https://documentation.cartodb.com/tiles/layergroup/template?api_key=APIKEY' -d @layergroup.json

response:

{
   "layergroupid":"jkjlkj3l4kj3j43kj4",
   "last_updated":"2013-11-14T11:20:15.000Z"
}

using named layergroup

Once it's created a client could get a layergroup to render tiles (notice no layergroup definition is sent):

curl -d '' 'https://documentation.cartodb.com/tiles/layergroup/jkjlkj3l4kj3j43kj4?token=12345&template_id=10' 

response:

{
   "layergroupid":"c01a54877c62831bb51720263f91fb33:123456788",
   "last_updated":"2013-11-14T11:20:15.000Z"
}

to fetch a tile a valid token should be used:

curl 'https://documentation.cartodb.com/tiles/layergroup/c01a54877c62831bb51720263f91fb33:123456788/0/0/0.png?token=VALIDTOKEN'

probably this tiles should contain a Subrogate Key including the layergroup name and the token in case they need to be invalidated

updating

same request than is done to create it. At this point, if the tokens are modified, the layergroups created from this named layergroups should stop working

removing named layergroup

these named layergroups are persisted until are deleted:

curl -X DELETE 'https://documentation.cartodb.com/tiles/layergroup/name?api_key=APIKEY'

should return a 204 and the layergroups created from this named layergroups should stop working

listing

since named layergroups are persistent a listing API is needed

curl 'http://documentation.cartodb.com/tiles/layergroup'

returns a list of protected layergroups:

{
    layergroups: [ 
        { /* layer definition */ },
        { /* layer definition */ },
        { /* layer definition */ }
    ]
}

options

Option type Default Description
api_key string mandatory allow access to private layergroups
tables string array null return layergroups that use one of those tables

example

curl 'http://documentation.cartodb.com/tiles/layergroup?tables=table_a,table_b&api_key=APIKEY

template language

The template language would support:

- numbers
- strings

there should be some escape mechanism there should be the same than the used for sql named queries (https://github.com/CartoDB/CartoDB-SQL-API/wiki/Named-Queries-API) it ideally should take care of sql injection issues

proposals:

  • mustache way: {varname:type}
  • python/printf way: "%type(varname)"
  • underscore way: "<%= varname %>" (already used by both node apps)

some other notes

  • as layergroups need to be persistent we need to think where is the best place. I wouldn't discuss this at this point, we should think about what is the right API and then move to the implementation details.
  • named layergroups are also a nice way to create persistent maps (like basemaps)
  • I'm assuming that we will be able to invalidate CDN. If not we should set a reasonable ttl (i.e using max-age or expires) for CDN
  • I described the usecases for CartoDB but also covers the typical usecase where a third party wants to include a map for an auth user with private data in their web app.
  • I don't discuss the management of table permissions. They are managed by a third service (in our case CartoDB rails app). If the tiler does not have permissions to access a table, an error is reported (forbidden)
  • we know that a public map for a private table could be used to extract the data from the table using interactivity. We are ok with that, if the user want to keep his data as secret as possible he should use protected maps where the layergroup definition can't be changed
  • In order to validate the creation of a "named layergroup" we'll need default values for any template parameter (for a test instantiation)