fix(grants): correct the removal of a users from a grant
This commit is contained in:
@@ -66,7 +66,8 @@ function _buildMembers(grantList) {
|
|||||||
const members = [];
|
const members = [];
|
||||||
for (const subjectGrants of bySubject.values()) {
|
for (const subjectGrants of bySubject.values()) {
|
||||||
members.push({
|
members.push({
|
||||||
grant: subjectGrants[0], // representative grant (used for subject info)
|
grant: subjectGrants[0], // representative grant (used for subject/resource info)
|
||||||
|
_grants: subjectGrants, // all grants — needed to revoke every permission on remove
|
||||||
role: _roleFromGrants(subjectGrants),
|
role: _roleFromGrants(subjectGrants),
|
||||||
_op: 'keep'
|
_op: 'keep'
|
||||||
});
|
});
|
||||||
@@ -442,15 +443,18 @@ const shareModal = {
|
|||||||
|
|
||||||
_commitStagedUsers() {
|
_commitStagedUsers() {
|
||||||
for (const contact of this._stagedUsers) {
|
for (const contact of this._stagedUsers) {
|
||||||
|
/** @type {Grant} */
|
||||||
|
const placeholderGrant = {
|
||||||
|
id: '', // not yet persisted
|
||||||
|
granted_at: 0,
|
||||||
|
granted_by: '',
|
||||||
|
subject: { type: 'user', id: contact.id },
|
||||||
|
permission: /** @type {import('../core/types.js').PermissionTypeEnum} */ (ROLE_PERMISSIONS[this._stagedRole][0]),
|
||||||
|
resource: { type: this._itemType, id: this._item?.id ?? '' }
|
||||||
|
};
|
||||||
this._localMembers.push({
|
this._localMembers.push({
|
||||||
grant: {
|
grant: placeholderGrant,
|
||||||
id: '', // not yet persisted
|
_grants: [], // no server grants yet — nothing to revoke on remove
|
||||||
granted_at: 0, // placeholder — grant hasn't been persisted yet
|
|
||||||
granted_by: '',
|
|
||||||
subject: { type: 'user', id: contact.id },
|
|
||||||
permission: /** @type {import('../core/types.js').PermissionTypeEnum} */ (ROLE_PERMISSIONS[this._stagedRole][0]),
|
|
||||||
resource: { type: this._itemType, id: this._item?.id ?? '' }
|
|
||||||
},
|
|
||||||
role: this._stagedRole,
|
role: this._stagedRole,
|
||||||
_op: 'new'
|
_op: 'new'
|
||||||
});
|
});
|
||||||
@@ -480,7 +484,7 @@ const shareModal = {
|
|||||||
*/
|
*/
|
||||||
_renderMemberGroupsInto(container) {
|
_renderMemberGroupsInto(container) {
|
||||||
container.replaceChildren();
|
container.replaceChildren();
|
||||||
const groups = /** @type {ShareRoleEnum[]} */ (['admin', 'editor', 'viewer']);
|
const groups = /** @type {ShareRoleEnum[]} */ (['viewer', 'editor', 'admin']);
|
||||||
let memberIndex = 0;
|
let memberIndex = 0;
|
||||||
|
|
||||||
for (const role of groups) {
|
for (const role of groups) {
|
||||||
@@ -946,8 +950,11 @@ const shareModal = {
|
|||||||
try {
|
try {
|
||||||
// ── Grants ─────────────────────────────────────────────────────────
|
// ── Grants ─────────────────────────────────────────────────────────
|
||||||
for (const m of this._localMembers) {
|
for (const m of this._localMembers) {
|
||||||
if (m._op === 'remove' && m.grant.id) {
|
if (m._op === 'remove') {
|
||||||
await grants.revokeGrant(m.grant.id);
|
// Revoke every individual grant for this subject (one per permission).
|
||||||
|
for (const g of m._grants) {
|
||||||
|
if (g.id) await grants.revokeGrant(g.id);
|
||||||
|
}
|
||||||
} else if (m._op === 'change' && m.grant.id) {
|
} else if (m._op === 'change' && m.grant.id) {
|
||||||
await grants.updateRole({
|
await grants.updateRole({
|
||||||
subject: { type: m.grant.subject.type, id: m.grant.subject.id },
|
subject: { type: m.grant.subject.type, id: m.grant.subject.id },
|
||||||
|
|||||||
@@ -366,8 +366,9 @@
|
|||||||
/**
|
/**
|
||||||
* One collaborator row in the share modal's People section.
|
* One collaborator row in the share modal's People section.
|
||||||
* @typedef {Object} MemberEntry
|
* @typedef {Object} MemberEntry
|
||||||
* @property {Grant} grant - The underlying grant (id, subject, resource, etc.)
|
* @property {Grant} grant - Representative grant (used for subject/resource info).
|
||||||
* @property {ShareRoleEnum} role - Derived role label shown in the UI.
|
* @property {Grant[]} _grants - All grants for this subject on the resource (may be > 1).
|
||||||
|
* @property {ShareRoleEnum} role - Derived role label shown in the UI.
|
||||||
* @property {'keep'|'remove'|'change'|'new'} _op - Pending local operation.
|
* @property {'keep'|'remove'|'change'|'new'} _op - Pending local operation.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|||||||
@@ -93,7 +93,7 @@ const sharedWithMeView = {
|
|||||||
if (data.items.length === 0 && !this._nextCursor) {
|
if (data.items.length === 0 && !this._nextCursor) {
|
||||||
// First page came back empty
|
// First page came back empty
|
||||||
ui.showError(`
|
ui.showError(`
|
||||||
<i class="fas fa-inbox empty-state-icon"></i>
|
<i class="fas fa-share-alt empty-state-icon"></i>
|
||||||
<p>${i18n.t('sharedwithme_emptyStateTitle', 'Nothing shared with you yet')}</p>
|
<p>${i18n.t('sharedwithme_emptyStateTitle', 'Nothing shared with you yet')}</p>
|
||||||
<p>${i18n.t('sharedwithme_emptyStateDesc', 'Items shared with you by other users will appear here')}</p>
|
<p>${i18n.t('sharedwithme_emptyStateDesc', 'Items shared with you by other users will appear here')}</p>
|
||||||
`);
|
`);
|
||||||
|
|||||||
Reference in New Issue
Block a user