Added check for user's roles -- disallow usage by non-subscribers.
This makes it clear from the get-go that users need to subscribe. Otherwise they'll get unexpected errors once they try to download something.
This commit is contained in:
parent
6ce4399407
commit
5eaee872bf
@ -269,9 +269,21 @@ class BlenderCloudBrowser(bpy.types.Operator):
|
|||||||
self.mouse_x = event.mouse_x
|
self.mouse_x = event.mouse_x
|
||||||
self.mouse_y = event.mouse_y
|
self.mouse_y = event.mouse_y
|
||||||
|
|
||||||
if self._state == 'BROWSING' and event.type == 'LEFTMOUSE' and event.value == 'RELEASE':
|
left_mouse_release = event.type == 'LEFTMOUSE' and event.value == 'RELEASE'
|
||||||
|
if self._state == 'PLEASE_SUBSCRIBE' and left_mouse_release:
|
||||||
|
self.open_browser_subscribe()
|
||||||
|
self._finish(context)
|
||||||
|
return {'FINISHED'}
|
||||||
|
|
||||||
|
if self._state == 'BROWSING':
|
||||||
selected = self.get_clicked()
|
selected = self.get_clicked()
|
||||||
|
|
||||||
|
if selected:
|
||||||
|
context.window.cursor_set('HAND')
|
||||||
|
else:
|
||||||
|
context.window.cursor_set('DEFAULT')
|
||||||
|
|
||||||
|
if left_mouse_release:
|
||||||
if selected is None:
|
if selected is None:
|
||||||
# No item clicked, ignore it.
|
# No item clicked, ignore it.
|
||||||
return {'RUNNING_MODAL'}
|
return {'RUNNING_MODAL'}
|
||||||
@ -286,7 +298,7 @@ class BlenderCloudBrowser(bpy.types.Operator):
|
|||||||
return {'RUNNING_MODAL'}
|
return {'RUNNING_MODAL'}
|
||||||
self.handle_item_selection(context, selected)
|
self.handle_item_selection(context, selected)
|
||||||
|
|
||||||
elif event.type in {'RIGHTMOUSE', 'ESC'}:
|
if event.type in {'RIGHTMOUSE', 'ESC'}:
|
||||||
self._finish(context)
|
self._finish(context)
|
||||||
return {'CANCELLED'}
|
return {'CANCELLED'}
|
||||||
|
|
||||||
@ -302,6 +314,10 @@ class BlenderCloudBrowser(bpy.types.Operator):
|
|||||||
|
|
||||||
try:
|
try:
|
||||||
await pillar.check_pillar_credentials()
|
await pillar.check_pillar_credentials()
|
||||||
|
except pillar.NotSubscribedToCloudError:
|
||||||
|
self.log.info('User not subscribed to Blender Cloud.')
|
||||||
|
self._show_subscribe_screen()
|
||||||
|
return
|
||||||
except pillar.CredentialsNotSyncedError:
|
except pillar.CredentialsNotSyncedError:
|
||||||
self.log.info('Credentials not synced, re-syncing automatically.')
|
self.log.info('Credentials not synced, re-syncing automatically.')
|
||||||
else:
|
else:
|
||||||
@ -311,6 +327,10 @@ class BlenderCloudBrowser(bpy.types.Operator):
|
|||||||
|
|
||||||
try:
|
try:
|
||||||
await pillar.refresh_pillar_credentials()
|
await pillar.refresh_pillar_credentials()
|
||||||
|
except pillar.NotSubscribedToCloudError:
|
||||||
|
self.log.info('User is not a Blender Cloud subscriber.')
|
||||||
|
self._show_subscribe_screen()
|
||||||
|
return
|
||||||
except pillar.UserNotLoggedInError:
|
except pillar.UserNotLoggedInError:
|
||||||
self.error('User not logged in on Blender ID.')
|
self.error('User not logged in on Blender ID.')
|
||||||
else:
|
else:
|
||||||
@ -321,6 +341,12 @@ class BlenderCloudBrowser(bpy.types.Operator):
|
|||||||
raise pillar.UserNotLoggedInError()
|
raise pillar.UserNotLoggedInError()
|
||||||
# self._new_async_task(self._check_credentials())
|
# self._new_async_task(self._check_credentials())
|
||||||
|
|
||||||
|
def _show_subscribe_screen(self):
|
||||||
|
"""Shows the "You need to subscribe" screen."""
|
||||||
|
|
||||||
|
self._state = 'PLEASE_SUBSCRIBE'
|
||||||
|
bpy.context.window.cursor_set('HAND')
|
||||||
|
|
||||||
def descend_node(self, node):
|
def descend_node(self, node):
|
||||||
"""Descends the node hierarchy by visiting this node.
|
"""Descends the node hierarchy by visiting this node.
|
||||||
|
|
||||||
@ -479,7 +505,7 @@ class BlenderCloudBrowser(bpy.types.Operator):
|
|||||||
self.log.debug('Browsing assets at project %r node %r', self.project_uuid, self.node_uuid)
|
self.log.debug('Browsing assets at project %r node %r', self.project_uuid, self.node_uuid)
|
||||||
self._new_async_task(self.async_download_previews())
|
self._new_async_task(self.async_download_previews())
|
||||||
|
|
||||||
def _new_async_task(self, async_task: asyncio.coroutine, future: asyncio.Future=None):
|
def _new_async_task(self, async_task: asyncio.coroutine, future: asyncio.Future = None):
|
||||||
"""Stops the currently running async task, and starts another one."""
|
"""Stops the currently running async task, and starts another one."""
|
||||||
|
|
||||||
self.log.debug('Setting up a new task %r, so any existing task must be stopped', async_task)
|
self.log.debug('Setting up a new task %r, so any existing task must be stopped', async_task)
|
||||||
@ -501,6 +527,7 @@ class BlenderCloudBrowser(bpy.types.Operator):
|
|||||||
'BROWSING': self._draw_browser,
|
'BROWSING': self._draw_browser,
|
||||||
'DOWNLOADING_TEXTURE': self._draw_downloading,
|
'DOWNLOADING_TEXTURE': self._draw_downloading,
|
||||||
'EXCEPTION': self._draw_exception,
|
'EXCEPTION': self._draw_exception,
|
||||||
|
'PLEASE_SUBSCRIBE': self._draw_subscribe,
|
||||||
}
|
}
|
||||||
|
|
||||||
if self._state in drawers:
|
if self._state in drawers:
|
||||||
@ -643,6 +670,11 @@ class BlenderCloudBrowser(bpy.types.Operator):
|
|||||||
blf.draw(font_id, line)
|
blf.draw(font_id, line)
|
||||||
bgl.glDisable(bgl.GL_BLEND)
|
bgl.glDisable(bgl.GL_BLEND)
|
||||||
|
|
||||||
|
def _draw_subscribe(self, context):
|
||||||
|
self._draw_text_on_colour(context,
|
||||||
|
'Click to subscribe to the Blender Cloud',
|
||||||
|
(0.0, 0.0, 0.2, 0.6))
|
||||||
|
|
||||||
def get_clicked(self) -> MenuItem:
|
def get_clicked(self) -> MenuItem:
|
||||||
|
|
||||||
for item in self.current_display_content:
|
for item in self.current_display_content:
|
||||||
@ -691,6 +723,13 @@ class BlenderCloudBrowser(bpy.types.Operator):
|
|||||||
future=signalling_future))
|
future=signalling_future))
|
||||||
self.async_task.add_done_callback(texture_download_completed)
|
self.async_task.add_done_callback(texture_download_completed)
|
||||||
|
|
||||||
|
def open_browser_subscribe(self):
|
||||||
|
import webbrowser
|
||||||
|
|
||||||
|
webbrowser.open_new_tab('https://cloud.blender.org/join')
|
||||||
|
|
||||||
|
self.report({'INFO'}, 'We just started a browser for you.')
|
||||||
|
|
||||||
|
|
||||||
# store keymaps here to access after registration
|
# store keymaps here to access after registration
|
||||||
addon_keymaps = []
|
addon_keymaps = []
|
||||||
|
@ -31,14 +31,15 @@ class UserNotLoggedInError(RuntimeError):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return 'UserNotLoggedInError'
|
return self.__class__.__name__
|
||||||
|
|
||||||
|
|
||||||
class CredentialsNotSyncedError(UserNotLoggedInError):
|
class CredentialsNotSyncedError(UserNotLoggedInError):
|
||||||
"""Raised when the user may be logged in on Blender ID, but has no Blender Cloud token."""
|
"""Raised when the user may be logged in on Blender ID, but has no Blender Cloud token."""
|
||||||
|
|
||||||
def __str__(self):
|
|
||||||
return 'CredentialsNotSyncedError'
|
class NotSubscribedToCloudError(UserNotLoggedInError):
|
||||||
|
"""Raised when the user may be logged in on Blender ID, but has no Blender Cloud token."""
|
||||||
|
|
||||||
|
|
||||||
class PillarError(RuntimeError):
|
class PillarError(RuntimeError):
|
||||||
@ -171,11 +172,24 @@ async def check_pillar_credentials():
|
|||||||
if not subclient:
|
if not subclient:
|
||||||
raise CredentialsNotSyncedError()
|
raise CredentialsNotSyncedError()
|
||||||
|
|
||||||
|
pillar_user_id = subclient['subclient_user_id']
|
||||||
|
if not pillar_user_id:
|
||||||
|
raise CredentialsNotSyncedError()
|
||||||
|
|
||||||
try:
|
try:
|
||||||
await get_project_uuid('textures') # Any query will do.
|
db_user = await pillar_call(pillarsdk.User.find, pillar_user_id)
|
||||||
except pillarsdk.UnauthorizedAccess:
|
except pillarsdk.UnauthorizedAccess:
|
||||||
raise CredentialsNotSyncedError()
|
raise CredentialsNotSyncedError()
|
||||||
|
|
||||||
|
roles = db_user.roles
|
||||||
|
log.debug('User has roles %r', roles)
|
||||||
|
if not roles or not {'subscriber', 'demo'}.intersection(set(roles)):
|
||||||
|
# Delete the subclient info. This forces a re-check later, which can
|
||||||
|
# then pick up on the user's new status.
|
||||||
|
del profile.subclients[SUBCLIENT_ID]
|
||||||
|
profile.save_json()
|
||||||
|
raise NotSubscribedToCloudError()
|
||||||
|
|
||||||
|
|
||||||
async def refresh_pillar_credentials():
|
async def refresh_pillar_credentials():
|
||||||
"""Refreshes the authentication token on Pillar.
|
"""Refreshes the authentication token on Pillar.
|
||||||
@ -197,7 +211,7 @@ async def refresh_pillar_credentials():
|
|||||||
|
|
||||||
# Test the new URL
|
# Test the new URL
|
||||||
_pillar_api = None
|
_pillar_api = None
|
||||||
await get_project_uuid('textures') # Any query will do.
|
await check_pillar_credentials()
|
||||||
|
|
||||||
|
|
||||||
async def get_project_uuid(project_url: str) -> str:
|
async def get_project_uuid(project_url: str) -> str:
|
||||||
|
Reference in New Issue
Block a user