mirror of
https://github.com/overleaf/overleaf.git
synced 2024-11-21 20:47:08 -05:00
[web] Upgrade restricted user access if they are invited members (#9401)
* [web] Upgrade restricted user access if they are invited members Previously, if a user joined a project via a read-only link and later on joined the project via an invite, we would still treat them as restricted users, disabling chat and commenting. This patch changes that, so that we do *not* consider an invited user restricted. GitOrigin-RevId: e2acdfd29cc0687cb7276310a9c96d697087b21a
This commit is contained in:
parent
855adb73ef
commit
b5e2604041
7 changed files with 55 additions and 15 deletions
|
@ -11,12 +11,19 @@ const Errors = require('../Errors/Errors')
|
|||
const { hasAdminAccess } = require('../Helpers/AdminAuthorizationHelper')
|
||||
const Settings = require('@overleaf/settings')
|
||||
|
||||
function isRestrictedUser(userId, privilegeLevel, isTokenMember) {
|
||||
function isRestrictedUser(
|
||||
userId,
|
||||
privilegeLevel,
|
||||
isTokenMember,
|
||||
isInvitedMember
|
||||
) {
|
||||
if (privilegeLevel === PrivilegeLevels.NONE) {
|
||||
return true
|
||||
}
|
||||
return (
|
||||
privilegeLevel === PrivilegeLevels.READ_ONLY && (isTokenMember || !userId)
|
||||
privilegeLevel === PrivilegeLevels.READ_ONLY &&
|
||||
(isTokenMember || !userId) &&
|
||||
!isInvitedMember
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -30,7 +37,17 @@ async function isRestrictedUserForProject(userId, projectId, token) {
|
|||
userId,
|
||||
projectId
|
||||
)
|
||||
return isRestrictedUser(userId, privilegeLevel, isTokenMember)
|
||||
const isInvitedMember =
|
||||
await CollaboratorsGetter.promises.isUserInvitedMemberOfProject(
|
||||
userId,
|
||||
projectId
|
||||
)
|
||||
return isRestrictedUser(
|
||||
userId,
|
||||
privilegeLevel,
|
||||
isTokenMember,
|
||||
isInvitedMember
|
||||
)
|
||||
}
|
||||
|
||||
async function getPublicAccessLevel(projectId) {
|
||||
|
|
|
@ -118,6 +118,9 @@ async function getInvitedCollaboratorCount(projectId) {
|
|||
}
|
||||
|
||||
async function isUserInvitedMemberOfProject(userId, projectId) {
|
||||
if (!userId) {
|
||||
return false
|
||||
}
|
||||
const members = await getMemberIdsWithPrivilegeLevels(projectId)
|
||||
for (const member of members) {
|
||||
if (
|
||||
|
|
|
@ -131,10 +131,16 @@ async function _buildJoinProjectView(req, projectId, userId) {
|
|||
userId,
|
||||
projectId
|
||||
)
|
||||
const isInvitedMember =
|
||||
await CollaboratorsGetter.promises.isUserInvitedMemberOfProject(
|
||||
userId,
|
||||
projectId
|
||||
)
|
||||
const isRestrictedUser = AuthorizationManager.isRestrictedUser(
|
||||
userId,
|
||||
privilegeLevel,
|
||||
isTokenMember
|
||||
isTokenMember,
|
||||
isInvitedMember
|
||||
)
|
||||
return {
|
||||
project: ProjectEditorHandler.buildProjectModelView(
|
||||
|
|
|
@ -833,6 +833,13 @@ const ProjectController = {
|
|||
}
|
||||
CollaboratorsGetter.userIsTokenMember(userId, projectId, cb)
|
||||
},
|
||||
isInvitedMember(cb) {
|
||||
CollaboratorsGetter.isUserInvitedMemberOfProject(
|
||||
userId,
|
||||
projectId,
|
||||
cb
|
||||
)
|
||||
},
|
||||
brandVariation: [
|
||||
'project',
|
||||
(results, cb) => {
|
||||
|
@ -1060,6 +1067,7 @@ const ProjectController = {
|
|||
subscription,
|
||||
userIsMemberOfGroupSubscription,
|
||||
isTokenMember,
|
||||
isInvitedMember,
|
||||
brandVariation,
|
||||
newSourceEditorAssignment,
|
||||
pdfjsAssignment,
|
||||
|
@ -1220,7 +1228,8 @@ const ProjectController = {
|
|||
isRestrictedTokenMember: AuthorizationManager.isRestrictedUser(
|
||||
userId,
|
||||
privilegeLevel,
|
||||
isTokenMember
|
||||
isTokenMember,
|
||||
isInvitedMember
|
||||
),
|
||||
languages: Settings.languages,
|
||||
learnedWords,
|
||||
|
|
|
@ -65,17 +65,19 @@ describe('AuthorizationManager', function () {
|
|||
describe('isRestrictedUser', function () {
|
||||
it('should produce the correct values', function () {
|
||||
const notRestrictedScenarios = [
|
||||
[null, 'readAndWrite', false],
|
||||
['id', 'readAndWrite', true],
|
||||
['id', 'readOnly', false],
|
||||
[null, 'readAndWrite', false, false],
|
||||
['id', 'readAndWrite', true, false],
|
||||
['id', 'readAndWrite', true, true],
|
||||
['id', 'readOnly', false, false],
|
||||
['id', 'readOnly', false, true],
|
||||
]
|
||||
const restrictedScenarios = [
|
||||
[null, 'readOnly', false],
|
||||
['id', 'readOnly', true],
|
||||
[null, false, true],
|
||||
[null, false, false],
|
||||
['id', false, true],
|
||||
['id', false, false],
|
||||
[null, 'readOnly', false, false],
|
||||
['id', 'readOnly', true, false],
|
||||
[null, false, true, false],
|
||||
[null, false, false, false],
|
||||
['id', false, true, false],
|
||||
['id', false, false, false],
|
||||
]
|
||||
for (const notRestrictedArgs of notRestrictedScenarios) {
|
||||
expect(
|
||||
|
|
|
@ -59,6 +59,7 @@ describe('EditorHttpController', function () {
|
|||
getInvitedMembersWithPrivilegeLevels: sinon
|
||||
.stub()
|
||||
.resolves(['members', 'mock']),
|
||||
isUserInvitedMemberOfProject: sinon.stub().resolves(false),
|
||||
},
|
||||
}
|
||||
this.CollaboratorsHandler = {
|
||||
|
@ -234,7 +235,7 @@ describe('EditorHttpController', function () {
|
|||
this.req.query = { user_id: 'anonymous-user' }
|
||||
this.res.json.callsFake(() => done())
|
||||
this.AuthorizationManager.isRestrictedUser
|
||||
.withArgs(null, 'readOnly', false)
|
||||
.withArgs(null, 'readOnly', false, false)
|
||||
.returns(true)
|
||||
this.AuthorizationManager.promises.getPrivilegeLevelForProject
|
||||
.withArgs(null, this.project._id, this.token)
|
||||
|
|
|
@ -96,6 +96,7 @@ describe('ProjectController', function () {
|
|||
}
|
||||
this.CollaboratorsGetter = {
|
||||
userIsTokenMember: sinon.stub().callsArgWith(2, null, false),
|
||||
isUserInvitedMemberOfProject: sinon.stub().callsArgWith(2, null, true),
|
||||
}
|
||||
this.ProjectEntityHandler = {}
|
||||
this.NotificationBuilder = {
|
||||
|
@ -1014,6 +1015,7 @@ describe('ProjectController', function () {
|
|||
})
|
||||
|
||||
it('should add isRestrictedTokenMember', function (done) {
|
||||
this.AuthorizationManager.isRestrictedUser.returns(false)
|
||||
this.res.render = (pageName, opts) => {
|
||||
opts.isRestrictedTokenMember.should.exist
|
||||
opts.isRestrictedTokenMember.should.equal(false)
|
||||
|
|
Loading…
Reference in a new issue