diff --git a/app/components/Sidebar/components/SidebarAction.tsx b/app/components/Sidebar/components/SidebarAction.tsx
index 82ecd7c56..334d42e44 100644
--- a/app/components/Sidebar/components/SidebarAction.tsx
+++ b/app/components/Sidebar/components/SidebarAction.tsx
@@ -21,6 +21,10 @@ function SidebarAction({ action, ...rest }: Props) {
const menuItem = actionToMenuItem(action, context);
invariant(menuItem.type === "button", "passed action must be a button");
+ if (!menuItem.visible) {
+ return null;
+ }
+
return (
+
+
+
{
sharing,
guestSignin,
documentEmbeds,
+ memberCollectionCreate,
collaborativeEditing,
defaultCollectionId,
defaultUserRole,
@@ -41,6 +42,9 @@ const teamUpdater = async ({ params, user, team, ip }: TeamUpdaterProps) => {
if (avatarUrl !== undefined) {
team.avatarUrl = avatarUrl;
}
+ if (memberCollectionCreate !== undefined) {
+ team.memberCollectionCreate = memberCollectionCreate;
+ }
if (defaultCollectionId !== undefined) {
team.defaultCollectionId = defaultCollectionId;
}
diff --git a/server/migrations/20220319060408-collection-create-permission.js b/server/migrations/20220319060408-collection-create-permission.js
new file mode 100644
index 000000000..797e477c1
--- /dev/null
+++ b/server/migrations/20220319060408-collection-create-permission.js
@@ -0,0 +1,15 @@
+'use strict';
+
+module.exports = {
+ up: async (queryInterface, Sequelize) => {
+ await queryInterface.addColumn("teams", "memberCollectionCreate", {
+ type: Sequelize.BOOLEAN,
+ defaultValue: true,
+ allowNull: false,
+ });
+ },
+
+ down: async (queryInterface, Sequelize) => {
+ await queryInterface.removeColumn("teams", "memberCollectionCreate");
+ }
+};
diff --git a/server/models/Team.ts b/server/models/Team.ts
index 8ffead4e6..962e682b6 100644
--- a/server/models/Team.ts
+++ b/server/models/Team.ts
@@ -89,6 +89,10 @@ class Team extends ParanoidModel {
@Column
documentEmbeds: boolean;
+ @Default(true)
+ @Column
+ memberCollectionCreate: boolean;
+
@Default(false)
@Column
collaborativeEditing: boolean;
diff --git a/server/policies/collection.ts b/server/policies/collection.ts
index fe3695ffd..7d96c56e6 100644
--- a/server/policies/collection.ts
+++ b/server/policies/collection.ts
@@ -8,7 +8,10 @@ allow(User, "createCollection", Team, (user, team) => {
if (!team || user.isViewer || user.teamId !== team.id) {
return false;
}
- return true;
+ if (user.isAdmin || team.memberCollectionCreate) {
+ return true;
+ }
+ return false;
});
allow(User, "importCollection", Team, (actor, team) => {
diff --git a/server/presenters/team.ts b/server/presenters/team.ts
index 7025a7dfe..60fab2cf4 100644
--- a/server/presenters/team.ts
+++ b/server/presenters/team.ts
@@ -6,6 +6,7 @@ export default function present(team: Team) {
name: team.name,
avatarUrl: team.logoUrl,
sharing: team.sharing,
+ memberCollectionCreate: team.memberCollectionCreate,
collaborativeEditing: team.collaborativeEditing,
defaultCollectionId: team.defaultCollectionId,
documentEmbeds: team.documentEmbeds,
diff --git a/server/routes/api/team.ts b/server/routes/api/team.ts
index 83cbd79f7..0890ad384 100644
--- a/server/routes/api/team.ts
+++ b/server/routes/api/team.ts
@@ -16,6 +16,7 @@ router.post("team.update", auth(), async (ctx) => {
sharing,
guestSignin,
documentEmbeds,
+ memberCollectionCreate,
collaborativeEditing,
defaultCollectionId,
defaultUserRole,
@@ -37,6 +38,7 @@ router.post("team.update", auth(), async (ctx) => {
sharing,
guestSignin,
documentEmbeds,
+ memberCollectionCreate,
collaborativeEditing,
defaultCollectionId,
defaultUserRole,
diff --git a/shared/i18n/locales/en_US/translation.json b/shared/i18n/locales/en_US/translation.json
index cf3a49cc5..f78d40d43 100644
--- a/shared/i18n/locales/en_US/translation.json
+++ b/shared/i18n/locales/en_US/translation.json
@@ -616,6 +616,8 @@
"When enabled, documents can be shared publicly on the internet by any team member": "When enabled, documents can be shared publicly on the internet by any team member",
"Rich service embeds": "Rich service embeds",
"Links to supported services are shown as rich embeds within your documents": "Links to supported services are shown as rich embeds within your documents",
+ "Collection creation": "Collection creation",
+ "Allow members to create new collections within the knowledge base": "Allow members to create new collections within the knowledge base",
"Default role": "Default role",
"The default user role for new accounts. Changing this setting does not affect existing user accounts.": "The default user role for new accounts. Changing this setting does not affect existing user accounts.",
"Sharing is currently disabled.": "Sharing is currently disabled.",