Skip to content
Snippets Groups Projects
Commit 6ec96548 authored by Vilém Duha's avatar Vilém Duha
Browse files

BlenderKit: Only refresh tokens when needed - on the end of their lifetime.

parent 9bfd19da
No related branches found
No related tags found
No related merge requests found
...@@ -1273,6 +1273,24 @@ class BlenderKitAddonPreferences(AddonPreferences): ...@@ -1273,6 +1273,24 @@ class BlenderKitAddonPreferences(AddonPreferences):
subtype="PASSWORD", subtype="PASSWORD",
) )
api_key_timeout: IntProperty(
name = 'api key timeout',
description = 'time where the api key will need to be refreshed',
default = 0,
)
api_key_life: IntProperty(
name='api key life time',
description='maximum lifetime of the api key, in seconds',
default=0,
)
refresh_in_progress: BoolProperty(
name="Api key refresh in progress",
description="Api key is currently being refreshed. Don't refresh it again.",
default=False
)
login_attempt: BoolProperty( login_attempt: BoolProperty(
name="Login/Signup attempt", name="Login/Signup attempt",
description="When this is on, BlenderKit is trying to connect and login.", description="When this is on, BlenderKit is trying to connect and login.",
......
...@@ -33,7 +33,7 @@ import bpy ...@@ -33,7 +33,7 @@ import bpy
import threading import threading
import requests import requests
import time
from bpy.props import ( from bpy.props import (
BoolProperty, BoolProperty,
...@@ -44,44 +44,52 @@ PORTS = [62485, 65425, 55428, 49452] ...@@ -44,44 +44,52 @@ PORTS = [62485, 65425, 55428, 49452]
active_authenticator = None active_authenticator = None
def login_thread(signup=False): def login_thread(signup=False):
global active_authenticator global active_authenticator
r_url = paths.get_oauth_landing_url() r_url = paths.get_oauth_landing_url()
url = paths.get_bkit_url() url = paths.get_bkit_url()
authenticator = oauth.SimpleOAuthAuthenticator(server_url=url, client_id=CLIENT_ID, ports=PORTS) authenticator = oauth.SimpleOAuthAuthenticator(server_url=url, client_id=CLIENT_ID, ports=PORTS)
#we store authenticator globally to be able to ping the server if connection fails. # we store authenticator globally to be able to ping the server if connection fails.
active_authenticator = authenticator active_authenticator = authenticator
thread = threading.Thread(target=login, args=([signup, url, r_url, authenticator]), daemon=True) thread = threading.Thread(target=login, args=([signup, url, r_url, authenticator]), daemon=True)
thread.start() thread.start()
def login(signup, url, r_url, authenticator): def login(signup, url, r_url, authenticator):
auth_token, refresh_token = authenticator.get_new_token(register=signup, redirect_url=r_url) auth_token, refresh_token, oauth_response = authenticator.get_new_token(register=signup, redirect_url=r_url)
utils.p('tokens retrieved') utils.p('tokens retrieved')
tasks_queue.add_task((write_tokens, (auth_token, refresh_token))) tasks_queue.add_task((write_tokens, (auth_token, refresh_token, oauth_response)))
def refresh_token_thread(): def refresh_token_thread():
preferences = bpy.context.preferences.addons['blenderkit'].preferences preferences = bpy.context.preferences.addons['blenderkit'].preferences
if len(preferences.api_key_refresh) > 0: if len(preferences.api_key_refresh) > 0 and preferences.refresh_in_progress == False:
preferences.refresh_in_progress = True
url = paths.get_bkit_url() url = paths.get_bkit_url()
thread = threading.Thread(target=refresh_token, args=([preferences.api_key_refresh, url]), daemon=True) thread = threading.Thread(target=refresh_token, args=([preferences.api_key_refresh, url]), daemon=True)
thread.start() thread.start()
else:
ui.add_report('Already Refreshing token, will be ready soon.')
def refresh_token(api_key_refresh, url): def refresh_token(api_key_refresh, url):
authenticator = oauth.SimpleOAuthAuthenticator(server_url=url, client_id=CLIENT_ID, ports=PORTS) authenticator = oauth.SimpleOAuthAuthenticator(server_url=url, client_id=CLIENT_ID, ports=PORTS)
auth_token, refresh_token = authenticator.get_refreshed_token(api_key_refresh) auth_token, refresh_token, oauth_response = authenticator.get_refreshed_token(api_key_refresh)
if auth_token is not None and refresh_token is not None: if auth_token is not None and refresh_token is not None:
tasks_queue.add_task((write_tokens, (auth_token, refresh_token))) tasks_queue.add_task((write_tokens, (auth_token, refresh_token, oauth_response)))
return auth_token, refresh_token return auth_token, refresh_token
def write_tokens(auth_token, refresh_token):
def write_tokens(auth_token, refresh_token, oauth_response):
utils.p('writing tokens') utils.p('writing tokens')
preferences = bpy.context.preferences.addons['blenderkit'].preferences preferences = bpy.context.preferences.addons['blenderkit'].preferences
preferences.api_key_refresh = refresh_token preferences.api_key_refresh = refresh_token
preferences.api_key = auth_token preferences.api_key = auth_token
preferences.api_key_timeout = time.time() + oauth_response['expires_in']
preferences.api_key_life = oauth_response['expires_in']
preferences.login_attempt = False preferences.login_attempt = False
preferences.refresh_in_progress = False
props = utils.get_search_props() props = utils.get_search_props()
if props is not None: if props is not None:
props.report = '' props.report = ''
...@@ -97,7 +105,6 @@ class RegisterLoginOnline(bpy.types.Operator): ...@@ -97,7 +105,6 @@ class RegisterLoginOnline(bpy.types.Operator):
bl_label = "BlenderKit login or signup" bl_label = "BlenderKit login or signup"
bl_options = {'REGISTER', 'UNDO'} bl_options = {'REGISTER', 'UNDO'}
signup: BoolProperty( signup: BoolProperty(
name="create a new account", name="create a new account",
description="True for register, otherwise login", description="True for register, otherwise login",
......
...@@ -53,9 +53,11 @@ class SimpleOAuthAuthenticator(object): ...@@ -53,9 +53,11 @@ class SimpleOAuthAuthenticator(object):
print("error retrieving refresh tokens %s" % response.status_code) print("error retrieving refresh tokens %s" % response.status_code)
print(response.content) print(response.content)
return None, None return None, None
refresh_token = json.loads(response.content)['refresh_token']
access_token = json.loads(response.content)['access_token'] response_json = json.loads(response.content)
return access_token, refresh_token refresh_token = response_json ['refresh_token']
access_token = response_json ['access_token']
return access_token, refresh_token, response_json
def get_new_token(self, register=True, redirect_url=None): def get_new_token(self, register=True, redirect_url=None):
class HTTPServerHandler(BaseHTTPRequestHandler): class HTTPServerHandler(BaseHTTPRequestHandler):
......
...@@ -57,7 +57,7 @@ def rerequest(method, url, **kwargs): ...@@ -57,7 +57,7 @@ def rerequest(method, url, **kwargs):
if user_preferences.enable_oauth: if user_preferences.enable_oauth:
tasks_queue.add_task((ui.add_report, ('refreshing token.',))) tasks_queue.add_task((ui.add_report, ('refreshing token.',)))
refresh_url = paths.get_bkit_url() refresh_url = paths.get_bkit_url()
auth_token, refresh_token = bkit_oauth.refresh_token(user_preferences.api_key_refresh, refresh_url) auth_token, refresh_token, oauth_response = bkit_oauth.refresh_token(user_preferences.api_key_refresh, refresh_url)
# utils.p(auth_token, refresh_token) # utils.p(auth_token, refresh_token)
if auth_token is not None: if auth_token is not None:
......
...@@ -82,11 +82,13 @@ reports = '' ...@@ -82,11 +82,13 @@ reports = ''
def refresh_token_timer(): def refresh_token_timer():
''' this timer gets run every 20 hours. It refreshes tokens and categories.''' ''' this timer gets run every time the token needs refresh. It refreshes tokens and also categories.'''
print('refresh timer') utils.p('refresh timer')
user_preferences = bpy.context.preferences.addons['blenderkit'].preferences
fetch_server_data() fetch_server_data()
categories.load_categories() categories.load_categories()
return 72000
return max(3600, user_preferences.api_key_life - 3600)
@persistent @persistent
...@@ -97,7 +99,7 @@ def scene_load(context): ...@@ -97,7 +99,7 @@ def scene_load(context):
# wm['bkit_update'] = version_checker.compare_versions(blenderkit) # wm['bkit_update'] = version_checker.compare_versions(blenderkit)
categories.load_categories() categories.load_categories()
if not bpy.app.timers.is_registered(refresh_token_timer): if not bpy.app.timers.is_registered(refresh_token_timer):
bpy.app.timers.register(refresh_token_timer, persistent=True, first_interval=72000) bpy.app.timers.register(refresh_token_timer, persistent=True, first_interval=36000)
def fetch_server_data(): def fetch_server_data():
...@@ -106,8 +108,10 @@ def fetch_server_data(): ...@@ -106,8 +108,10 @@ def fetch_server_data():
user_preferences = bpy.context.preferences.addons['blenderkit'].preferences user_preferences = bpy.context.preferences.addons['blenderkit'].preferences
url = paths.BLENDERKIT_ADDON_URL url = paths.BLENDERKIT_ADDON_URL
api_key = user_preferences.api_key api_key = user_preferences.api_key
# version_checker.check_version_thread(url, api_key, blenderkit) # Only refresh new type of tokens(by length), and only one hour before the token timeouts.
if user_preferences.enable_oauth: if user_preferences.enable_oauth and \
len(user_preferences.api_key)<38 and \
user_preferences.api_key_timeout<time.time()+ 3600:
bkit_oauth.refresh_token_thread() bkit_oauth.refresh_token_thread()
if api_key != '': if api_key != '':
get_profile() get_profile()
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment