Repository navigation
Feature: change edit and re-share on an existing internal share #517
Closed
branch1337
started this conversation in
Ideas
Replies: 2 comments
|
Thank you for the suggestion. The person who granted a share can now change its edit and re-share permissions in place, with a "Change permissions" button in the share window and on Shared Transcripts. A permission can be granted only within the grantor's own permissions, and shares created by a group tag or a group folder still follow the group. Lowering a permission leaves the shares the recipient has already made in place. This will be included in the next release. |
0 replies
|
Thank you for considering and implementing the suggestion! And please let me know if any of my reports or requests are confusing. I don’t want to waste your time. I really appreciate the quick response and all your hard work! |
0 replies
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
Description
After a recording is shared with a user, the grantor cannot change that user's permissions. The share modal lists the person and shows a green "Edit" pill when
can_editis true, a blue "Reshare" pill whencan_reshareis true, and a gray "View" pill when both are false. Those pills are status labels. The only action on the card is the red revoke button. The same list on Shared Transcripts offers revoke for a manual share and nothing else.The practical workaround is to revoke the share and create it again with the checkboxes set differently. That is not a permission edit. Revoke is a cascade deletion of the share row, and creating the share again is refused while the row still exists. A second share of the same recording to the same user is also impossible because of the unique constraint on that pair.
Affected Version
v0.10.16-alpha
Requested Feature
On a manual internal share, the grantor can change
can_editandcan_resharein place. The recipient, the recording, the share id, and the recipient's inbox and personal notes stay as they are.In the share modal, each manual share the current user granted gets a control beside the revoke button. Its accessible name is "Change permissions", not "Edit". Activating it shows the same two checkboxes used when adding a user, filled with the flags on that row, and a save action that writes them. The green, blue, and gray pills stay read-only status and keep their current labels.
Shared Transcripts gets the same control on each manual recipient row that already shows Revoke. Rows shared with the current user stay read-only.
Group-tag and group-folder shares do not get the control. Their flags still come from the group rule that created them.
A grantor cannot raise a flag above the permissions they themselves hold. Lowering a flag does not delete shares that recipient already created for other people. Revoke remains the action that cascades.
Proposed Implementation
Add
PATCH /api/internal-shares/<int:share_id>insrc/api/shares.py, on the same blueprint asrevoke_internal_share(src/api/shares.py:590-603). That function is the only mutation of an internal share today, and it only deletes. Leaveshare_recording_internal(src/api/shares.py:432-476) as the create path, including the409already_sharedresponse. Leaveupdate_share(src/api/shares.py:368-381) as the public-link settings update. It writesshare_summaryandshare_noteson the publicSharerow and is not on this path.validate_reshare_permissions(src/models/sharing.py:145-173) already refuses a grant the caller does not hold.log_share_modified(src/models/audit.py:80-93) already records old and new flags and has no caller. Addshare_source_lockedandpermissions_requirednext toalready_sharedinserver.apiError(speakr.git/static/locales/en.json:3129). Add the English strings and the same keys in the other locale files that already translatealready_shared.get_internal_shares(src/api/shares.py:548-587) should addpermissions_editableon each real share: true only whensource_type == 'manual'andowner_id == current_user.id. The owner sentinel row stays without that flag. The modal inspeakr.git/templates/modals/unified-share-modal.html:246-251renders the new button from that flag, beside revoke, and does not treat the pill atspeakr.git/templates/modals/unified-share-modal.html:234-236as a button.createInternalShare(speakr.git/static/js/modules/composables/sharing.js:616-648) keeps posting the add-user checkboxes. A newupdateInternalSharein that composable sends the PATCH and replaces the matching row inrecordingInternalShares. The add-user checkboxes atspeakr.git/templates/modals/unified-share-modal.html:168-194stay bound tointernalSharePermissionsand are not reused as the editor for an existing row, so opening the editor does not change what the next Add will grant.On Shared Transcripts,
get_shares_overviewalready setsrevocablefor a manual share the caller granted (src/api/shares.py:336-338). The people list (speakr.git/templates/account.html:4219-4225) shows the change-permissions button on the samep.revocablebranch as Revoke. The shared-with-me rows stay as they are.Document the control in "Managing Your Shares" (
speakr.git/docs/user-guide/sharing.md:42-45), and say there that the green Edit pill is the current permission, while "Change permissions" writes the flags. State that group shares are unchanged from that screen.Tests, in
speakr.git/tests/test_shares_authz.py, next totest_revoke_internal_share_owner_succeeds:test_update_internal_share_grantor_changes_permissions: the grantor PATCHescan_editfrom false to true, gets200, the row keeps its id, and aShareAuditLogrow with actionmodifiedstores the old and new flags.test_update_internal_share_unchanged_is_noop: the same flags return200and write no audit row.test_update_internal_share_third_party_deniedandtest_update_internal_share_recipient_denied:403, row unchanged. Mirrortest_revoke_internal_share_third_party_denied_and_survivesandtest_revoke_internal_share_recipient_cannot_revoke.test_update_internal_share_requires_login: anonymous PATCH is302or401, same astest_revoke_internal_share_requires_login.test_update_internal_share_above_ceiling_denied: a grantor whose own share hascan_editfalse gets403when they setcan_edittrue, viavalidate_reshare_permissions.test_update_internal_share_group_source_locked:source_type='group_tag'returns409and the flags stay at the valuesapply_tag_shareswrote (speakr.git/src/services/tag_sharing.py:52-59).test_share_recording_internal_already_shared_still_409: a second POST for the same user still returns409.Run them with
python -m pytest tests/test_shares_authz.py -k "update_internal_share or already_shared"fromspeakr.git.Expected Behavior
can_editandcan_resharefrom the share card or from Shared Transcripts. The response is200withsuccess: trueand the updatedshare. The share id does not change. The recipient'sSharedRecordingStateis not reset to the inbox, which a revoke-and-recreate does atsrc/api/shares.py:515-517.common.edit,unifiedShareModal.reshare, andunifiedShareModal.view(speakr.git/templates/modals/unified-share-modal.html:234-242).share.owner_idreceives403andshare_revoke_denied, the same refusal revoke already returns (src/api/shares.py:601-603). The recording owner cannot change a share that someone else granted.can_editorcan_resharecannot turn that flag on. The response is403withreshare_edit_not_permittedorreshare_reshare_not_permitted.409andshare_source_locked. The modal and Shared Transcripts do not show the control. Revoke of a manual share is unchanged, and a group share stays non-revocable on Shared Transcripts./api/recordings/<id>/share-internalfor a user who already has a row still returns409andalready_shared(src/api/shares.py:469-476).200and does not add an audit row. Sending neither flag returns400.can_reshareorcan_editdoes not delete downstream shares. Those rows stay until someone revokes them. The next share that recipient tries to create is still checked against their updated flags.Root Cause Analysis
Permissions are written only when the share row is inserted.
share_recording_internalcopiescan_editandcan_resharefrom the request onto a newInternalShare(src/api/shares.py:478-497) and then refuses any later POST for that recording and user with409(src/api/shares.py:469-476).unique_recording_sharemakes a second row for the same pair invalid (src/models/sharing.py:87-91). The only later route,revoke_internal_share, deletes the row (src/api/shares.py:590-603) and cascades to shares that user granted.The modal never offers another action. For a non-owner row it renders the status pills and one button, whose click handler is
revokeInternalShare(speakr.git/templates/modals/unified-share-modal.html:233-251). The client functions that follow arecreateInternalShare, which POSTs, andrevokeInternalShare, which DELETEs (speakr.git/static/js/modules/composables/sharing.js:616-672). Shared Transcripts repeats that split: it prints the permission text and, for a manual share, a revoke button (speakr.git/templates/account.html:4202-4225).update_sharelooks like the missing editor and is not. It updates a publicSharethe caller owns, and only the summary and notes flags (src/api/shares.py:368-381). The user guide describes the same gap: the share list shows the permission level and the revoke icon, and it does not describe a way to change the level (speakr.git/docs/user-guide/sharing.md:42-45).Additional Context
The green pill uses the word Edit because
t('common.edit')is the label for "this person may edit the recording" (speakr.git/static/locales/en.json:1049, drawn atspeakr.git/templates/modals/unified-share-modal.html:234-236). The new control needs its own string,unifiedShareModal.changePermissions, so the two are not the same control.This request does not change how group shares pick their flags.
apply_tag_sharessetscan_editfrom the membership role andcan_reshareto false (speakr.git/src/services/tag_sharing.py:52-59), andshare_targetsskips anyone who already has a row. Editing those flags from the share card would diverge from the group rule. It also does not walk downstream shares when a flag is lowered. A recipient who already re-shared keeps those grants; cutting that chain is still a revoke. Public links stay onupdate_share.All reactions