mirror of
https://github.com/overleaf/overleaf.git
synced 2024-11-21 20:47:08 -05:00
* Make Operation.fromRaw parse AddComment operations * Send operations to project-history when deleting comments * remove RedisManager.updateDocument call * format fix * Revert "remove RedisManager.updateDocument call" This reverts commit 5d45f34b5919bf5a85e8475e5a450bcb213d3f82. * remove versions from deleteComment op * pass userId to deleteComment operation * revert userId from chat service * revert userid from chat tests * format:fix * document updater fix tests * format:fix * fix web unit test * deleteThread test fix * send only if historyRangesSupport is true * use headers to pass userId * set historyRangesSupport in tests * optional headers * Revert "use headers to pass userId" This reverts commit e916c469f95b1ac166e30e12e735171eb814af01. --------- Co-authored-by: Eric Mc Sween <5454374+emcsween@users.noreply.github.com> GitOrigin-RevId: 14c10669e43d76883dbaaa8ab55e102b5ebadd38
This commit is contained in:
parent
51994579cd
commit
3e701f1388
8 changed files with 125 additions and 18 deletions
|
@ -422,7 +422,7 @@ const DocumentManager = {
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
|
|
||||||
deleteComment(projectId, docId, commentId, _callback) {
|
deleteComment(projectId, docId, commentId, userId, _callback) {
|
||||||
const timer = new Metrics.Timer('docManager.deleteComment')
|
const timer = new Metrics.Timer('docManager.deleteComment')
|
||||||
const callback = (...args) => {
|
const callback = (...args) => {
|
||||||
timer.done()
|
timer.done()
|
||||||
|
@ -432,7 +432,17 @@ const DocumentManager = {
|
||||||
DocumentManager.getDoc(
|
DocumentManager.getDoc(
|
||||||
projectId,
|
projectId,
|
||||||
docId,
|
docId,
|
||||||
(error, lines, version, ranges) => {
|
(
|
||||||
|
error,
|
||||||
|
lines,
|
||||||
|
version,
|
||||||
|
ranges,
|
||||||
|
pathname,
|
||||||
|
projectHistoryId,
|
||||||
|
unflushedTime,
|
||||||
|
alreadyLoaded,
|
||||||
|
historyRangesSupport
|
||||||
|
) => {
|
||||||
if (error) {
|
if (error) {
|
||||||
return callback(error)
|
return callback(error)
|
||||||
}
|
}
|
||||||
|
@ -457,6 +467,21 @@ const DocumentManager = {
|
||||||
[],
|
[],
|
||||||
newRanges,
|
newRanges,
|
||||||
{},
|
{},
|
||||||
|
error => {
|
||||||
|
if (error) {
|
||||||
|
return callback(error)
|
||||||
|
}
|
||||||
|
if (historyRangesSupport) {
|
||||||
|
ProjectHistoryRedisManager.queueOps(
|
||||||
|
projectId,
|
||||||
|
JSON.stringify({
|
||||||
|
pathname,
|
||||||
|
deleteComment: commentId,
|
||||||
|
meta: {
|
||||||
|
ts: new Date(),
|
||||||
|
user_id: userId,
|
||||||
|
},
|
||||||
|
}),
|
||||||
error => {
|
error => {
|
||||||
if (error) {
|
if (error) {
|
||||||
return callback(error)
|
return callback(error)
|
||||||
|
@ -464,6 +489,11 @@ const DocumentManager = {
|
||||||
callback()
|
callback()
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
} else {
|
||||||
|
callback()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
|
@ -659,13 +689,14 @@ const DocumentManager = {
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
|
|
||||||
deleteCommentWithLock(projectId, docId, threadId, callback) {
|
deleteCommentWithLock(projectId, docId, threadId, userId, callback) {
|
||||||
const UpdateManager = require('./UpdateManager')
|
const UpdateManager = require('./UpdateManager')
|
||||||
UpdateManager.lockUpdatesAndDo(
|
UpdateManager.lockUpdatesAndDo(
|
||||||
DocumentManager.deleteComment,
|
DocumentManager.deleteComment,
|
||||||
projectId,
|
projectId,
|
||||||
docId,
|
docId,
|
||||||
threadId,
|
threadId,
|
||||||
|
userId,
|
||||||
callback
|
callback
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
|
|
|
@ -307,16 +307,23 @@ function deleteComment(req, res, next) {
|
||||||
doc_id: docId,
|
doc_id: docId,
|
||||||
comment_id: commentId,
|
comment_id: commentId,
|
||||||
} = req.params
|
} = req.params
|
||||||
|
const userId = req.body.user_id
|
||||||
logger.debug({ projectId, docId, commentId }, 'deleting comment via http')
|
logger.debug({ projectId, docId, commentId }, 'deleting comment via http')
|
||||||
const timer = new Metrics.Timer('http.deleteComment')
|
const timer = new Metrics.Timer('http.deleteComment')
|
||||||
DocumentManager.deleteCommentWithLock(projectId, docId, commentId, error => {
|
DocumentManager.deleteCommentWithLock(
|
||||||
|
projectId,
|
||||||
|
docId,
|
||||||
|
commentId,
|
||||||
|
userId,
|
||||||
|
error => {
|
||||||
timer.done()
|
timer.done()
|
||||||
if (error) {
|
if (error) {
|
||||||
return next(error)
|
return next(error)
|
||||||
}
|
}
|
||||||
logger.debug({ projectId, docId, commentId }, 'deleted comment via http')
|
logger.debug({ projectId, docId, commentId }, 'deleted comment via http')
|
||||||
res.sendStatus(204) // No Content
|
res.sendStatus(204) // No Content
|
||||||
})
|
}
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
function updateProject(req, res, next) {
|
function updateProject(req, res, next) {
|
||||||
|
|
|
@ -833,13 +833,25 @@ describe('DocumentManager', function () {
|
||||||
this.lines = ['original', 'lines']
|
this.lines = ['original', 'lines']
|
||||||
this.ranges = { comments: ['one', 'two', 'three'] }
|
this.ranges = { comments: ['one', 'two', 'three'] }
|
||||||
this.updated_ranges = { comments: ['one', 'three'] }
|
this.updated_ranges = { comments: ['one', 'three'] }
|
||||||
|
this.historyRangesSupport = true
|
||||||
this.DocumentManager.getDoc = sinon
|
this.DocumentManager.getDoc = sinon
|
||||||
.stub()
|
.stub()
|
||||||
.yields(null, this.lines, this.version, this.ranges)
|
.yields(
|
||||||
|
null,
|
||||||
|
this.lines,
|
||||||
|
this.version,
|
||||||
|
this.ranges,
|
||||||
|
this.pathname,
|
||||||
|
this.projectHistoryId,
|
||||||
|
Date.now() - 1e9,
|
||||||
|
true,
|
||||||
|
this.historyRangesSupport
|
||||||
|
)
|
||||||
this.RangesManager.deleteComment = sinon
|
this.RangesManager.deleteComment = sinon
|
||||||
.stub()
|
.stub()
|
||||||
.returns(this.updated_ranges)
|
.returns(this.updated_ranges)
|
||||||
this.RedisManager.updateDocument = sinon.stub().yields()
|
this.RedisManager.updateDocument = sinon.stub().yields()
|
||||||
|
this.ProjectHistoryRedisManager.queueOps = sinon.stub().yields()
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('successfully', function () {
|
describe('successfully', function () {
|
||||||
|
@ -848,6 +860,7 @@ describe('DocumentManager', function () {
|
||||||
this.project_id,
|
this.project_id,
|
||||||
this.doc_id,
|
this.doc_id,
|
||||||
this.comment_id,
|
this.comment_id,
|
||||||
|
this.user_id,
|
||||||
this.callback
|
this.callback
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
@ -878,6 +891,23 @@ describe('DocumentManager', function () {
|
||||||
.should.equal(true)
|
.should.equal(true)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('should queue the delete comment operation', function () {
|
||||||
|
this.ProjectHistoryRedisManager.queueOps
|
||||||
|
.calledWith(
|
||||||
|
this.project_id,
|
||||||
|
JSON.stringify({
|
||||||
|
pathname: this.pathname,
|
||||||
|
deleteComment: this.comment_id,
|
||||||
|
meta: {
|
||||||
|
ts: new Date(),
|
||||||
|
user_id: this.user_id,
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
sinon.match.func
|
||||||
|
)
|
||||||
|
.should.equal(true)
|
||||||
|
})
|
||||||
|
|
||||||
it('should call the callback', function () {
|
it('should call the callback', function () {
|
||||||
this.callback.called.should.equal(true)
|
this.callback.called.should.equal(true)
|
||||||
})
|
})
|
||||||
|
|
|
@ -11,6 +11,7 @@ describe('HttpController', function () {
|
||||||
'./HistoryManager': (this.HistoryManager = {
|
'./HistoryManager': (this.HistoryManager = {
|
||||||
flushProjectChangesAsync: sinon.stub(),
|
flushProjectChangesAsync: sinon.stub(),
|
||||||
}),
|
}),
|
||||||
|
'./ProjectHistoryRedisManager': (this.ProjectHistoryRedisManager = {}),
|
||||||
'./ProjectManager': (this.ProjectManager = {}),
|
'./ProjectManager': (this.ProjectManager = {}),
|
||||||
'./ProjectFlusher': { flushAllProjects() {} },
|
'./ProjectFlusher': { flushAllProjects() {} },
|
||||||
'./DeleteQueueManager': (this.DeleteQueueManager = {}),
|
'./DeleteQueueManager': (this.DeleteQueueManager = {}),
|
||||||
|
@ -651,6 +652,7 @@ describe('HttpController', function () {
|
||||||
|
|
||||||
describe('deleteComment', function () {
|
describe('deleteComment', function () {
|
||||||
beforeEach(function () {
|
beforeEach(function () {
|
||||||
|
this.user_id = 'user-id-123'
|
||||||
this.req = {
|
this.req = {
|
||||||
params: {
|
params: {
|
||||||
project_id: this.project_id,
|
project_id: this.project_id,
|
||||||
|
@ -658,7 +660,9 @@ describe('HttpController', function () {
|
||||||
comment_id: (this.comment_id = 'mock-comment-id'),
|
comment_id: (this.comment_id = 'mock-comment-id'),
|
||||||
},
|
},
|
||||||
query: {},
|
query: {},
|
||||||
body: {},
|
body: {
|
||||||
|
user_id: this.user_id,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -666,13 +670,20 @@ describe('HttpController', function () {
|
||||||
beforeEach(function () {
|
beforeEach(function () {
|
||||||
this.DocumentManager.deleteCommentWithLock = sinon
|
this.DocumentManager.deleteCommentWithLock = sinon
|
||||||
.stub()
|
.stub()
|
||||||
.callsArgWith(3)
|
.callsArgWith(4)
|
||||||
|
|
||||||
|
this.ProjectHistoryRedisManager.queueOps = sinon.stub()
|
||||||
this.HttpController.deleteComment(this.req, this.res, this.next)
|
this.HttpController.deleteComment(this.req, this.res, this.next)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should accept the change', function () {
|
it('should accept the change', function () {
|
||||||
this.DocumentManager.deleteCommentWithLock
|
this.DocumentManager.deleteCommentWithLock
|
||||||
.calledWith(this.project_id, this.doc_id, this.comment_id)
|
.calledWith(
|
||||||
|
this.project_id,
|
||||||
|
this.doc_id,
|
||||||
|
this.comment_id,
|
||||||
|
this.user_id
|
||||||
|
)
|
||||||
.should.equal(true)
|
.should.equal(true)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -702,7 +713,7 @@ describe('HttpController', function () {
|
||||||
beforeEach(function () {
|
beforeEach(function () {
|
||||||
this.DocumentManager.deleteCommentWithLock = sinon
|
this.DocumentManager.deleteCommentWithLock = sinon
|
||||||
.stub()
|
.stub()
|
||||||
.callsArgWith(3, new Error('oops'))
|
.callsArgWith(4, new Error('oops'))
|
||||||
this.HttpController.deleteComment(this.req, this.res, this.next)
|
this.HttpController.deleteComment(this.req, this.res, this.next)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
|
@ -14,6 +14,7 @@ import * as OperationsCompressor from './OperationsCompressor.js'
|
||||||
* @typedef {import('./types.ts').Op} Op
|
* @typedef {import('./types.ts').Op} Op
|
||||||
* @typedef {import('./types.ts').RenameUpdate} RenameUpdate
|
* @typedef {import('./types.ts').RenameUpdate} RenameUpdate
|
||||||
* @typedef {import('./types.ts').TextUpdate} TextUpdate
|
* @typedef {import('./types.ts').TextUpdate} TextUpdate
|
||||||
|
* @typedef {import('./types.ts').DeleteCommentUpdate} DeleteCommentUpdate
|
||||||
* @typedef {import('./types.ts').Update} Update
|
* @typedef {import('./types.ts').Update} Update
|
||||||
* @typedef {import('./types.ts').UpdateWithBlob} UpdateWithBlob
|
* @typedef {import('./types.ts').UpdateWithBlob} UpdateWithBlob
|
||||||
*/
|
*/
|
||||||
|
@ -77,6 +78,13 @@ function _convertToChange(projectId, updateWithBlob) {
|
||||||
if (update.v != null) {
|
if (update.v != null) {
|
||||||
v2DocVersions[update.doc] = { pathname, v: update.v }
|
v2DocVersions[update.doc] = { pathname, v: update.v }
|
||||||
}
|
}
|
||||||
|
} else if (isDeleteCommentUpdate(update)) {
|
||||||
|
operations = [
|
||||||
|
{
|
||||||
|
pathname: _convertPathname(update.pathname),
|
||||||
|
deleteComment: update.deleteComment,
|
||||||
|
},
|
||||||
|
]
|
||||||
} else {
|
} else {
|
||||||
const error = new Errors.UpdateWithUnknownFormatError(
|
const error = new Errors.UpdateWithUnknownFormatError(
|
||||||
'update with unknown format',
|
'update with unknown format',
|
||||||
|
@ -180,6 +188,14 @@ export function isAddUpdate(update) {
|
||||||
return _isAddDocUpdate(update) || _isAddFileUpdate(update)
|
return _isAddDocUpdate(update) || _isAddFileUpdate(update)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {Update} update
|
||||||
|
* @returns {update is DeleteCommentUpdate}
|
||||||
|
*/
|
||||||
|
export function isDeleteCommentUpdate(update) {
|
||||||
|
return 'deleteComment' in update
|
||||||
|
}
|
||||||
|
|
||||||
export function _convertPathname(pathname) {
|
export function _convertPathname(pathname) {
|
||||||
// Strip leading /
|
// Strip leading /
|
||||||
pathname = pathname.replace(/^\//, '')
|
pathname = pathname.replace(/^\//, '')
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
export type Update = TextUpdate | AddDocUpdate | AddFileUpdate | RenameUpdate
|
export type Update = TextUpdate | AddDocUpdate | AddFileUpdate | RenameUpdate | DeleteCommentUpdate
|
||||||
|
|
||||||
export type UpdateMeta = {
|
export type UpdateMeta = {
|
||||||
user_id: string
|
user_id: string
|
||||||
|
@ -18,6 +18,12 @@ export type TextUpdate = {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type DeleteCommentUpdate = {
|
||||||
|
pathname: string
|
||||||
|
deleteComment: string
|
||||||
|
meta: UpdateMeta
|
||||||
|
}
|
||||||
|
|
||||||
type ProjectUpdateBase = {
|
type ProjectUpdateBase = {
|
||||||
version: string
|
version: string
|
||||||
projectHistoryId: string
|
projectHistoryId: string
|
||||||
|
|
|
@ -212,11 +212,14 @@ function acceptChanges(projectId, docId, changeIds, callback) {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
function deleteThread(projectId, docId, threadId, callback) {
|
function deleteThread(projectId, docId, threadId, userId, callback) {
|
||||||
_makeRequest(
|
_makeRequest(
|
||||||
{
|
{
|
||||||
path: `/project/${projectId}/doc/${docId}/comment/${threadId}`,
|
path: `/project/${projectId}/doc/${docId}/comment/${threadId}`,
|
||||||
method: 'DELETE',
|
method: 'DELETE',
|
||||||
|
json: {
|
||||||
|
user_id: userId,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
projectId,
|
projectId,
|
||||||
'delete-thread',
|
'delete-thread',
|
||||||
|
|
|
@ -766,6 +766,7 @@ describe('DocumentUpdaterHandler', function () {
|
||||||
this.project_id,
|
this.project_id,
|
||||||
this.doc_id,
|
this.doc_id,
|
||||||
this.thread_id,
|
this.thread_id,
|
||||||
|
this.user_id,
|
||||||
this.callback
|
this.callback
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
@ -796,6 +797,7 @@ describe('DocumentUpdaterHandler', function () {
|
||||||
this.project_id,
|
this.project_id,
|
||||||
this.doc_id,
|
this.doc_id,
|
||||||
this.thread_id,
|
this.thread_id,
|
||||||
|
this.user_id,
|
||||||
this.callback
|
this.callback
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
@ -814,6 +816,7 @@ describe('DocumentUpdaterHandler', function () {
|
||||||
this.project_id,
|
this.project_id,
|
||||||
this.doc_id,
|
this.doc_id,
|
||||||
this.thread_id,
|
this.thread_id,
|
||||||
|
this.user_id,
|
||||||
this.callback
|
this.callback
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
Loading…
Reference in a new issue