mirror of
https://github.com/overleaf/overleaf.git
synced 2024-11-21 20:47:08 -05:00
Merge pull request #19249 from overleaf/ii-invite-token-response
[web] Fix share modal resend status code GitOrigin-RevId: 303f7b6c49d9522df6317789bb7c3c69d774715f
This commit is contained in:
parent
309340f94a
commit
b442a74f54
8 changed files with 122 additions and 59 deletions
|
@ -240,6 +240,12 @@ const CollaboratorsInviteController = {
|
|||
inviteId
|
||||
)
|
||||
|
||||
EditorRealTimeController.emitToRoom(
|
||||
projectId,
|
||||
'project:membership:changed',
|
||||
{ invites: true }
|
||||
)
|
||||
|
||||
if (invite != null) {
|
||||
ProjectAuditLogHandler.addEntryInBackground(
|
||||
projectId,
|
||||
|
@ -251,9 +257,11 @@ const CollaboratorsInviteController = {
|
|||
privileges: invite.privileges,
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
res.status(201).json({ newInviteId: invite._id })
|
||||
res.sendStatus(201)
|
||||
} else {
|
||||
res.sendStatus(404)
|
||||
}
|
||||
},
|
||||
|
||||
async viewInvite(req, res) {
|
||||
|
|
|
@ -657,8 +657,10 @@
|
|||
"invalid_password_too_similar": "",
|
||||
"invalid_request": "",
|
||||
"invite": "",
|
||||
"invite_expired": "",
|
||||
"invite_more_collabs": "",
|
||||
"invite_not_accepted": "",
|
||||
"invite_resend_limit_hit": "",
|
||||
"invited_to_group": "",
|
||||
"invited_to_group_have_individual_subcription": "",
|
||||
"invited_to_join": "",
|
||||
|
|
|
@ -44,25 +44,21 @@ Invite.propTypes = {
|
|||
|
||||
function ResendInvite({ invite }) {
|
||||
const { t } = useTranslation()
|
||||
const { updateProject, monitorRequest } = useShareProjectContext()
|
||||
const { _id: projectId, invites } = useProjectContext()
|
||||
const { monitorRequest, setError, inFlight } = useShareProjectContext()
|
||||
const { _id: projectId } = useProjectContext()
|
||||
|
||||
// const buttonRef = useRef(null)
|
||||
//
|
||||
const handleClick = useCallback(
|
||||
() =>
|
||||
monitorRequest(() => resendInvite(projectId, invite))
|
||||
.then(({ newInviteId }) => {
|
||||
const updatedInvites = invites.map(existing => {
|
||||
if (existing === invite) {
|
||||
// Update the invitation id for the project
|
||||
existing._id = newInviteId
|
||||
}
|
||||
return existing
|
||||
})
|
||||
updateProject({
|
||||
invites: updatedInvites,
|
||||
})
|
||||
.catch(error => {
|
||||
if (error?.response?.status === 404) {
|
||||
setError('invite_expired')
|
||||
}
|
||||
if (error?.response?.status === 429) {
|
||||
setError('invite_resend_limit_hit')
|
||||
}
|
||||
})
|
||||
.finally(() => {
|
||||
// NOTE: disabled as react-bootstrap v0.33.1 isn't forwarding the ref to the `button`
|
||||
|
@ -71,7 +67,7 @@ function ResendInvite({ invite }) {
|
|||
// }
|
||||
document.activeElement.blur()
|
||||
}),
|
||||
[invite, monitorRequest, projectId, invites, updateProject]
|
||||
[invite, monitorRequest, projectId, setError]
|
||||
)
|
||||
|
||||
return (
|
||||
|
@ -79,6 +75,7 @@ function ResendInvite({ invite }) {
|
|||
bsStyle="link"
|
||||
className="btn-inline-link"
|
||||
onClick={handleClick}
|
||||
disabled={inFlight}
|
||||
// ref={buttonRef}
|
||||
>
|
||||
{t('resend')}
|
||||
|
|
|
@ -43,21 +43,30 @@ Invite.propTypes = {
|
|||
|
||||
function ResendInvite({ invite }) {
|
||||
const { t } = useTranslation()
|
||||
const { monitorRequest } = useShareProjectContext()
|
||||
const { monitorRequest, setError, inFlight } = useShareProjectContext()
|
||||
const { _id: projectId } = useProjectContext()
|
||||
|
||||
// const buttonRef = useRef(null)
|
||||
//
|
||||
const handleClick = useCallback(
|
||||
() =>
|
||||
monitorRequest(() => resendInvite(projectId, invite)).finally(() => {
|
||||
// NOTE: disabled as react-bootstrap v0.33.1 isn't forwarding the ref to the `button`
|
||||
// if (buttonRef.current) {
|
||||
// buttonRef.current.blur()
|
||||
// }
|
||||
document.activeElement.blur()
|
||||
}),
|
||||
[invite, monitorRequest, projectId]
|
||||
monitorRequest(() => resendInvite(projectId, invite))
|
||||
.catch(error => {
|
||||
if (error?.response?.status === 404) {
|
||||
setError('invite_expired')
|
||||
}
|
||||
if (error?.response?.status === 429) {
|
||||
setError('invite_resend_limit_hit')
|
||||
}
|
||||
})
|
||||
.finally(() => {
|
||||
// NOTE: disabled as react-bootstrap v0.33.1 isn't forwarding the ref to the `button`
|
||||
// if (buttonRef.current) {
|
||||
// buttonRef.current.blur()
|
||||
// }
|
||||
document.activeElement.blur()
|
||||
}),
|
||||
[invite, monitorRequest, projectId, setError]
|
||||
)
|
||||
|
||||
return (
|
||||
|
@ -65,6 +74,7 @@ function ResendInvite({ invite }) {
|
|||
bsStyle="link"
|
||||
className="btn-inline-link"
|
||||
onClick={handleClick}
|
||||
disabled={inFlight}
|
||||
// ref={buttonRef}
|
||||
>
|
||||
{t('resend')}
|
||||
|
|
|
@ -98,6 +98,12 @@ function ErrorMessage({ error }: Pick<ShareProjectModalContentProps, 'error'>) {
|
|||
case 'too_many_requests':
|
||||
return <>{t('too_many_requests')}</>
|
||||
|
||||
case 'invite_expired':
|
||||
return <>{t('invite_expired')}</>
|
||||
|
||||
case 'invite_resend_limit_hit':
|
||||
return <>{t('invite_resend_limit_hit')}</>
|
||||
|
||||
default:
|
||||
return <>{t('generic_something_went_wrong')}</>
|
||||
}
|
||||
|
|
|
@ -98,6 +98,12 @@ function ErrorMessage({ error }: Pick<ShareProjectModalContentProps, 'error'>) {
|
|||
case 'too_many_requests':
|
||||
return <>{t('too_many_requests')}</>
|
||||
|
||||
case 'invite_expired':
|
||||
return <>{t('invite_expired')}</>
|
||||
|
||||
case 'invite_resend_limit_hit':
|
||||
return <>{t('invite_resend_limit_hit')}</>
|
||||
|
||||
default:
|
||||
return <>{t('generic_something_went_wrong')}</>
|
||||
}
|
||||
|
|
|
@ -951,10 +951,12 @@
|
|||
"invalid_request": "Invalid Request. Please correct the data and try again.",
|
||||
"invalid_zip_file": "Invalid zip file",
|
||||
"invite": "Invite",
|
||||
"invite_expired": "The invite may have expired",
|
||||
"invite_more_collabs": "Invite more collaborators",
|
||||
"invite_not_accepted": "Invite not yet accepted",
|
||||
"invite_not_valid": "This is not a valid project invite",
|
||||
"invite_not_valid_description": "The invite may have expired. Please contact the project owner",
|
||||
"invite_resend_limit_hit": "The invite resend limit hit",
|
||||
"invited_to_group": "<0>__inviterName__</0> has invited you to join a group subscription on __appName__",
|
||||
"invited_to_group_have_individual_subcription": "__inviterName__ has invited you to join a group __appName__ subscription. If you join this group, you may not need your individual subscription. Would you like to cancel it?",
|
||||
"invited_to_group_login": "To accept this invitation you need to log in as __emailAddress__.",
|
||||
|
|
|
@ -1269,46 +1269,78 @@ describe('CollaboratorsInviteController', function () {
|
|||
})
|
||||
|
||||
describe('when generateNewInvite does not produce an error', function () {
|
||||
beforeEach(function (done) {
|
||||
this.res.callback = () => done()
|
||||
this.CollaboratorsInviteController.generateNewInvite(
|
||||
this.req,
|
||||
this.res,
|
||||
this.next
|
||||
)
|
||||
})
|
||||
describe('and returns an invite object', function () {
|
||||
beforeEach(function (done) {
|
||||
this.res.callback = () => done()
|
||||
this.CollaboratorsInviteController.generateNewInvite(
|
||||
this.req,
|
||||
this.res,
|
||||
this.next
|
||||
)
|
||||
})
|
||||
|
||||
it('should produce a 201 response with new invitation id', function () {
|
||||
this.res.status.callCount.should.equal(1)
|
||||
this.res.status.calledWith(201).should.equal(true)
|
||||
expect(this.res.json.firstCall.args[0]).to.deep.equal({
|
||||
newInviteId: this.invite._id,
|
||||
it('should produce a 201 response', function () {
|
||||
this.res.sendStatus.callCount.should.equal(1)
|
||||
this.res.sendStatus.calledWith(201).should.equal(true)
|
||||
})
|
||||
|
||||
it('should have called generateNewInvite', function () {
|
||||
this.CollaboratorsInviteHandler.promises.generateNewInvite.callCount.should.equal(
|
||||
1
|
||||
)
|
||||
})
|
||||
|
||||
it('should have called emitToRoom', function () {
|
||||
this.EditorRealTimeController.emitToRoom.callCount.should.equal(1)
|
||||
this.EditorRealTimeController.emitToRoom
|
||||
.calledWith(this.projectId, 'project:membership:changed')
|
||||
.should.equal(true)
|
||||
})
|
||||
|
||||
it('should check the rate limit', function () {
|
||||
this.CollaboratorsInviteController.promises._checkRateLimit.callCount.should.equal(
|
||||
1
|
||||
)
|
||||
})
|
||||
|
||||
it('should add a project audit log entry', function () {
|
||||
this.ProjectAuditLogHandler.addEntryInBackground.should.have.been.calledWith(
|
||||
this.projectId,
|
||||
'resend-invite',
|
||||
this.currentUser._id,
|
||||
this.req.ip,
|
||||
{
|
||||
inviteId: this.invite._id,
|
||||
privileges: this.privileges,
|
||||
}
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
it('should have called generateNewInvite', function () {
|
||||
this.CollaboratorsInviteHandler.promises.generateNewInvite.callCount.should.equal(
|
||||
1
|
||||
)
|
||||
})
|
||||
describe('and returns a null invite', function () {
|
||||
beforeEach(function (done) {
|
||||
this.CollaboratorsInviteHandler.promises.generateNewInvite.resolves(
|
||||
null
|
||||
)
|
||||
this.res.callback = () => done()
|
||||
this.CollaboratorsInviteController.generateNewInvite(
|
||||
this.req,
|
||||
this.res,
|
||||
this.next
|
||||
)
|
||||
})
|
||||
|
||||
it('should check the rate limit', function () {
|
||||
this.CollaboratorsInviteController.promises._checkRateLimit.callCount.should.equal(
|
||||
1
|
||||
)
|
||||
})
|
||||
it('should have called emitToRoom', function () {
|
||||
this.EditorRealTimeController.emitToRoom.callCount.should.equal(1)
|
||||
this.EditorRealTimeController.emitToRoom
|
||||
.calledWith(this.projectId, 'project:membership:changed')
|
||||
.should.equal(true)
|
||||
})
|
||||
|
||||
it('should add a project audit log entry', function () {
|
||||
this.ProjectAuditLogHandler.addEntryInBackground.should.have.been.calledWith(
|
||||
this.projectId,
|
||||
'resend-invite',
|
||||
this.currentUser._id,
|
||||
this.req.ip,
|
||||
{
|
||||
inviteId: this.invite._id,
|
||||
privileges: this.privileges,
|
||||
}
|
||||
)
|
||||
it('should produce a 404 response when invite is null', function () {
|
||||
this.res.sendStatus.callCount.should.equal(1)
|
||||
this.res.sendStatus.should.have.been.calledWith(404)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
|
|
Loading…
Reference in a new issue