Extensions: support token access for remote repositories
This introduce a new "secret" per-repository property of type password as described by #121856. A token or secret may be used by some non blender.org repositories. This only shows for remote repositories and is shown in the "Add Remote Repository" popup. This commit doesn't implement sending to token to the server which will be implemented separately. Ref !121886 Co-authored-by: Dalai Felinto <dalai@blender.org>
This commit is contained in:
@@ -2137,24 +2137,41 @@ class USERPREF_PT_extensions_repos(Panel):
|
||||
split.prop(active_repo, "remote_url", text="", icon='URL', placeholder="Repository URL")
|
||||
split = row.split()
|
||||
|
||||
if active_repo.use_access_token:
|
||||
access_token_icon = 'LOCKED' if active_repo.access_token else 'UNLOCKED'
|
||||
row = layout.row()
|
||||
split = row.split(factor=0.936)
|
||||
split.prop(active_repo, "access_token", icon=access_token_icon)
|
||||
split = row.split()
|
||||
|
||||
layout.prop(active_repo, "use_sync_on_startup")
|
||||
|
||||
layout_header, layout_panel = layout.panel("advanced", default_closed=True)
|
||||
layout_header.label(text="Advanced")
|
||||
if layout_panel:
|
||||
layout_panel.prop(active_repo, "use_custom_directory")
|
||||
|
||||
row = layout_panel.row()
|
||||
if layout_panel:
|
||||
layout_panel.use_property_split = True
|
||||
|
||||
col = layout_panel.column(align=False, heading="Custom Directory")
|
||||
row = col.row(align=True)
|
||||
sub = row.row(align=True)
|
||||
sub.prop(active_repo, "use_custom_directory", text="")
|
||||
sub = sub.row(align=True)
|
||||
sub.active = active_repo.use_custom_directory
|
||||
if active_repo.use_custom_directory:
|
||||
if active_repo.custom_directory == "":
|
||||
row.alert = True
|
||||
row.prop(active_repo, "custom_directory", text="")
|
||||
sub.alert = True
|
||||
sub.prop(active_repo, "custom_directory", text="")
|
||||
else:
|
||||
# Show the read-only directory property.
|
||||
# Apart from being consistent with the custom directory UI,
|
||||
# prefer a read-only property over a label because this is not necessarily
|
||||
# valid UTF-8 which will raise a Python exception when passed in as text.
|
||||
row.prop(active_repo, "directory", text="")
|
||||
sub.prop(active_repo, "directory", text="")
|
||||
|
||||
if active_repo.use_remote_url:
|
||||
row = layout_panel.row(align=True, heading="Authentication")
|
||||
row.prop(active_repo, "use_access_token")
|
||||
|
||||
layout_panel.prop(active_repo, "use_cache")
|
||||
layout_panel.separator()
|
||||
|
||||
@@ -15,6 +15,8 @@ extern "C" {
|
||||
#include "BLI_compiler_attrs.h"
|
||||
#include "BLI_sys_types.h"
|
||||
|
||||
struct BlendWriter;
|
||||
struct BlendReader;
|
||||
struct UserDef;
|
||||
struct bUserExtensionRepo;
|
||||
struct bUserAssetLibrary;
|
||||
@@ -121,6 +123,11 @@ void BKE_preferences_extension_remote_to_name(const char *remote_url, char name[
|
||||
int BKE_preferences_extension_repo_get_index(const UserDef *userdef,
|
||||
const bUserExtensionRepo *repo);
|
||||
|
||||
void BKE_preferences_extension_repo_read_data(struct BlendDataReader *reader,
|
||||
bUserExtensionRepo *repo);
|
||||
void BKE_preferences_extension_repo_write_data(struct BlendWriter *writer,
|
||||
const bUserExtensionRepo *repo);
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
|
||||
@@ -340,7 +340,13 @@ void BKE_blender_userdef_data_free(UserDef *userdef, bool clear_fonts)
|
||||
BLI_freelistN(&userdef->autoexec_paths);
|
||||
BLI_freelistN(&userdef->script_directories);
|
||||
BLI_freelistN(&userdef->asset_libraries);
|
||||
BLI_freelistN(&userdef->extension_repos);
|
||||
|
||||
LISTBASE_FOREACH_MUTABLE (bUserExtensionRepo *, repo_ref, &userdef->extension_repos) {
|
||||
MEM_SAFE_FREE(repo_ref->access_token);
|
||||
MEM_freeN(repo_ref);
|
||||
}
|
||||
BLI_listbase_clear(&userdef->asset_shelves_settings);
|
||||
|
||||
LISTBASE_FOREACH_MUTABLE (bUserAssetShelfSettings *, settings, &userdef->asset_shelves_settings)
|
||||
{
|
||||
BKE_asset_catalog_path_list_free(settings->enabled_catalog_paths);
|
||||
|
||||
@@ -25,6 +25,8 @@
|
||||
|
||||
#include "BLT_translation.hh"
|
||||
|
||||
#include "BLO_read_write.hh"
|
||||
|
||||
#include "DNA_asset_types.h"
|
||||
#include "DNA_defaults.h"
|
||||
#include "DNA_userdef_types.h"
|
||||
@@ -404,6 +406,21 @@ int BKE_preferences_extension_repo_get_index(const UserDef *userdef,
|
||||
{
|
||||
return BLI_findindex(&userdef->extension_repos, repo);
|
||||
}
|
||||
|
||||
void BKE_preferences_extension_repo_read_data(BlendDataReader *reader, bUserExtensionRepo *repo)
|
||||
{
|
||||
if (repo->access_token) {
|
||||
BLO_read_string(reader, &repo->access_token);
|
||||
}
|
||||
}
|
||||
|
||||
void BKE_preferences_extension_repo_write_data(BlendWriter *writer, const bUserExtensionRepo *repo)
|
||||
{
|
||||
if (repo->access_token) {
|
||||
BLO_write_string(writer, repo->access_token);
|
||||
}
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
|
||||
@@ -82,6 +82,7 @@
|
||||
#include "BKE_node.hh" /* for tree type defines */
|
||||
#include "BKE_object.hh"
|
||||
#include "BKE_packedFile.h"
|
||||
#include "BKE_preferences.h"
|
||||
#include "BKE_report.hh"
|
||||
#include "BKE_scene.hh"
|
||||
#include "BKE_screen.hh"
|
||||
@@ -3424,6 +3425,10 @@ static BHead *read_userdef(BlendFileData *bfd, FileData *fd, BHead *bhead)
|
||||
IDP_BlendDataRead(reader, &addon->prop);
|
||||
}
|
||||
|
||||
LISTBASE_FOREACH (bUserExtensionRepo *, repo_ref, &user->extension_repos) {
|
||||
BKE_preferences_extension_repo_read_data(reader, repo_ref);
|
||||
}
|
||||
|
||||
LISTBASE_FOREACH (bUserAssetShelfSettings *, shelf_settings, &user->asset_shelves_settings) {
|
||||
BKE_asset_catalog_path_list_blend_read_data(reader, shelf_settings->enabled_catalog_paths);
|
||||
}
|
||||
|
||||
@@ -114,6 +114,7 @@
|
||||
#include "BKE_main_namemap.hh"
|
||||
#include "BKE_node.hh"
|
||||
#include "BKE_packedFile.h"
|
||||
#include "BKE_preferences.h"
|
||||
#include "BKE_report.hh"
|
||||
#include "BKE_workspace.hh"
|
||||
|
||||
@@ -934,6 +935,7 @@ static void write_userdef(BlendWriter *writer, const UserDef *userdef)
|
||||
|
||||
LISTBASE_FOREACH (const bUserExtensionRepo *, repo_ref, &userdef->extension_repos) {
|
||||
BLO_write_struct(writer, bUserExtensionRepo, repo_ref);
|
||||
BKE_preferences_extension_repo_write_data(writer, repo_ref);
|
||||
}
|
||||
LISTBASE_FOREACH (
|
||||
const bUserAssetShelfSettings *, shelf_settings, &userdef->asset_shelves_settings)
|
||||
|
||||
@@ -275,9 +275,11 @@ static int preferences_extension_repo_add_exec(bContext *C, wmOperator *op)
|
||||
|
||||
char name[sizeof(bUserExtensionRepo::name)] = "";
|
||||
char remote_url[sizeof(bUserExtensionRepo::remote_url)] = "";
|
||||
char *access_token = nullptr;
|
||||
char custom_directory[sizeof(bUserExtensionRepo::custom_dirpath)] = "";
|
||||
|
||||
const bool use_custom_directory = RNA_boolean_get(op->ptr, "use_custom_directory");
|
||||
const bool use_access_token = RNA_boolean_get(op->ptr, "use_access_token");
|
||||
const bool use_sync_on_startup = RNA_boolean_get(op->ptr, "use_sync_on_startup");
|
||||
if (use_custom_directory) {
|
||||
RNA_string_get(op->ptr, "custom_directory", custom_directory);
|
||||
@@ -286,6 +288,12 @@ static int preferences_extension_repo_add_exec(bContext *C, wmOperator *op)
|
||||
|
||||
if (repo_type == bUserExtensionRepoAddType::Remote) {
|
||||
RNA_string_get(op->ptr, "remote_url", remote_url);
|
||||
|
||||
if (use_access_token) {
|
||||
if (RNA_string_length(op->ptr, "access_token")) {
|
||||
access_token = RNA_string_get_alloc(op->ptr, "access_token", nullptr, 0, nullptr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Setup the name using the following logic:
|
||||
@@ -353,6 +361,13 @@ static int preferences_extension_repo_add_exec(bContext *C, wmOperator *op)
|
||||
if (repo_type == bUserExtensionRepoAddType::Remote) {
|
||||
STRNCPY(new_repo->remote_url, remote_url);
|
||||
new_repo->flag |= USER_EXTENSION_REPO_FLAG_USE_REMOTE_URL;
|
||||
|
||||
if (use_access_token) {
|
||||
new_repo->flag |= USER_EXTENSION_REPO_FLAG_USE_ACCESS_TOKEN;
|
||||
}
|
||||
if (access_token) {
|
||||
new_repo->access_token = access_token;
|
||||
}
|
||||
}
|
||||
|
||||
/* Activate new repository in the UI for further setup. */
|
||||
@@ -401,6 +416,23 @@ static void preferences_extension_repo_add_ui(bContext * /*C*/, wmOperator *op)
|
||||
case bUserExtensionRepoAddType::Remote: {
|
||||
uiItemR(layout, op->ptr, "remote_url", UI_ITEM_R_IMMEDIATE, nullptr, ICON_NONE);
|
||||
uiItemR(layout, op->ptr, "use_sync_on_startup", UI_ITEM_NONE, nullptr, ICON_NONE);
|
||||
|
||||
uiItemS_ex(layout, 0.2f, LayoutSeparatorType::Line);
|
||||
|
||||
const bool use_access_token = RNA_boolean_get(ptr, "use_access_token");
|
||||
const int token_icon = (use_access_token && RNA_string_length(op->ptr, "access_token")) ?
|
||||
ICON_LOCKED :
|
||||
ICON_UNLOCKED;
|
||||
|
||||
uiLayout *row = uiLayoutRowWithHeading(layout, true, IFACE_("Authentication"));
|
||||
uiItemR(row, op->ptr, "use_access_token", UI_ITEM_NONE, nullptr, ICON_NONE);
|
||||
uiLayout *col = uiLayoutRow(layout, false);
|
||||
uiLayoutSetActive(col, use_access_token);
|
||||
/* Use "immediate" flag to refresh the icon. */
|
||||
uiItemR(col, op->ptr, "access_token", UI_ITEM_R_IMMEDIATE, nullptr, token_icon);
|
||||
|
||||
uiItemS_ex(layout, 0.2f, LayoutSeparatorType::Line);
|
||||
|
||||
break;
|
||||
}
|
||||
case bUserExtensionRepoAddType::Local: {
|
||||
@@ -479,6 +511,30 @@ static void PREFERENCES_OT_extension_repo_add(wmOperatorType *ot)
|
||||
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
|
||||
}
|
||||
|
||||
{ /* Use Access Token. */
|
||||
const char *prop_id = "use_access_token";
|
||||
PropertyRNA *prop_ref = RNA_struct_type_find_property(type_ref, prop_id);
|
||||
PropertyRNA *prop = RNA_def_boolean(ot->srna,
|
||||
prop_id,
|
||||
false,
|
||||
RNA_property_ui_name_raw(prop_ref),
|
||||
RNA_property_ui_description_raw(prop_ref));
|
||||
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
|
||||
}
|
||||
|
||||
{ /* Access Token (dynamic length). */
|
||||
const char *prop_id = "access_token";
|
||||
PropertyRNA *prop_ref = RNA_struct_type_find_property(type_ref, prop_id);
|
||||
PropertyRNA *prop = RNA_def_string(ot->srna,
|
||||
prop_id,
|
||||
nullptr,
|
||||
0,
|
||||
RNA_property_ui_name_raw(prop_ref),
|
||||
RNA_property_ui_description_raw(prop_ref));
|
||||
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
|
||||
RNA_def_property_subtype(prop, PROP_PASSWORD);
|
||||
}
|
||||
|
||||
{ /* Check for Updated on Startup. */
|
||||
const char *prop_id = "use_sync_on_startup";
|
||||
PropertyRNA *prop_ref = RNA_struct_type_find_property(type_ref, prop_id);
|
||||
|
||||
@@ -636,6 +636,12 @@ typedef struct bUserExtensionRepo {
|
||||
*/
|
||||
char module[48];
|
||||
|
||||
/**
|
||||
* Secret access token for remote repositories (allocated).
|
||||
* Only use when #USER_EXTENSION_REPO_FLAG_USE_ACCESS_TOKEN is set.
|
||||
*/
|
||||
char *access_token;
|
||||
|
||||
/**
|
||||
* The "local" directory where extensions are stored.
|
||||
* When unset, use `{BLENDER_USER_EXTENSIONS}/{bUserExtensionRepo::module}`.
|
||||
@@ -654,6 +660,7 @@ typedef enum eUserExtensionRepo_Flag {
|
||||
USER_EXTENSION_REPO_FLAG_USE_CUSTOM_DIRECTORY = 1 << 2,
|
||||
USER_EXTENSION_REPO_FLAG_USE_REMOTE_URL = 1 << 3,
|
||||
USER_EXTENSION_REPO_FLAG_SYNC_ON_STARTUP = 1 << 4,
|
||||
USER_EXTENSION_REPO_FLAG_USE_ACCESS_TOKEN = 1 << 5,
|
||||
} eUserExtensionRepo_Flag;
|
||||
|
||||
typedef struct SolidLight {
|
||||
|
||||
@@ -385,6 +385,32 @@ static int rna_userdef_extension_repo_directory_length(PointerRNA *ptr)
|
||||
return BKE_preferences_extension_repo_dirpath_get(repo, dirpath, sizeof(dirpath));
|
||||
}
|
||||
|
||||
static void rna_userdef_extension_repo_access_token_get(PointerRNA *ptr, char *value)
|
||||
{
|
||||
const bUserExtensionRepo *repo = (bUserExtensionRepo *)ptr->data;
|
||||
if (repo->access_token) {
|
||||
strcpy(value, repo->access_token);
|
||||
}
|
||||
else {
|
||||
value[0] = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
static int rna_userdef_extension_repo_access_token_length(PointerRNA *ptr)
|
||||
{
|
||||
const bUserExtensionRepo *repo = (bUserExtensionRepo *)ptr->data;
|
||||
return (repo->access_token) ? strlen(repo->access_token) : 0;
|
||||
}
|
||||
|
||||
static void rna_userdef_extension_repo_access_token_set(PointerRNA *ptr, const char *value)
|
||||
{
|
||||
bUserExtensionRepo *repo = (bUserExtensionRepo *)ptr->data;
|
||||
if (repo->access_token) {
|
||||
MEM_freeN(repo->access_token);
|
||||
}
|
||||
repo->access_token = value[0] ? BLI_strdup(value) : nullptr;
|
||||
}
|
||||
|
||||
static void rna_userdef_extension_repo_generic_flag_set_impl(PointerRNA *ptr,
|
||||
const bool value,
|
||||
const int flag)
|
||||
@@ -6693,6 +6719,14 @@ static void rna_def_userdef_filepaths_extension_repo(BlenderRNA *brna)
|
||||
RNA_def_property_translation_context(prop, BLT_I18NCONTEXT_EDITOR_FILEBROWSER);
|
||||
RNA_def_property_update(prop, 0, "rna_userdef_update");
|
||||
|
||||
prop = RNA_def_property(srna, "access_token", PROP_STRING, PROP_PASSWORD);
|
||||
RNA_def_property_ui_text(
|
||||
prop, "Secret", "Personal access token, may be required by some repositories");
|
||||
RNA_def_property_string_funcs(prop,
|
||||
"rna_userdef_extension_repo_access_token_get",
|
||||
"rna_userdef_extension_repo_access_token_length",
|
||||
"rna_userdef_extension_repo_access_token_set");
|
||||
|
||||
/* NOTE(@ideasman42): this is intended to be used by a package manger component
|
||||
* which is not yet integrated. */
|
||||
prop = RNA_def_property(srna, "use_cache", PROP_BOOLEAN, PROP_NONE);
|
||||
@@ -6711,6 +6745,10 @@ static void rna_def_userdef_filepaths_extension_repo(BlenderRNA *brna)
|
||||
RNA_def_property_ui_text(
|
||||
prop, "Check for Updates on Startup", "Allow Blender to check for updates upon launch");
|
||||
|
||||
prop = RNA_def_property(srna, "use_access_token", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, nullptr, "flag", USER_EXTENSION_REPO_FLAG_USE_ACCESS_TOKEN);
|
||||
RNA_def_property_ui_text(prop, "Requires Access Token", "Repository requires an access token");
|
||||
|
||||
prop = RNA_def_property(srna, "use_custom_directory", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(
|
||||
prop, nullptr, "flag", USER_EXTENSION_REPO_FLAG_USE_CUSTOM_DIRECTORY);
|
||||
|
||||
Reference in New Issue
Block a user