diff --git a/src/element/ControlBar/component/ControlBar.svelte b/src/element/ControlBar/component/ControlBar.svelte
index 953c6f7..834bb9b 100644
--- a/src/element/ControlBar/component/ControlBar.svelte
+++ b/src/element/ControlBar/component/ControlBar.svelte
@@ -167,11 +167,6 @@
// go async to allow svelte components to bind to local variables
await Promise.resolve();
- // user does not have write permisisons to this page
- if('READ_WRITE' !== G_META.access_mode) {
- b_read_only = true;
- }
-
// initial control bar alignment
queueMicrotask(realign_control_bar);
@@ -207,9 +202,6 @@
sx_document_metadata_local = JSON.stringify(g_bundle?.data, null, ' ');
sx_document_metadata_remote = JSON.stringify(g_bundle?.data);
-
- // user does not have edit permissions to document
- b_read_only ||= !await k_document.fetchUserHasUpdatePermissions(); // eslint-disable-line @typescript-eslint/no-unsafe-call
}
LOAD_PAGE_METADATA: {
@@ -229,6 +221,14 @@
sx_page_content_local = g_bundle.document.prettyPrint();
sx_page_content_remote = g_bundle.document.toString();
}
+
+ if(k_page) {
+ b_read_only = !await k_page.fetchUserHasUpdatePermissions();;
+ // page is in a document, determine if the user has edit access to the document
+ if(k_document) {
+ b_read_only = !await k_document.fetchUserHasUpdatePermissions();;
+ }
+ }
});
function toggle_collapse() {
@@ -676,7 +676,7 @@
New updates are available every morning
-
+
{/if}
diff --git a/src/element/QueryTable/component/QueryTable.svelte b/src/element/QueryTable/component/QueryTable.svelte
index 349b481..549bbc9 100644
--- a/src/element/QueryTable/component/QueryTable.svelte
+++ b/src/element/QueryTable/component/QueryTable.svelte
@@ -107,6 +107,9 @@
// table edited
$: b_changed = b_published? si_query_hash_previous !== si_query_hash_published : '' !== si_query_hash_previous;
+ // read-only mode
+ let b_read_only = true;
+
// once the component mounts
onMount(async() => {
// get query table's connection
@@ -141,6 +144,13 @@
}
// keep track of the number of rows in the published table
n_published_rows = get_published_table_rows().length;
+
+ // determine if the user has read-only access
+ const k_page = k_model.getContext().page;
+
+ if(k_page) {
+ b_read_only = !await k_page.fetchUserHasUpdatePermissions();
+ }
});
const A_DUMMY_TABLE_ROWS = [{}, {}, {}];
@@ -775,15 +785,17 @@
Connected Data Table {g_source ? `with ${g_source.label}` : ''}
-
-
- {#if b_display_parameters}
-
-
- {/if}
-
+ {#if !b_read_only}
+
+
+ {#if b_display_parameters}
+
+
+ {/if}
+
+ {/if}
diff --git a/src/ui/component/DatasetsTable.svelte b/src/ui/component/DatasetsTable.svelte
index 8b22709..42b9f34 100644
--- a/src/ui/component/DatasetsTable.svelte
+++ b/src/ui/component/DatasetsTable.svelte
@@ -25,9 +25,10 @@
import {
VeOdm,
} from '#/model/Serializable';
-import {
- ObjectStore
-} from '#/model/ObjectStore';
+
+ import {
+ ObjectStore
+ } from '#/model/ObjectStore';
import {
faCheckCircle,
@@ -69,7 +70,6 @@ import {
};
export let g_context: Context;
- export let b_read_only = false;
let k_object_store = g_context.store;
let g_version_current: ModelVersionDescriptor;
@@ -241,6 +241,9 @@ import {
// download page
const k_page = ConfluencePage.fromBasicPageInfo(g_page);
+ // don't update page if the user doesn't have access to it
+ if(!await k_page.fetchUserHasUpdatePermissions()) continue;
+
// fetch xhtml contents
let {
document: k_doc,
@@ -284,11 +287,13 @@ import {
cf.setConnection(k_connection_new);
let cfstring = await cf.fetchDisplayText();
let display = cdataDoc.select('//span[@class="ve-transclusion-display"]')[0].childNodes.item(0) as Text;
- display.replaceData(0, display.data.length, cfstring);
- cdataNode.replaceData(0, cdataNode.data.length, cdataDoc.toString());
- set_connection_properties(k_connection, {
- cfs_touched_count: ++c_cfs_touched,
- });
+ if(display) {
+ display.replaceData(0, display.data.length, cfstring);
+ cdataNode.replaceData(0, cdataNode.data.length, cdataDoc.toString());
+ set_connection_properties(k_connection, {
+ cfs_touched_count: ++c_cfs_touched,
+ });
+ }
}
let sx_new_page = k_doc.toString();
if (sx_page === sx_new_page) {
@@ -364,6 +369,20 @@ import {
];
}
+ async function can_update_to_latest(k_connection: Connection): Promise
{
+ const info = await locate_tables(k_connection)
+ if(!info) return false;
+ for(const g_page of info.pages) { // TODO this should just requery all pages to prevent potential outdated data/conflicts
+ // download page
+ let k_page = ConfluencePage.fromBasicPageInfo(g_page);
+ let b_user_can_update = await k_page.fetchUserHasUpdatePermissions();
+ if(!b_user_can_update){
+ return false;
+ }
+ }
+ return true;
+ }
+
/* eslint-disable @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call */
@@ -540,10 +559,14 @@ import {
{k_connection.label} |
{#await fetch_version_info(k_connection)}
- Loading...
- {:then [g_current_version, g_latest_version, s_hash, s_current_version, s_latest_version]}
- {s_current_version}
+ Loading...
+ {:then [g_current_version, g_latest_version, s_hash, s_current_version, s_latest_version]}
+ {#await can_update_to_latest(k_connection)}
+ Loading...
+ {:then b_can_update}
+ {s_current_version}
+ {/await}
{/await}
diff --git a/src/vendor/confluence/module/confluence.ts b/src/vendor/confluence/module/confluence.ts
index a42690a..52fdf4c 100644
--- a/src/vendor/confluence/module/confluence.ts
+++ b/src/vendor/confluence/module/confluence.ts
@@ -867,6 +867,62 @@ export class ConfluencePage extends ConfluenceEntity {
async isDocumentMember(): Promise {
return null !== await this.fetchDocument();
}
+
+ async fetchUserHasUpdatePermissions(): Promise {
+
+ // fetch page restrictions
+ const g_response_page = await confluence_get_json(`/content/${this.pageId}/restriction/byOperation/update`, {
+ search: {
+ expand: ['restrictions.user', 'restrictions.group'].join(','),
+ },
+ });
+
+
+ // destructure response data
+ const g_data = g_response_page.data!;
+ const {
+ group: {
+ results: a_groups_cover,
+ },
+ user: {
+ results: a_users_cover,
+ },
+ } = g_data.restrictions;
+
+ // no restriction(s) exists
+ if(!a_groups_cover.length && !a_users_cover.length) {
+ return true;
+ }
+
+ // user key
+ const si_user_current = G_META.remote_user_key;
+
+ // each user
+ for(const g_user of a_users_cover) {
+ // found current user
+ if(g_user.userKey === si_user_current) return true;
+ }
+
+ // fetch user groups
+ const g_response_user = await confluence_get_json('/user/memberof', {
+ search: {
+ key: G_META.remote_user_key,
+ },
+ });
+
+ // convert user groups into set
+ const as_groups_user = new Set((g_response_user.data?.results || []).map(g_group => g_group.name));
+
+ // each group
+ for(const g_group of a_groups_cover) {
+ // user belongs to authorized group
+ if(as_groups_user.has(g_group.name)) {
+ return true;
+ }
+ }
+
+ return false;
+ }
}
export class ConfluenceDocument extends ConfluenceEntity {
|