1 # SPDX-FileCopyrightText: 2016-2022 Blender Foundation
3 # SPDX-License-Identifier: GPL-2.0-or-later
8 from . import communication
10 # Set/created upon register.
16 """Metaclass for BlenderIdProfile."""
19 # noinspection PyUnresolvedReferences
20 return '%s(user_id=%r)' % (self
.__qualname
__, self
.user_id
)
23 class BlenderIdProfile(metaclass
=_BIPMeta
):
24 """Current Blender ID profile.
26 This is always stored at class level, as there is only one current
46 """Updates the active profile information from the JSON file."""
50 active_profile
= get_active_profile()
51 if not active_profile
:
54 for key
, value
in active_profile
.items():
56 setattr(cls
, key
, value
)
58 print('Skipping key %r from profile JSON' % key
)
61 def save_json(cls
, make_active_profile
=False):
62 """Updates the JSON file with the active profile information."""
64 jsonfile
= get_profiles_data()
65 jsonfile
['profiles'][cls
.user_id
] = {
66 'username': cls
.username
,
68 'expires': cls
.expires
,
69 'subclients': cls
.subclients
,
72 if make_active_profile
:
73 jsonfile
['active_profile'] = cls
.user_id
75 save_profiles_data(jsonfile
)
79 global profiles_path
, profiles_file
81 profiles_path
= bpy
.utils
.user_resource('CONFIG', path
='blender_id', create
=True)
82 profiles_file
= os
.path
.join(profiles_path
, 'profiles.json')
85 def _create_default_file():
86 """Creates the default profile file, returning its contents."""
89 profiles_default_data
= {
90 'active_profile': None,
94 os
.makedirs(profiles_path
, exist_ok
=True)
96 # Populate the file, ensuring that its permissions are restrictive enough.
97 old_umask
= os
.umask(0o077)
99 with
open(profiles_file
, 'w', encoding
='utf8') as outfile
:
100 json
.dump(profiles_default_data
, outfile
)
104 return profiles_default_data
107 def get_profiles_data():
108 """Returns the profiles.json content from a blender_id folder in the
109 Blender config directory. If the file does not exist we create one with the
110 basic data structure.
114 # if the file does not exist
115 if not os
.path
.exists(profiles_file
):
116 return _create_default_file()
118 # try parsing the file
119 with
open(profiles_file
, 'r', encoding
='utf8') as f
:
121 file_data
= json
.load(f
)
122 file_data
['active_profile']
123 file_data
['profiles']
125 except (ValueError, # malformed json data
126 KeyError): # it doesn't have the expected content
128 'Warning: profiles.json is either empty or malformed. '
129 'The file will be reset.' % __name__
)
132 return _create_default_file()
135 def get_active_user_id():
136 """Get the id of the currently active profile. If there is no
137 active profile on the file, this function will return None.
140 return get_profiles_data()['active_profile']
143 def get_active_profile():
144 """Pick the active profile from profiles.json. If there is no
145 active profile on the file, this function will return None.
147 @returns: dict like {'user_id': 1234, 'username': 'email@blender.org'}
149 file_content
= get_profiles_data()
150 user_id
= file_content
['active_profile']
151 if not user_id
or user_id
not in file_content
['profiles']:
154 profile
= file_content
['profiles'][user_id
]
155 profile
['user_id'] = user_id
159 def get_profile(user_id
):
160 """Loads the profile data for a given user_id if existing
161 else it returns None.
164 file_content
= get_profiles_data()
165 if not user_id
or user_id
not in file_content
['profiles']:
168 profile
= file_content
['profiles'][user_id
]
170 username
=profile
['username'],
171 token
=profile
['token']
175 def save_profiles_data(all_profiles
: dict):
176 """Saves the profiles data to JSON."""
179 with
open(profiles_file
, 'w', encoding
='utf8') as outfile
:
180 json
.dump(all_profiles
, outfile
, sort_keys
=True)
183 def save_as_active_profile(auth_result
: communication
.AuthResult
, username
, subclients
):
184 """Saves the given info as the active profile."""
186 BlenderIdProfile
.user_id
= auth_result
.user_id
187 BlenderIdProfile
.token
= auth_result
.token
188 BlenderIdProfile
.expires
= auth_result
.expires
190 BlenderIdProfile
.username
= username
191 BlenderIdProfile
.subclients
= subclients
193 BlenderIdProfile
.save_json(make_active_profile
=True)
197 """Invalidates the token and state of active for this user.
198 This is different from switching the active profile, where the active
199 profile is changed but there isn't an explicit logout.
203 file_content
= get_profiles_data()
205 # Remove user from 'active profile'
206 if file_content
['active_profile'] == user_id
:
207 file_content
['active_profile'] = ""
209 # Remove both user and token from profiles list
210 if user_id
in file_content
['profiles']:
211 del file_content
['profiles'][user_id
]
213 with
open(profiles_file
, 'w', encoding
='utf8') as outfile
:
214 json
.dump(file_content
, outfile
)