diff --git a/services/web/app/src/Features/Subscription/SubscriptionController.mjs b/services/web/app/src/Features/Subscription/SubscriptionController.mjs
index a7eebd8871..a5c197f6c9 100644
--- a/services/web/app/src/Features/Subscription/SubscriptionController.mjs
+++ b/services/web/app/src/Features/Subscription/SubscriptionController.mjs
@@ -178,6 +178,7 @@ function formatGroupPlansDataForDash() {
async function userSubscriptionPage(req, res) {
const user = SessionManager.getSessionUser(req.session)
+ await SplitTestHandler.promises.getAssignment(req, res, 'sharing-updates')
await SplitTestHandler.promises.getAssignment(req, res, 'pause-subscription')
await SplitTestHandler.promises.getAssignment(
req,
diff --git a/services/web/app/src/models/Subscription.mjs b/services/web/app/src/models/Subscription.mjs
index 9a84d9ff69..cbb8ccb2ee 100644
--- a/services/web/app/src/models/Subscription.mjs
+++ b/services/web/app/src/models/Subscription.mjs
@@ -112,6 +112,18 @@ export const SubscriptionSchema = new Schema(
},
},
ssoConfig: { type: ObjectId, ref: 'SSOConfig' },
+ sharingPermissions: {
+ byEmail: {
+ type: String,
+ enum: ['anyone_in_x', 'anyone'],
+ default: 'anyone',
+ },
+ byLinkSharing: {
+ type: String,
+ enum: ['no_one', 'anyone_in_x', 'anyone'],
+ default: 'anyone',
+ },
+ },
},
{ minimize: false }
)
diff --git a/services/web/frontend/extracted-translations.json b/services/web/frontend/extracted-translations.json
index 3fa78c4c06..639ba85bf1 100644
--- a/services/web/frontend/extracted-translations.json
+++ b/services/web/frontend/extracted-translations.json
@@ -149,11 +149,14 @@
"and_much_more": "",
"annual_discount": "",
"anonymous": "",
+ "anyone": "",
+ "anyone_in_x": "",
"anyone_with_link_can_edit": "",
"anyone_with_link_can_view": "",
"app_on_x": "",
"appearance": "",
"apply": "",
+ "apply_changes": "",
"apply_educational_discount_description_with_group_discount": "",
"apply_suggestion": "",
"archive": "",
@@ -217,6 +220,8 @@
"buy_more_licenses": "",
"buy_now_no_exclamation_mark": "",
"by_continuing_you_agree_to_use_this_feature_in_line_with_your_institutions_policies": "",
+ "by_email": "",
+ "by_sharing_link": "",
"by_subscribing_you_agree_to_our_terms_of_service": "",
"can_link_institution_email_acct_to_institution_acct": "",
"can_link_your_institution_acct_2": "",
@@ -266,6 +271,8 @@
"change_the_ownership_of_your_personal_projects": "",
"change_to_group_plan": "",
"change_to_this_plan": "",
+ "changes_applied": "",
+ "changes_to_these_settings_will_be_applied_to_all_new_projects": "",
"changing_the_position_of_your_figure": "",
"changing_the_position_of_your_table": "",
"characters": "",
@@ -1082,6 +1089,7 @@
"manage_group_settings_subtext": "",
"manage_group_settings_subtext_group_sso": "",
"manage_group_settings_subtext_managed_users": "",
+ "manage_group_sharing_permissions_subtext": "",
"manage_institution_managers": "",
"manage_managers_subtext": "",
"manage_newsletter": "",
@@ -1198,6 +1206,7 @@
"no_messages_yet": "",
"no_new_commits_in_github": "",
"no_one_has_commented_or_left_any_suggestions_yet": "",
+ "no_one_sharing_link_is_disabled": "",
"no_other_projects_found": "",
"no_pdf_error_explanation": "",
"no_pdf_error_reason_no_content": "",
@@ -1682,6 +1691,7 @@
"share_project": "",
"shared_with_you": "",
"sharelatex_beta_program": "",
+ "sharing_permissions": "",
"shortcut_to_open_advanced_reference_search": "",
"show_all_projects": "",
"show_breadcrumbs": "",
@@ -1937,6 +1947,7 @@
"this_grants_access_to_features_2": "",
"this_is_the_file_that_references_pulled_from_your_reference_manager_will_be_added_to": "",
"this_organization_is_tax_exempt": "",
+ "this_policy_applies_to_all_projects_owned_by_your_group_members": "",
"this_project_already_has_maximum_collaborators": "",
"this_project_exceeded_collaborator_limit": "",
"this_project_exceeded_compile_timeout_limit_on_free_plan": "",
@@ -2251,6 +2262,7 @@
"what_should_we_call_you": "",
"what_would_you_like_to_do": "",
"when_you_tick_the_include_caption_box": "",
+ "who_can_be_invited_to_group_members_projects": "",
"why_not_pause_instead": "",
"wide": "",
"will_lose_edit_access_on_date": "",
diff --git a/services/web/frontend/js/features/subscription/components/dashboard/managed-group-subscriptions.tsx b/services/web/frontend/js/features/subscription/components/dashboard/managed-group-subscriptions.tsx
index 75fc5ab458..b45836d5fc 100644
--- a/services/web/frontend/js/features/subscription/components/dashboard/managed-group-subscriptions.tsx
+++ b/services/web/frontend/js/features/subscription/components/dashboard/managed-group-subscriptions.tsx
@@ -96,6 +96,8 @@ export default function ManagedGroupSubscriptions() {
const combinedUserManagement = useFeatureFlag('combined-user-management')
+ const isSharingUpdatesEnabled = useFeatureFlag('sharing-updates')
+
if (!managedGroupSubscriptions) {
return null
}
@@ -147,17 +149,28 @@ export default function ManagedGroupSubscriptions() {
)}
{isAdmin && (
-
- sendMB('group-audit-log-click', {
- subscriptionId: subscription._id,
- })
- }
- />
+ <>
+ {isSharingUpdatesEnabled &&
+ subscription.planLevelName === 'Professional' && (
+
+ )}
+
+ sendMB('group-audit-log-click', {
+ subscriptionId: subscription._id,
+ })
+ }
+ />
+ >
)}
terms of service0> and <1>privacy notice1>.",
"by_registering_you_agree_to_our_terms_of_service": "By registering, you agree to our <0>terms of service0> and <1>privacy notice1>.",
+ "by_sharing_link": "By sharing link",
"by_subscribing_you_agree_to_our_terms_of_service": "By subscribing, you agree to our <0>terms of service0>.",
"can_link_institution_email_acct_to_institution_acct": "You can now link your __email__ __appName__ account to your __institutionName__ institutional account.",
"can_link_institution_email_by_clicking": "You can link your __email__ __appName__ account to your __institutionName__ account by clicking __clickText__.",
@@ -332,6 +337,8 @@
"change_the_ownership_of_your_personal_projects": "Change the ownership of your personal projects to the new account. <0>Find out how to change project owner.0>",
"change_to_group_plan": "Change to a group plan",
"change_to_this_plan": "Change to this plan",
+ "changes_applied": "Changes applied",
+ "changes_to_these_settings_will_be_applied_to_all_new_projects": "Changes to these settings will be applied to all new projects. Existing projects will not be affected.",
"changing_the_position_of_your_figure": "Changing the position of your figure",
"changing_the_position_of_your_table": "Changing the position of your table",
"characters": "Characters",
@@ -1396,6 +1403,7 @@
"manage_group_settings_subtext": "Configure and manage SSO and Managed Users",
"manage_group_settings_subtext_group_sso": "Configure and manage SSO",
"manage_group_settings_subtext_managed_users": "Turn on Managed Users",
+ "manage_group_sharing_permissions_subtext": "Manage how group members share projects",
"manage_institution_managers": "Manage institution managers",
"manage_managers_subtext": "Assign or remove manager privileges",
"manage_newsletter": "Manage newsletter preferences",
@@ -1536,6 +1544,7 @@
"no_messages_yet": "No messages yet",
"no_new_commits_in_github": "No new commits in GitHub since last merge.",
"no_one_has_commented_or_left_any_suggestions_yet": "No one has commented or left any suggestions yet.",
+ "no_one_sharing_link_is_disabled": "No one—sharing link is disabled",
"no_other_projects_found": "No other projects found, please create another project first",
"no_other_sessions": "No other sessions active",
"no_pdf_error_explanation": "This compile didn’t produce a PDF. This can happen if:",
@@ -2157,6 +2166,7 @@
"share_project": "Share Project",
"shared_with_you": "Shared with you",
"sharelatex_beta_program": "__appName__ beta program",
+ "sharing_permissions": "Sharing permissions",
"shortcut_to_open_advanced_reference_search": "(__ctrlSpace__ or __altSpace__)",
"show_all_projects": "Show all projects",
"show_breadcrumbs": "Show breadcrumbs",
@@ -2471,6 +2481,7 @@
"this_is_the_file_that_references_pulled_from_your_reference_manager_will_be_added_to": "This is the file that references pulled from your reference manager will be added to.",
"this_is_your_template": "This is your template from your project",
"this_organization_is_tax_exempt": "This organization is tax exempt",
+ "this_policy_applies_to_all_projects_owned_by_your_group_members": "This policy applies to all projects owned by your group members. Project owners can apply stricter sharing rules for individual projects.",
"this_project_already_has_maximum_collaborators": "This project already has the maximum number of collaborators permitted on the owner’s plan. This means you can view but not edit or review the project.",
"this_project_exceeded_collaborator_limit": "This project exceeded the collaborator limit for your plan. All other users now have view-only access.",
"this_project_exceeded_compile_timeout_limit_on_free_plan": "This project exceeded the compile timeout limit on our free plan.",
@@ -2814,6 +2825,7 @@
"what_would_you_like_to_do": "What would you like to do?",
"when_you_join_labs": "When you join Labs, you can choose which experiments you want to be part of. Once you’ve done that, you can use Overleaf as normal, but you’ll see any labs features marked with this badge:",
"when_you_tick_the_include_caption_box": "When you tick the box “Include caption” the image will be inserted into your document with a placeholder caption. To edit it, you simply select the placeholder text and type to replace it with your own.",
+ "who_can_be_invited_to_group_members_projects": "Who can be invited to group members’ projects?",
"why_latex": "Why LaTeX?",
"why_not_pause_instead": "Pause instead, to pick up where you left off",
"wide": "Wide",
diff --git a/services/web/test/frontend/features/subscription/components/dashboard/managed-group-subscriptions.test.tsx b/services/web/test/frontend/features/subscription/components/dashboard/managed-group-subscriptions.test.tsx
index 74dfead7c9..74a78b5b03 100644
--- a/services/web/test/frontend/features/subscription/components/dashboard/managed-group-subscriptions.test.tsx
+++ b/services/web/test/frontend/features/subscription/components/dashboard/managed-group-subscriptions.test.tsx
@@ -208,6 +208,48 @@ describe('', function () {
await screen.findAllByText('Audit logs')
})
+ it('does not render the Sharing Permissions settings row when the user is not the group admin', function () {
+ renderWithSubscriptionDashContext(, {
+ metaTags: [
+ {
+ name: 'ol-managedGroupSubscriptions',
+ value: managedGroupSubscriptions2,
+ },
+ {
+ name: 'ol-groupSettingsEnabledFor',
+ value: [],
+ },
+ {
+ name: 'ol-splitTestVariants',
+ value: { 'sharing-updates': 'enabled' },
+ },
+ ],
+ })
+
+ expect(screen.queryByText(/sharing permissions/i)).to.be.null
+ expect(screen.queryByText(/manage how group members share projects/i)).to.be
+ .null
+ })
+
+ it('renders the Sharing Permissions settings row when the user is the group admin and plan is professional', async function () {
+ renderWithSubscriptionDashContext(, {
+ metaTags: [
+ {
+ name: 'ol-managedGroupSubscriptions',
+ value: managedGroupSubscriptions,
+ },
+ { name: 'ol-usersEmail', value: 'you@example.com' },
+ {
+ name: 'ol-splitTestVariants',
+ value: { 'sharing-updates': 'enabled' },
+ },
+ ],
+ })
+
+ await screen.findAllByText(/sharing permissions/i)
+ await screen.findAllByText(/manage how group members share projects/i)
+ })
+
it('renders Managed Group / Group SSO settings row when both features are turned on', async function () {
renderWithSubscriptionDashContext(, {
metaTags: [