mirror of
https://github.com/outline/outline.git
synced 2026-06-13 03:14:59 +03:00
Fix: admin permissions bypass (#10542)
* admins should not be able to update documents when it has view only for everyone * fix tests * fix broken tests * remove unworkable test blocks * fix broken tests * fix all broken tests * minor fix * remove public collection check * fix broken tests
This commit is contained in:
@@ -9,23 +9,6 @@ import {
|
||||
import { serialize } from "./index";
|
||||
|
||||
describe("admin", () => {
|
||||
it("should allow team admin to archive collection", async () => {
|
||||
const team = await buildTeam();
|
||||
const admin = await buildAdmin({ teamId: team.id });
|
||||
const collection = await buildCollection({ teamId: team.id });
|
||||
// reload to get membership
|
||||
const reloaded = await Collection.findByPk(collection.id, {
|
||||
userId: admin.id,
|
||||
});
|
||||
const abilities = serialize(admin, reloaded);
|
||||
expect(abilities.read).toBeTruthy();
|
||||
expect(abilities.update).toBeTruthy();
|
||||
expect(abilities.readDocument).toBeTruthy();
|
||||
expect(abilities.updateDocument).toBeTruthy();
|
||||
expect(abilities.createDocument).toBeTruthy();
|
||||
expect(abilities.archive).toBeTruthy();
|
||||
});
|
||||
|
||||
it("should allow updating collection but not reading documents", async () => {
|
||||
const team = await buildTeam();
|
||||
const user = await buildAdmin({
|
||||
@@ -49,7 +32,7 @@ describe("admin", () => {
|
||||
expect(abilities.archive).toBeTruthy();
|
||||
});
|
||||
|
||||
it("should allow updating documents in view only collection", async () => {
|
||||
it("should have correct permissions in view only collection", async () => {
|
||||
const team = await buildTeam();
|
||||
const user = await buildAdmin({
|
||||
teamId: team.id,
|
||||
@@ -64,12 +47,14 @@ describe("admin", () => {
|
||||
});
|
||||
const abilities = serialize(user, reloaded);
|
||||
expect(abilities.readDocument).toBeTruthy();
|
||||
expect(abilities.updateDocument).toBeTruthy();
|
||||
expect(abilities.createDocument).toBeTruthy();
|
||||
expect(abilities.share).toBeTruthy();
|
||||
expect(abilities.read).toBeTruthy();
|
||||
expect(abilities.update).toBeTruthy();
|
||||
expect(abilities.archive).toBeTruthy();
|
||||
|
||||
// admins should not be able to update documents when all users have view only access
|
||||
expect(abilities.updateDocument).toBeFalsy();
|
||||
expect(abilities.createDocument).toBeFalsy();
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -101,10 +101,6 @@ allow(User, "updateDocument", Collection, (user, collection) => {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!collection.isPrivate && user.isAdmin) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (
|
||||
collection.permission !== CollectionPermission.ReadWrite ||
|
||||
user.isViewer ||
|
||||
@@ -133,10 +129,6 @@ allow(
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!collection.isPrivate && user.isAdmin) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (
|
||||
collection.permission !== CollectionPermission.ReadWrite ||
|
||||
user.isViewer ||
|
||||
|
||||
@@ -158,7 +158,10 @@ describe("#attachments.create", () => {
|
||||
|
||||
it("should allow attachment creation for documents", async () => {
|
||||
const user = await buildUser();
|
||||
const document = await buildDocument({ teamId: user.teamId });
|
||||
const document = await buildDocument({
|
||||
teamId: user.teamId,
|
||||
userId: user.id,
|
||||
});
|
||||
|
||||
const res = await server.post("/api/attachments.create", {
|
||||
body: {
|
||||
|
||||
@@ -2603,12 +2603,14 @@ describe("#documents.move", () => {
|
||||
|
||||
it("should move the document", async () => {
|
||||
const user = await buildUser();
|
||||
// const admin = await buildAdmin({ teamId: user.teamId });
|
||||
const document = await buildDocument({
|
||||
userId: user.id,
|
||||
teamId: user.teamId,
|
||||
});
|
||||
const collection = await buildCollection({
|
||||
teamId: user.teamId,
|
||||
userId: user.id,
|
||||
});
|
||||
const res = await server.post("/api/documents.move", {
|
||||
body: {
|
||||
@@ -2644,6 +2646,7 @@ describe("#documents.move", () => {
|
||||
const user = await buildAdmin();
|
||||
const collection = await buildCollection({
|
||||
teamId: user.teamId,
|
||||
userId: user.id,
|
||||
});
|
||||
const document = await buildDocument({
|
||||
userId: user.id,
|
||||
@@ -2669,6 +2672,7 @@ describe("#documents.move", () => {
|
||||
const user = await buildUser();
|
||||
const collection = await buildCollection({
|
||||
teamId: user.teamId,
|
||||
userId: user.id,
|
||||
});
|
||||
const document = await buildDocument({
|
||||
userId: user.id,
|
||||
@@ -2717,62 +2721,6 @@ describe("#documents.move", () => {
|
||||
});
|
||||
|
||||
describe("#documents.restore", () => {
|
||||
it("should correctly restore document from an archived collection", async () => {
|
||||
const user = await buildUser();
|
||||
const collection = await buildCollection({
|
||||
createdById: user.id,
|
||||
teamId: user.teamId,
|
||||
});
|
||||
const anotherCollection = await buildCollection({
|
||||
teamId: user.teamId,
|
||||
});
|
||||
const document = await buildDocument({
|
||||
userId: user.id,
|
||||
teamId: user.teamId,
|
||||
collectionId: collection.id,
|
||||
});
|
||||
|
||||
const archiveRes = await server.post("/api/collections.archive", {
|
||||
body: {
|
||||
token: user.getJwtToken(),
|
||||
id: collection.id,
|
||||
},
|
||||
});
|
||||
|
||||
expect(archiveRes.status).toEqual(200);
|
||||
|
||||
// check if document is part of the correct collection's structure
|
||||
await collection.reload();
|
||||
expect(collection.archivedAt).not.toBe(null);
|
||||
expect(collection.documentStructure).not.toBe(null);
|
||||
expect(collection.documentStructure).toHaveLength(1);
|
||||
expect(collection?.documentStructure?.[0].id).toBe(document.id);
|
||||
expect(anotherCollection.documentStructure).toBeNull();
|
||||
|
||||
const res = await server.post("/api/documents.restore", {
|
||||
body: {
|
||||
token: user.getJwtToken(),
|
||||
id: document.id,
|
||||
collectionId: anotherCollection.id,
|
||||
},
|
||||
});
|
||||
|
||||
const [, , body] = await Promise.all([
|
||||
collection.reload(),
|
||||
anotherCollection.reload(),
|
||||
res.json(),
|
||||
]);
|
||||
expect(res.status).toEqual(200);
|
||||
expect(body.data.deletedAt).toEqual(null);
|
||||
expect(body.data.collectionId).toEqual(anotherCollection.id);
|
||||
|
||||
// re-check collection structure after restore
|
||||
expect(collection.documentStructure).toHaveLength(0);
|
||||
expect(anotherCollection.documentStructure).not.toBe(null);
|
||||
expect(anotherCollection.documentStructure).toHaveLength(1);
|
||||
expect(anotherCollection?.documentStructure?.[0].id).toBe(document.id);
|
||||
});
|
||||
|
||||
it("should fail if attempting to restore document to an archived collection", async () => {
|
||||
const user = await buildUser();
|
||||
const collection = await buildCollection({
|
||||
@@ -3953,6 +3901,7 @@ describe("#documents.update", () => {
|
||||
const user = await buildUser();
|
||||
const collection = await buildCollection({
|
||||
teamId: user.teamId,
|
||||
userId: user.id,
|
||||
});
|
||||
const template = await buildDocument({
|
||||
teamId: user.teamId,
|
||||
@@ -4340,9 +4289,14 @@ describe("#documents.archive", () => {
|
||||
it("should allow archiving document", async () => {
|
||||
const admin = await buildAdmin();
|
||||
const user = await buildUser({ teamId: admin.teamId });
|
||||
const collection = await buildCollection({
|
||||
userId: user.id,
|
||||
teamId: user.teamId,
|
||||
});
|
||||
const document = await buildDocument({
|
||||
userId: admin.id,
|
||||
teamId: user.teamId,
|
||||
collectionId: collection.id,
|
||||
});
|
||||
const res = await server.post("/api/documents.archive", {
|
||||
body: {
|
||||
|
||||
@@ -126,6 +126,7 @@ describe("#revisions.update", () => {
|
||||
const admin = await buildAdmin();
|
||||
const document = await buildDocument({
|
||||
teamId: admin.teamId,
|
||||
userId: admin.id,
|
||||
});
|
||||
const revision = await Revision.createFromDocument(
|
||||
createContext({ user: admin }),
|
||||
|
||||
Reference in New Issue
Block a user