It is now possible, only for user with admin capability, to setup a project as ‘film’. This action can be performed via CLI using ./manage.py cloud setup_for_film <project_url> or via the web interface in the Cloud settings area. Setting up a project for film creates a number of extension props under the ‘cloud’ key. Such properties are listed in the cloud_extension_props variable in setup.py. At this moment the functionality exists for a very specific purpose: improving the presentation of public Film projects in the Blender Cloud. It can be further extended to improve the presentation of Training and Libraries later on.
152 lines
4.7 KiB
Python
152 lines
4.7 KiB
Python
import logging
|
|
|
|
import flask
|
|
from werkzeug.local import LocalProxy
|
|
|
|
import pillarsdk
|
|
import pillar.auth
|
|
from pillar.api.utils import authorization
|
|
from pillar.extension import PillarExtension
|
|
|
|
EXTENSION_NAME = 'cloud'
|
|
|
|
|
|
class CloudExtension(PillarExtension):
|
|
has_context_processor = True
|
|
user_roles = {'subscriber-pro', 'has_subscription'}
|
|
user_roles_indexable = {'subscriber-pro', 'has_subscription'}
|
|
|
|
user_caps = {
|
|
'has_subscription': {'can-renew-subscription'},
|
|
}
|
|
|
|
def __init__(self):
|
|
self._log = logging.getLogger('%s.CloudExtension' % __name__)
|
|
|
|
@property
|
|
def name(self):
|
|
return EXTENSION_NAME
|
|
|
|
def flask_config(self):
|
|
"""Returns extension-specific defaults for the Flask configuration.
|
|
|
|
Use this to set sensible default values for configuration settings
|
|
introduced by the extension.
|
|
|
|
:rtype: dict
|
|
"""
|
|
|
|
# Just so that it registers the management commands.
|
|
from . import cli
|
|
|
|
return {
|
|
'EXTERNAL_SUBSCRIPTIONS_MANAGEMENT_SERVER': 'https://store.blender.org/api/',
|
|
'EXTERNAL_SUBSCRIPTIONS_TIMEOUT_SECS': 10,
|
|
'BLENDER_ID_WEBHOOK_USER_CHANGED_SECRET': 'oos9wah1Zoa0Yau6ahThohleiChephoi',
|
|
'NODE_TAGS': ['animation', 'modeling', 'rigging', 'sculpting', 'shading', 'texturing', 'lighting',
|
|
'character-pipeline', 'effects', 'video-editing', 'digital-painting', 'production-design',
|
|
'walk-through'],
|
|
}
|
|
|
|
def eve_settings(self):
|
|
"""Returns extensions to the Eve settings.
|
|
|
|
Currently only the DOMAIN key is used to insert new resources into
|
|
Eve's configuration.
|
|
|
|
:rtype: dict
|
|
"""
|
|
|
|
return {}
|
|
|
|
def blueprints(self):
|
|
"""Returns the list of top-level blueprints for the extension.
|
|
|
|
These blueprints will be mounted at the url prefix given to
|
|
app.load_extension().
|
|
|
|
:rtype: list of flask.Blueprint objects.
|
|
"""
|
|
from . import routes
|
|
import cloud.stats.routes
|
|
return [
|
|
routes.blueprint,
|
|
cloud.stats.routes.blueprint,
|
|
]
|
|
|
|
@property
|
|
def template_path(self):
|
|
import os.path
|
|
return os.path.join(os.path.dirname(__file__), 'templates')
|
|
|
|
@property
|
|
def static_path(self):
|
|
import os.path
|
|
return os.path.join(os.path.dirname(__file__), 'static')
|
|
|
|
def context_processor(self):
|
|
return {
|
|
'current_user_is_subscriber': authorization.user_has_cap('subscriber')
|
|
}
|
|
|
|
def is_cloud_project(self, project):
|
|
"""Returns whether the project is set up for Blender Cloud.
|
|
|
|
Requires the presence of the 'cloud' key in extension_props
|
|
"""
|
|
|
|
try:
|
|
pprops = project.extension_props[EXTENSION_NAME]
|
|
except AttributeError:
|
|
self._log.warning("is_cloud_project: Project url=%r doesn't have any "
|
|
"extension properties.", project['url'])
|
|
if self._log.isEnabledFor(logging.DEBUG):
|
|
import pprint
|
|
self._log.debug('Project: %s', pprint.pformat(project.to_dict()))
|
|
return False
|
|
except KeyError:
|
|
# Not set up for Blender Cloud
|
|
return False
|
|
|
|
if pprops is None:
|
|
self._log.debug("is_cloud_project: Project url=%r doesn't have Blender Cloud"
|
|
" extension properties.", project['url'])
|
|
return False
|
|
return True
|
|
|
|
@property
|
|
def has_project_settings(self) -> bool:
|
|
# Only available for admins
|
|
return pillar.auth.current_user.has_cap('admin')
|
|
|
|
def project_settings(self, project: pillarsdk.Project, **template_args: dict) -> flask.Response:
|
|
"""Renders the project settings page for this extension.
|
|
|
|
Set YourExtension.has_project_settings = True and Pillar will call this function.
|
|
|
|
:param project: the project for which to render the settings.
|
|
:param template_args: additional template arguments.
|
|
:returns: a Flask HTTP response
|
|
"""
|
|
|
|
from cloud.routes import project_settings
|
|
|
|
return project_settings(project, **template_args)
|
|
|
|
def setup_app(self, app):
|
|
from . import routes, webhooks, eve_hooks, email
|
|
|
|
routes.setup_app(app)
|
|
app.register_api_blueprint(webhooks.blueprint, '/webhooks')
|
|
eve_hooks.setup_app(app)
|
|
email.setup_app(app)
|
|
|
|
|
|
def _get_current_cloud():
|
|
"""Returns the Cloud extension of the current application."""
|
|
return flask.current_app.pillar_extensions[EXTENSION_NAME]
|
|
|
|
|
|
current_cloud = LocalProxy(_get_current_cloud)
|
|
"""Cloud extension of the current app."""
|