[Bf-extensions-cvs] [84a9344] master: Fix T49008: Blender-ID add-on for inclusion as OFFICIAL
Sybren A. Stüvel
noreply at git.blender.org
Sun Aug 7 11:37:58 CEST 2016
Commit: 84a93440fd5c5ecbe80d7bb9743c1747d0bde3eb
Author: Sybren A. Stüvel
Date: Sun Aug 7 11:37:23 2016 +0200
Branches: master
https://developer.blender.org/rBA84a93440fd5c5ecbe80d7bb9743c1747d0bde3eb
Fix T49008: Blender-ID add-on for inclusion as OFFICIAL
Added Blender-ID add-on version 1.2.0.
For more info, see the repository at
https://developer.blender.org/diffusion/BIA/
To bundle a new version, run this from the Blender-ID add-on source:
python3 setup.py bdist bundle --path /path/to/blender/release/scripts/addons
===================================================================
A blender_id/README.md
A blender_id/__init__.py
A blender_id/communication.py
A blender_id/profiles.py
===================================================================
diff --git a/blender_id/README.md b/blender_id/README.md
new file mode 100644
index 0000000..936e6e3
--- /dev/null
+++ b/blender_id/README.md
@@ -0,0 +1,109 @@
+Blender ID addon
+================
+
+This addon allows you to authenticate your Blender with your
+[Blender ID](https://www.blender.org/id/) account. This authentication
+can then be used by other addons, such as the
+[Blender Cloud addon](https://developer.blender.org/diffusion/BCA/)
+
+Blender compatibility
+---------------------
+
+Blender ID add-on version 1.2.0 removed some workarounds necessary for
+Blender 2.77a. As such, versions 1.1.x are the last versions compatible with
+Blender 2.77a, and 1.2.0 and newer require at least Blender 2.78.
+
+Building & Bundling
+-------------------
+
+* To build the addon, run `python3 setup.py bdist`
+* To bundle the addon with Blender, run `python3 setup.py bdist bundle --path
+ ../blender-git/blender/release/scripts/addons`.
+* If you don't want to bundle, you can install the addon from Blender
+ (User Preferences → Addons → Install from file...) by pointing it to
+ `dist/blender_id*.addon.zip`.
+
+
+Using the addon
+---------------
+
+* Install the addon as described above.
+* Enable the addon in User Preferences → Addons → System.
+* Sign up for an account at the
+ [Blender ID site](https://www.blender.org/id/) if you don't have an
+ account yet.
+* Log in with your Blender ID and password. You only have to do this
+ once.
+
+Your password is never saved on your machine, just an access token. It
+is stored next to your Blender configuration files, in
+
+* Linux and similar: `$HOME/.config/blender/{version}/config/blender_id`
+* MacOS: `$HOME/Library/Application Support/Blender/{version}/config/blender_id`
+* Windows: `%APPDATA%\Blender Foundation\Blender\{version}\config\blender_id`
+
+where `{version}` is the Blender version.
+
+
+Using the addon from another addon
+----------------------------------
+
+The following functions can be used from other addons to use the Blender
+ID functionality:
+
+**blender_id.get_active_profile()** returns the `BlenderIdProfile` that
+represents the currently logged in user, or `None` when the user isn't
+logged in:
+
+ lang=python
+ class BlenderIdProfile:
+ user_id = '41234'
+ username = 'username at example.com'
+ token = '41344124-auth-token-434134'
+
+
+**blender_id.get_active_user_id()** returns the user ID of the logged
+in user, or `''` when the user isn't logged in.
+
+**blender_id.is_logged_in()** returns `True` if the user is logged
+in, and `False` otherwise.
+
+
+Here is an example of a simple addon that shows your username in its
+preferences panel:
+
+ lang=python,name=demo_blender_id_addon.py
+ # Extend this with your info
+ bl_info = {
+ 'name': 'Demo addon using Blender ID',
+ 'location': 'Add-on preferences',
+ 'category': 'System',
+ 'support': 'TESTING',
+ }
+
+ import bpy
+
+
+ class DemoPreferences(bpy.types.AddonPreferences):
+ bl_idname = __name__
+
+ def draw(self, context):
+ import blender_id
+
+ profile = blender_id.get_active_profile()
+ if profile:
+ self.layout.label('You are logged in as %s' % profile.username)
+ else:
+ self.layout.label('You are not logged in on Blender ID')
+
+
+ def register():
+ bpy.utils.register_module(__name__)
+
+
+ def unregister():
+ bpy.utils.unregister_module(__name__)
+
+
+ if __name__ == '__main__':
+ register()
diff --git a/blender_id/__init__.py b/blender_id/__init__.py
new file mode 100644
index 0000000..ae24af8
--- /dev/null
+++ b/blender_id/__init__.py
@@ -0,0 +1,277 @@
+# ##### BEGIN GPL LICENSE BLOCK #####
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# ##### END GPL LICENSE BLOCK #####
+
+# <pep8 compliant>
+
+bl_info = {
+ 'name': 'Blender ID authentication',
+ 'author': 'Francesco Siddi, Inês Almeida and Sybren A. Stüvel',
+ 'version': (1, 2, 0),
+ 'blender': (2, 77, 0),
+ 'location': 'Add-on preferences',
+ 'description':
+ 'Stores your Blender ID credentials for usage with other add-ons',
+ 'wiki_url': 'http://wiki.blender.org/index.php/Extensions:2.6/Py/'
+ 'Scripts/System/BlenderID',
+ 'category': 'System',
+ 'support': 'OFFICIAL',
+}
+
+import bpy
+from bpy.types import AddonPreferences, Operator, PropertyGroup
+from bpy.props import PointerProperty, StringProperty
+
+if 'communication' in locals():
+ import importlib
+
+ # noinspection PyUnboundLocalVariable
+ communication = importlib.reload(communication)
+ # noinspection PyUnboundLocalVariable
+ profiles = importlib.reload(profiles)
+else:
+ from . import communication, profiles
+BlenderIdProfile = profiles.BlenderIdProfile
+BlenderIdCommError = communication.BlenderIdCommError
+
+__all__ = ('get_active_profile', 'get_active_user_id', 'is_logged_in', 'create_subclient_token',
+ 'BlenderIdProfile', 'BlenderIdCommError')
+
+
+# Public API functions
+def get_active_user_id() -> str:
+ """Get the id of the currently active profile. If there is no
+ active profile on the file, this function will return an empty string.
+ """
+
+ return BlenderIdProfile.user_id
+
+
+def get_active_profile() -> BlenderIdProfile:
+ """Returns the active Blender ID profile. If there is no
+ active profile on the file, this function will return None.
+
+ :rtype: BlenderIdProfile
+ """
+
+ if not BlenderIdProfile.user_id:
+ return None
+
+ return BlenderIdProfile
+
+
+def is_logged_in() -> bool:
+ """Returns whether the user is logged in on Blender ID or not."""
+
+ return bool(BlenderIdProfile.user_id)
+
+
+def create_subclient_token(subclient_id: str, webservice_endpoint: str) -> dict:
+ """Lets the Blender ID server create a subclient token.
+
+ :param subclient_id: the ID of the subclient
+ :param webservice_endpoint: the URL of the endpoint of the webservice
+ that belongs to this subclient.
+ :returns: the token along with its expiry timestamp, in a {'scst': 'token',
+ 'expiry': datetime.datetime} dict.
+ :raises: blender_id.communication.BlenderIdCommError when the
+ token cannot be created.
+ """
+
+ # Communication between us and Blender ID.
+ profile = get_active_profile()
+ scst_info = communication.subclient_create_token(profile.token, subclient_id)
+ subclient_token = scst_info['token']
+
+ # Send the token to the webservice.
+ user_id = communication.send_token_to_subclient(webservice_endpoint, profile.user_id,
+ subclient_token, subclient_id)
+
+ # Now that everything is okay we can store the token locally.
+ profile.subclients[subclient_id] = {'subclient_user_id': user_id, 'token': subclient_token}
+ profile.save_json()
+
+ return scst_info
+
+
+def get_subclient_user_id(subclient_id: str) -> str:
+ """Returns the user ID at the given subclient.
+
+ Requires that the user has been authenticated at the subclient using
+ a call to create_subclient_token(...)
+
+ :returns: the subclient-local user ID, or None if not logged in.
+ """
+
+ if not BlenderIdProfile.user_id:
+ return None
+
+ return BlenderIdProfile.subclients[subclient_id]['subclient_user_id']
+
+
+class BlenderIdPreferences(AddonPreferences):
+ bl_idname = __name__
+
+ error_message = StringProperty(
+ name='Error Message',
+ default='',
+ options={'HIDDEN', 'SKIP_SAVE'}
+ )
+ ok_message = StringProperty(
+ name='Message',
+ default='',
+ options={'HIDDEN', 'SKIP_SAVE'}
+ )
+ blender_id_username = StringProperty(
+ name='E-mail address',
+ default='',
+ options={'HIDDEN', 'SKIP_SAVE'}
+ )
+ blender_id_password = StringProperty(
+ name='Password',
+ default='',
+ options={'HIDDEN', 'SKIP_SAVE'},
+ subtype='PASSWORD'
+ )
+
+ def reset_messages(self):
+ self.ok_message = ''
+ self.error_message = ''
+
+ def draw(self, context):
+ layout = self.layout
+
+ if self.error_message:
+ sub = layout.row()
+ sub.alert = True # labels don't display in red :(
+ sub.label(self.error_message, icon='ERROR')
+ if self.ok_message:
+ sub = layout.row()
+ sub.label(self.ok_message, icon='FILE_TICK')
+
+ active_profile = get_active_profile()
+ if active_profile:
+ text = 'You are logged in as {0}'.format(active_profile.username)
+ layout.label(text=text, icon='WORLD_DATA')
+ row = layout.row()
+ row.operator('blender_id.logout')
+ if bpy.app.debug:
+ row.operator('blender_id.validate')
+ else:
+ layout.prop(self, 'blender_id_username')
+ layout.prop(self, 'blender_id_password')
+
+ layout.operator('blender_id.login')
+
+
+class BlenderIdMixin:
+ @staticmethod
+ def addon_prefs(context):
+ preferences = context.user_preferences.addons[__name__].preferences
+ preferences.reset_messages()
+ return preferences
+
+
+class BlenderIdLogin(BlenderIdMixin, Operator):
+ bl_idname = 'blender_id.login'
+ bl_label = 'Login'
+
+ def execute(self, context):
+ import random
+ import string
+
+ addon_prefs = self.addon_prefs(context)
+
@@ Diff output truncated at 10240 characters. @@
More information about the Bf-extensions-cvs
mailing list