Share Permissions (#761)
* Share restrictions * Tweak language, add spec
This commit is contained in:
@@ -4,7 +4,7 @@ import Sequelize from 'sequelize';
|
||||
import auth from '../middlewares/authentication';
|
||||
import pagination from './middlewares/pagination';
|
||||
import { presentShare } from '../presenters';
|
||||
import { Document, User, Share } from '../models';
|
||||
import { Document, User, Share, Team } from '../models';
|
||||
import policy from '../policies';
|
||||
|
||||
const Op = Sequelize.Op;
|
||||
@@ -57,7 +57,9 @@ router.post('shares.create', auth(), async ctx => {
|
||||
|
||||
const user = ctx.state.user;
|
||||
const document = await Document.findById(documentId);
|
||||
const team = await Team.findById(user.teamId);
|
||||
authorize(user, 'share', document);
|
||||
authorize(user, 'share', team);
|
||||
|
||||
const [share] = await Share.findOrCreate({
|
||||
where: {
|
||||
|
||||
@@ -122,6 +122,15 @@ describe('#shares.create', async () => {
|
||||
expect(body.data.id).toBe(share.id);
|
||||
});
|
||||
|
||||
it('should not allow creating a share record if disabled', async () => {
|
||||
const { user, document, team } = await seed();
|
||||
await team.update({ sharing: false });
|
||||
const res = await server.post('/api/shares.create', {
|
||||
body: { token: user.getJwtToken(), documentId: document.id },
|
||||
});
|
||||
expect(res.status).toEqual(403);
|
||||
});
|
||||
|
||||
it('should require authentication', async () => {
|
||||
const { document } = await seed();
|
||||
const res = await server.post('/api/shares.create', {
|
||||
|
||||
@@ -12,7 +12,7 @@ const { authorize } = policy;
|
||||
const router = new Router();
|
||||
|
||||
router.post('team.update', auth(), async ctx => {
|
||||
const { name, avatarUrl } = ctx.body;
|
||||
const { name, avatarUrl, sharing } = ctx.body;
|
||||
const endpoint = publicS3Endpoint();
|
||||
|
||||
const user = ctx.state.user;
|
||||
@@ -20,6 +20,7 @@ router.post('team.update', auth(), async ctx => {
|
||||
authorize(user, 'update', team);
|
||||
|
||||
if (name) team.name = name;
|
||||
if (sharing !== undefined) team.sharing = sharing;
|
||||
if (avatarUrl && avatarUrl.startsWith(`${endpoint}/uploads/${user.id}`)) {
|
||||
team.avatarUrl = avatarUrl;
|
||||
}
|
||||
|
||||
12
server/migrations/20180819054252-disable-sharing.js
Normal file
12
server/migrations/20180819054252-disable-sharing.js
Normal file
@@ -0,0 +1,12 @@
|
||||
module.exports = {
|
||||
up: async (queryInterface, Sequelize) => {
|
||||
await queryInterface.addColumn('teams', 'sharing', {
|
||||
type: Sequelize.BOOLEAN,
|
||||
allowNull: false,
|
||||
defaultValue: true
|
||||
});
|
||||
},
|
||||
down: async (queryInterface, Sequelize) => {
|
||||
await queryInterface.removeColumn('teams', 'sharing');
|
||||
}
|
||||
}
|
||||
@@ -17,6 +17,7 @@ const Team = sequelize.define(
|
||||
slackId: { type: DataTypes.STRING, allowNull: true },
|
||||
googleId: { type: DataTypes.STRING, allowNull: true },
|
||||
avatarUrl: { type: DataTypes.STRING, allowNull: true },
|
||||
sharing: { type: DataTypes.BOOLEAN, allowNull: false, defaultValue: true },
|
||||
slackData: DataTypes.JSONB,
|
||||
},
|
||||
{
|
||||
@@ -39,11 +40,16 @@ const uploadAvatar = async model => {
|
||||
const endpoint = publicS3Endpoint();
|
||||
|
||||
if (model.avatarUrl && !model.avatarUrl.startsWith(endpoint)) {
|
||||
const newUrl = await uploadToS3FromUrl(
|
||||
model.avatarUrl,
|
||||
`avatars/${model.id}/${uuid.v4()}`
|
||||
);
|
||||
if (newUrl) model.avatarUrl = newUrl;
|
||||
try {
|
||||
const newUrl = await uploadToS3FromUrl(
|
||||
model.avatarUrl,
|
||||
`avatars/${model.id}/${uuid.v4()}`
|
||||
);
|
||||
if (newUrl) model.avatarUrl = newUrl;
|
||||
} catch (err) {
|
||||
// we can try again next time
|
||||
console.error(err);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -7,6 +7,11 @@ const { allow } = policy;
|
||||
|
||||
allow(User, 'read', Team, (user, team) => team && user.teamId === team.id);
|
||||
|
||||
allow(User, 'share', Team, (user, team) => {
|
||||
if (!team || user.teamId !== team.id) return false;
|
||||
return team.sharing;
|
||||
});
|
||||
|
||||
allow(User, ['update', 'export'], Team, (user, team) => {
|
||||
if (!team || user.teamId !== team.id) return false;
|
||||
if (user.isAdmin) return true;
|
||||
|
||||
@@ -11,6 +11,7 @@ function present(ctx: Object, team: Team) {
|
||||
team.avatarUrl || (team.slackData ? team.slackData.image_88 : null),
|
||||
slackConnected: !!team.slackId,
|
||||
googleConnected: !!team.googleId,
|
||||
sharing: team.sharing,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user