Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allowing personal space editors to bahave as members #16

Merged
merged 3 commits into from
Jul 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 13 additions & 12 deletions packages/contracts/src/personal/PersonalSpaceAdminPlugin.sol
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,16 @@ contract PersonalSpaceAdminPlugin is PluginCloneable, ProposalUpgradeable, IEdit
this.submitRemoveEditor.selector ^
this.leaveSpace.selector;

/// @notice Raised when a wallet who is not an editor or a member attempts to do something
error NotAMember(address caller);

modifier onlyMembers() {
if (!isMember(msg.sender)) {
revert NotAMember(msg.sender);
}
_;
}

/// @notice Initializes the contract.
/// @param _dao The associated DAO.
/// @dev This method is required to support [ERC-1167](https://eips.ethereum.org/EIPS/eip-1167).
Expand Down Expand Up @@ -86,10 +96,7 @@ contract PersonalSpaceAdminPlugin is PluginCloneable, ProposalUpgradeable, IEdit
/// @notice Creates and executes a proposal that makes the DAO emit new content on the given space.
/// @param _contentUri The URI of the IPFS content to publish
/// @param _spacePlugin The address of the space plugin where changes will be executed
function submitEdits(
string memory _contentUri,
address _spacePlugin
) public auth(MEMBER_PERMISSION_ID) {
function submitEdits(string memory _contentUri, address _spacePlugin) public onlyMembers {
IDAO.Action[] memory _actions = new IDAO.Action[](1);

_actions[0].to = _spacePlugin;
Expand All @@ -105,10 +112,7 @@ contract PersonalSpaceAdminPlugin is PluginCloneable, ProposalUpgradeable, IEdit
/// @notice Creates and executes a proposal that makes the DAO accept the given DAO as a subspace.
/// @param _subspaceDao The address of the DAO that holds the new subspace
/// @param _spacePlugin The address of the space plugin where changes will be executed
function submitAcceptSubspace(
IDAO _subspaceDao,
address _spacePlugin
) public auth(MEMBER_PERMISSION_ID) {
function submitAcceptSubspace(IDAO _subspaceDao, address _spacePlugin) public onlyMembers {
IDAO.Action[] memory _actions = new IDAO.Action[](1);
_actions[0].to = _spacePlugin;
_actions[0].data = abi.encodeCall(SpacePlugin.acceptSubspace, (address(_subspaceDao)));
Expand All @@ -123,10 +127,7 @@ contract PersonalSpaceAdminPlugin is PluginCloneable, ProposalUpgradeable, IEdit
/// @notice Creates and executes a proposal that makes the DAO remove the given DAO as a subspace.
/// @param _subspaceDao The address of the DAO that holds the subspace to remove
/// @param _spacePlugin The address of the space plugin where changes will be executed
function submitRemoveSubspace(
IDAO _subspaceDao,
address _spacePlugin
) public auth(MEMBER_PERMISSION_ID) {
function submitRemoveSubspace(IDAO _subspaceDao, address _spacePlugin) public onlyMembers {
IDAO.Action[] memory _actions = new IDAO.Action[](1);
_actions[0].to = _spacePlugin;
_actions[0].data = abi.encodeCall(SpacePlugin.removeSubspace, (address(_subspaceDao)));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ contract PersonalSpaceAdminPluginSetup is PluginSetup {
PermissionLib.MultiTargetPermission[]
memory permissions = new PermissionLib.MultiTargetPermission[](2);

// Grant `ADMIN_EXECUTE_PERMISSION` of the plugin to the editor.
// Grant `EDITOR_PERMISSION` of the plugin to the editor.
permissions[0] = PermissionLib.MultiTargetPermission(
PermissionLib.Operation.Grant,
plugin,
Expand All @@ -73,7 +73,7 @@ contract PersonalSpaceAdminPluginSetup is PluginSetup {
}

/// @inheritdoc IPluginSetup
/// @dev Currently, there is no reliable way to revoke the `ADMIN_EXECUTE_PERMISSION_ID` from all addresses it has been granted to. Accordingly, only the `EXECUTE_PERMISSION_ID` is revoked for this uninstallation.
/// @dev There is no reliable way to revoke `EDITOR_PERMISSION_ID` from all addresses it has been granted to. Removing `EXECUTE_PERMISSION_ID` only, as being an editor or a member is useless without EXECUTE.
function prepareUninstallation(
address _dao,
SetupPayload calldata _payload
Expand Down
72 changes: 25 additions & 47 deletions packages/contracts/test/unit-testing/personal-space-admin-plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -255,24 +255,26 @@ describe('Personal Space Admin Plugin', function () {
).to.emit(personalSpaceVotingPlugin, 'ProposalCreated');
});

it('Only members can call content proposal wrappers', async () => {
await expect(
personalSpaceVotingPlugin
.connect(bob)
.submitEdits('ipfs://', spacePlugin.address)
).to.not.be.reverted;
await expect(
personalSpaceVotingPlugin
.connect(bob)
.submitAcceptSubspace(ADDRESS_TWO, spacePlugin.address)
).to.not.be.reverted;
await expect(
personalSpaceVotingPlugin
.connect(bob)
.submitRemoveSubspace(ADDRESS_THREE, spacePlugin.address)
).to.not.be.reverted;
it('Only members or editors can call content proposal wrappers', async () => {
for (const account of [alice, bob]) {
await expect(
personalSpaceVotingPlugin
.connect(account)
.submitEdits('ipfs://', spacePlugin.address)
).to.not.be.reverted;
await expect(
personalSpaceVotingPlugin
.connect(account)
.submitAcceptSubspace(ADDRESS_TWO, spacePlugin.address)
).to.not.be.reverted;
await expect(
personalSpaceVotingPlugin
.connect(account)
.submitRemoveSubspace(ADDRESS_THREE, spacePlugin.address)
).to.not.be.reverted;
}
expect(await personalSpaceVotingPlugin.proposalCount()).to.equal(
BigNumber.from(3)
BigNumber.from(6)
);

// Non members
Expand All @@ -281,46 +283,22 @@ describe('Personal Space Admin Plugin', function () {
.connect(carol)
.submitEdits('ipfs://', spacePlugin.address)
)
.to.be.revertedWithCustomError(
personalSpaceVotingPlugin,
'DaoUnauthorized'
)
.withArgs(
dao.address,
personalSpaceVotingPlugin.address,
carol.address,
MEMBER_PERMISSION_ID
);
.to.be.revertedWithCustomError(personalSpaceVotingPlugin, 'NotAMember')
.withArgs(carol.address);
await expect(
personalSpaceVotingPlugin
.connect(carol)
.submitAcceptSubspace(ADDRESS_TWO, spacePlugin.address)
)
.to.be.revertedWithCustomError(
personalSpaceVotingPlugin,
'DaoUnauthorized'
)
.withArgs(
dao.address,
personalSpaceVotingPlugin.address,
carol.address,
MEMBER_PERMISSION_ID
);
.to.be.revertedWithCustomError(personalSpaceVotingPlugin, 'NotAMember')
.withArgs(carol.address);
await expect(
personalSpaceVotingPlugin
.connect(carol)
.submitRemoveSubspace(ADDRESS_TWO, spacePlugin.address)
)
.to.be.revertedWithCustomError(
personalSpaceVotingPlugin,
'DaoUnauthorized'
)
.withArgs(
dao.address,
personalSpaceVotingPlugin.address,
carol.address,
MEMBER_PERMISSION_ID
);
.to.be.revertedWithCustomError(personalSpaceVotingPlugin, 'NotAMember')
.withArgs(carol.address);
});

it('Only editors can call permission proposal wrappers', async () => {
Expand Down
Loading