Introducing Project creation

Authorised users can now create projects. The before and after insert
projects hooks take care of stripping unwanted urls and attaching
default node_type and permissions, as well as initialising a storage
bucket per project. We are temporarily switching to the development
version of the gcloud library, since it allows the creation of EU-based
buckets.
This commit is contained in:
Francesco Siddi 2016-03-24 15:16:37 +01:00
parent 90693595a6
commit a33e4421a8
4 changed files with 141 additions and 3 deletions

View File

@ -0,0 +1,85 @@
import logging
from flask import g
from flask import abort
from eve.methods.put import put_internal
from eve.methods.post import post_internal
from application import app
from application.utils import remove_private_keys
from application.utils.gcs import GoogleCloudStorageBucket
from manage.node_types.asset import node_type_asset
from manage.node_types.group import node_type_group
from manage.node_types.page import node_type_page
from manage.node_types.comment import node_type_comment
log = logging.getLogger(__name__)
def before_inserting_projects(items):
"""Strip unwanted properties, that will be assigned after creation. Also,
verify permission to create a project (check quota, check role).
:param items: List of project docs that have been inserted (normally one)
"""
for item in items:
item.pop('url', None)
def after_inserting_projects(items):
"""After inserting a project in the collection we do some processing such as:
- apply the right permissions
- define basic node types
- optionally generate a url
- initialize storage space
:param items: List of project docs that have been inserted (normally one)
"""
current_user = g.get('current_user', None)
users_collection = app.data.driver.db['users']
user = users_collection.find_one({'_id': current_user['user_id']})
for item in items:
# Create a project specific group (with name matching the project id)
project_group = dict(name=str(item['_id']))
group = post_internal('groups', project_group)
# If Group creation failed, stop
# TODO: undo project creation
if group[3] != 201:
abort(group[3])
else:
group = group[0]
# Assign the current user to the group
if 'groups' in user:
user['groups'].append(group['_id'])
else:
user['groups'] = [group['_id']]
put_internal('users', remove_private_keys(user), _id=user['_id'])
# Assign the group to the project with admin rights
permissions = dict(
world=['GET'],
users=[],
groups=[
dict(group=group['_id'],
methods=['GET', 'PUT', 'POST'])
]
)
# Assign permissions to the project itself, as well as to the node_types
item['permissions'] = permissions
node_type_asset['permissions'] = permissions
node_type_group['permissions'] = permissions
node_type_page['permissions'] = permissions
node_type_comment['permissions'] = permissions
# Assign the basic 'group', 'asset' and 'page' node_types
item['node_types'] = [
node_type_group,
node_type_asset,
node_type_page,
node_type_comment]
# TODO: Depending on user role or status, assign the url attribute
# Initialize storage page (defaults to GCS)
gcs_storage = GoogleCloudStorageBucket(str(item['_id']))
if gcs_storage.bucket.exists():
log.debug("Created CGS bucket {0}".format(item['_id']))
# Assign a url based on the project id
item['url'] = "p-{}".format(item['_id'])
# Commit the changes
put_internal('projects', remove_private_keys(item), _id=item['_id'])

View File

@ -26,9 +26,17 @@ class GoogleCloudStorageBucket(object):
def __init__(self, bucket_name, subdir='_/'): def __init__(self, bucket_name, subdir='_/'):
gcs = Client() gcs = Client()
self.bucket = gcs.get_bucket(bucket_name) try:
self.bucket = gcs.get_bucket(bucket_name)
except NotFound:
self.bucket = gcs.bucket(bucket_name)
# Hardcode the bucket location to EU
self.bucket.location = 'EU'
self.bucket.create()
self.subdir = subdir self.subdir = subdir
def List(self, path=None): def List(self, path=None):
"""Display the content of a subdir in the project bucket. If the path """Display the content of a subdir in the project bucket. If the path
points to a file the listing is simply empty. points to a file the listing is simply empty.

View File

@ -9,10 +9,12 @@ from flask.ext.script import Manager
# Use a sensible default when running manage.py commands. # Use a sensible default when running manage.py commands.
if not os.environ.get('EVE_SETTINGS'): if not os.environ.get('EVE_SETTINGS'):
settings_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'settings.py') settings_path = os.path.join(os.path.dirname(os.path.abspath(__file__)),
'settings.py')
os.environ['EVE_SETTINGS'] = settings_path os.environ['EVE_SETTINGS'] = settings_path
from application import app from application import app
from application.utils.gcs import GoogleCloudStorageBucket
from manage.node_types.asset import node_type_asset from manage.node_types.asset import node_type_asset
from manage.node_types.blog import node_type_blog from manage.node_types.blog import node_type_blog
from manage.node_types.comment import node_type_comment from manage.node_types.comment import node_type_comment
@ -106,6 +108,45 @@ def setup_db():
print("Created user {0}".format(user[0]['_id'])) print("Created user {0}".format(user[0]['_id']))
# TODO: Create a default project # TODO: Create a default project
groups_collection = app.data.driver.db['groups']
admin_group = groups_collection.find_one({'name': 'admin'})
default_permissions = dict(
world=['GET'],
users=[],
groups=[
dict(group=admin_group['_id'],
methods=['GET', 'PUT', 'POST'])
]
)
node_type_blog['permissions'] = default_permissions
node_type_post['permissions'] = default_permissions
node_type_comment['permissions'] = default_permissions
project = dict(
owners=dict(users=[], groups=[]),
description='Default Project',
name='Default Project',
node_types=[
node_type_blog,
node_type_post,
node_type_comment
],
status='published',
user=user[0]['_id'],
is_private=False,
permissions=default_permissions,
url='default-project',
summary='Default Project summary',
category='training'
)
project = post_internal('projects', project)
print("Created default project {0}".format(project[0]['_id']))
gcs_storage = GoogleCloudStorageBucket(str(project[0]['_id']))
if gcs_storage.bucket.exists():
print("Created CGS instance")
@manager.command @manager.command

View File

@ -6,7 +6,7 @@ Eve==0.5.3
Events==0.2.1 Events==0.2.1
Flask-Script==2.0.5 Flask-Script==2.0.5
flup==1.0.2 flup==1.0.2
gcloud==0.11.0 -e git+https://github.com/GoogleCloudPlatform/gcloud-python.git@dbb22a7fddcf12228bba7b191774f2c4a2adfe35#egg=gcloud
google-apitools==0.4.11 google-apitools==0.4.11
httplib2==0.9.2 httplib2==0.9.2
idna==2.0 idna==2.0
@ -22,3 +22,7 @@ simplejson==3.8.1
WebOb==1.5.0 WebOb==1.5.0
wheel==0.24.0 wheel==0.24.0
zencoder==0.6.5 zencoder==0.6.5
# development requirements
httpretty==0.8.14
pytest==2.9.1