fix: Admins should be able to add and remove themselves from collections
This commit is contained in:
@@ -377,15 +377,29 @@ class WebsocketProvider extends React.Component<Props> {
|
||||
// or otherwise just remove any membership state we have for that user.
|
||||
this.socket.on(
|
||||
"collections.remove_user",
|
||||
action((event: WebsocketCollectionUserEvent) => {
|
||||
async (event: WebsocketCollectionUserEvent) => {
|
||||
if (auth.user && event.userId === auth.user.id) {
|
||||
collections.remove(event.collectionId);
|
||||
memberships.removeCollectionMemberships(event.collectionId);
|
||||
// check if we still have access to the collection
|
||||
try {
|
||||
await collections.fetch(event.collectionId, {
|
||||
force: true,
|
||||
});
|
||||
} catch (err) {
|
||||
if (
|
||||
err instanceof AuthorizationError ||
|
||||
err instanceof NotFoundError
|
||||
) {
|
||||
collections.remove(event.collectionId);
|
||||
memberships.remove(`${event.userId}-${event.collectionId}`);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
documents.removeCollectionDocuments(event.collectionId);
|
||||
} else {
|
||||
memberships.remove(`${event.userId}-${event.collectionId}`);
|
||||
}
|
||||
})
|
||||
}
|
||||
);
|
||||
|
||||
this.socket.on(
|
||||
|
||||
@@ -1,19 +1,24 @@
|
||||
import * as React from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useMenuState } from "reakit/Menu";
|
||||
import User from "~/models/User";
|
||||
import ContextMenu from "~/components/ContextMenu";
|
||||
import OverflowMenuButton from "~/components/ContextMenu/OverflowMenuButton";
|
||||
import Template from "~/components/ContextMenu/Template";
|
||||
import useCurrentUser from "~/hooks/useCurrentUser";
|
||||
|
||||
type Props = {
|
||||
user: User;
|
||||
onRemove: () => void;
|
||||
};
|
||||
|
||||
function MemberMenu({ onRemove }: Props) {
|
||||
function MemberMenu({ user, onRemove }: Props) {
|
||||
const { t } = useTranslation();
|
||||
const currentUser = useCurrentUser();
|
||||
const menu = useMenuState({
|
||||
modal: true,
|
||||
});
|
||||
|
||||
return (
|
||||
<>
|
||||
<OverflowMenuButton aria-label={t("Show menu")} {...menu} />
|
||||
@@ -23,7 +28,7 @@ function MemberMenu({ onRemove }: Props) {
|
||||
items={[
|
||||
{
|
||||
type: "button",
|
||||
title: t("Remove"),
|
||||
title: currentUser.id === user.id ? t("Leave") : t("Remove"),
|
||||
dangerous: true,
|
||||
onClick: onRemove,
|
||||
},
|
||||
|
||||
@@ -13,7 +13,6 @@ import PaginatedList from "~/components/PaginatedList";
|
||||
import Text from "~/components/Text";
|
||||
import useBoolean from "~/hooks/useBoolean";
|
||||
import useCurrentTeam from "~/hooks/useCurrentTeam";
|
||||
import useCurrentUser from "~/hooks/useCurrentUser";
|
||||
import useDebouncedCallback from "~/hooks/useDebouncedCallback";
|
||||
import useStores from "~/hooks/useStores";
|
||||
import useToasts from "~/hooks/useToasts";
|
||||
@@ -26,7 +25,6 @@ type Props = {
|
||||
function AddPeopleToCollection({ collection }: Props) {
|
||||
const { memberships, users } = useStores();
|
||||
const { showToast } = useToasts();
|
||||
const user = useCurrentUser();
|
||||
const team = useCurrentTeam();
|
||||
const { t } = useTranslation();
|
||||
const [
|
||||
@@ -99,9 +97,7 @@ function AddPeopleToCollection({ collection }: Props) {
|
||||
<Empty>{t("No people left to add")}</Empty>
|
||||
)
|
||||
}
|
||||
items={users
|
||||
.notInCollection(collection.id, query)
|
||||
.filter((member) => member.id !== user.id)}
|
||||
items={users.notInCollection(collection.id, query)}
|
||||
fetch={query ? undefined : users.fetchPage}
|
||||
renderItem={(item: User) => (
|
||||
<MemberListItem
|
||||
|
||||
@@ -60,7 +60,7 @@ const MemberListItem = ({
|
||||
)}
|
||||
{canEdit && (
|
||||
<>
|
||||
{onRemove && <MemberMenu onRemove={onRemove} />}
|
||||
{onRemove && <MemberMenu user={user} onRemove={onRemove} />}
|
||||
{onAdd && (
|
||||
<Button onClick={onAdd} neutral>
|
||||
{t("Add")}
|
||||
|
||||
@@ -318,7 +318,7 @@ function CollectionPermissions({ collectionId }: Props) {
|
||||
key={item.id}
|
||||
user={item}
|
||||
membership={memberships.get(`${item.id}-${collection.id}`)}
|
||||
canEdit={item.id !== user.id}
|
||||
canEdit={item.id !== user.id || user.isAdmin}
|
||||
onRemove={() => handleRemoveUser(item)}
|
||||
onUpdate={(permission) => handleUpdateUser(item, permission)}
|
||||
/>
|
||||
|
||||
@@ -13,7 +13,7 @@ import { colorPalette } from "@shared/utils/collections";
|
||||
import collectionExporter from "@server/commands/collectionExporter";
|
||||
import teamUpdater from "@server/commands/teamUpdater";
|
||||
import { sequelize } from "@server/database/sequelize";
|
||||
import { AuthorizationError, ValidationError } from "@server/errors";
|
||||
import { ValidationError } from "@server/errors";
|
||||
import auth from "@server/middlewares/authentication";
|
||||
import { rateLimiter } from "@server/middlewares/rateLimiter";
|
||||
import { transaction } from "@server/middlewares/transaction";
|
||||
@@ -406,10 +406,6 @@ router.post(
|
||||
lock: transaction.LOCK.UPDATE,
|
||||
});
|
||||
|
||||
if (userId === actor.id) {
|
||||
throw AuthorizationError("You cannot add yourself to a collection");
|
||||
}
|
||||
|
||||
if (permission) {
|
||||
assertCollectionPermission(permission);
|
||||
}
|
||||
|
||||
@@ -346,6 +346,7 @@
|
||||
"Delete group": "Delete group",
|
||||
"Group options": "Group options",
|
||||
"Member options": "Member options",
|
||||
"Leave": "Leave",
|
||||
"New child document": "New child document",
|
||||
"New document in <em>{{ collectionName }}</em>": "New document in <em>{{ collectionName }}</em>",
|
||||
"New template": "New template",
|
||||
|
||||
Reference in New Issue
Block a user