Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 47 additions & 3 deletions carto/api_keys.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
PERMISSION_SELECT = "select"
PERMISSION_UPDATE = "update"
PERMISSION_DELETE = "delete"
PERMISSION_DELETE = "create"
SERVICE_GEOCODING = "geocoding"
SERVICE_ROUTING = "routing"
SERVICE_ISOLINES = "isolines"
Expand Down Expand Up @@ -79,32 +80,41 @@ class APIKeyManager(Manager):
json_collection_attribute = "result"
paginator_class = CartoPaginator

def create(self, name, apis=['sql', 'maps'], tables=None, services=None):
def create(self, name, apis=['sql', 'maps'], tables=None, schemas=None, services=None):
"""
Creates a regular APIKey.

:param name: The API key name
:param apis: Describes which APIs does this API Key provide access to
:param tables: Describes to which tables and which privleges on each table this API Key grants access to
:param schemas: Describes to which schemas and which privleges on each schema this API Key grants access to
:param services: Describes to which data services this API Key grants access to
:type name: str
:type apis: list
:type tables: TableGrant or dict
:type schemas: SchemaGrant or dict
:type services: list

:return: An APIKey instance with a token
"""
grants = []
database_grant = {'type': 'database'}
if not apis:
raise CartoException("'apis' cannot be empty. Please specify which CARTO APIs you want to grant. Example: ['sql', 'maps']")
grants.append({'type': 'apis', 'apis': apis})
if tables and (len(tables) > 0):
if isinstance(tables[0], dict):
grants.append({'type': 'database', 'tables': tables})
database_grant['tables'] = tables
elif isinstance(tables[0], TableGrant):
grants.append({'type': 'database', 'tables': [x.to_json for x in tables]})
database_grant['tables'] = [x.to_json for x in tables]
if schemas and (len(schemas) > 0):
if isinstance(schemas[0], dict):
database_grant['schemas'] = schemas
elif isinstance(schemas[0], SchemaGrant):
database_grant['schemas'] = [x.to_json for x in schemas]
if services:
grants.append({'type': 'dataservices', 'services': services})
grants.append(database_grant)
return super(APIKeyManager, self).create(name=name, grants=grants)


Expand Down Expand Up @@ -146,6 +156,40 @@ def to_json(self):
}


class SchemaGrant(Resource):
"""
Describes to which schemas and which privleges on each schema this API Key grants access to trough schemas attribute.
For example if you grant `create` on the user `public` schema, they will be able to run `CREATE TABLE AS...` SQL queries
This is an internal data type, with no specific API endpoints

See https://carto.com/developers/auth-api/reference/#section/API-Key-format

Example:

.. code::

{
"type": "database",
"schemas": [
{
"name": "public",
"permissions": [
"create"
]
}
]
}
"""
name = CharField()
permissions = CharField(many=True)

def to_json(self):
return {
'name': self.name,
'permissions': self.permissions
}


class Grants(Resource):
apis = CharField(many=True)
tables = TableGrantField(many=True)
Expand Down
1 change: 1 addition & 0 deletions carto/fields.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ class GrantsField(ResourceField):
type_field = {
'apis': 'apis',
'tables': 'database',
'schemas': 'database',
'services': 'dataservices'
}

Expand Down