2020-10-06 06:31:34 -04:00
|
|
|
const { db } = require('../../infrastructure/mongodb')
|
|
|
|
const { normalizeQuery } = require('../Helpers/Mongo')
|
2020-08-11 05:35:08 -04:00
|
|
|
const OError = require('@overleaf/o-error')
|
2020-10-30 04:10:50 -04:00
|
|
|
const metrics = require('@overleaf/metrics')
|
2019-09-09 07:52:25 -04:00
|
|
|
const { promisifyAll } = require('../../util/promises')
|
2019-05-29 05:21:06 -04:00
|
|
|
const { Project } = require('../../models/Project')
|
2021-11-10 08:40:18 -05:00
|
|
|
const logger = require('@overleaf/logger')
|
2019-05-29 05:21:06 -04:00
|
|
|
const LockManager = require('../../infrastructure/LockManager')
|
2019-07-18 10:18:56 -04:00
|
|
|
const { DeletedProject } = require('../../models/DeletedProject')
|
2019-05-29 05:21:06 -04:00
|
|
|
|
2019-09-09 07:52:25 -04:00
|
|
|
const ProjectGetter = {
|
2019-05-29 05:21:06 -04:00
|
|
|
EXCLUDE_DEPTH: 8,
|
|
|
|
|
2021-02-17 08:00:48 -05:00
|
|
|
getProjectWithoutDocLines(projectId, callback) {
|
2019-05-29 05:21:06 -04:00
|
|
|
const excludes = {}
|
2021-02-17 08:00:48 -05:00
|
|
|
for (let i = 1; i <= ProjectGetter.EXCLUDE_DEPTH; i++) {
|
2019-05-29 05:21:06 -04:00
|
|
|
excludes[`rootFolder${Array(i).join('.folders')}.docs.lines`] = 0
|
|
|
|
}
|
2021-02-17 08:00:48 -05:00
|
|
|
ProjectGetter.getProject(projectId, excludes, callback)
|
2019-05-29 05:21:06 -04:00
|
|
|
},
|
|
|
|
|
2021-02-17 08:00:48 -05:00
|
|
|
getProjectWithOnlyFolders(projectId, callback) {
|
2019-05-29 05:21:06 -04:00
|
|
|
const excludes = {}
|
2021-02-17 08:00:48 -05:00
|
|
|
for (let i = 1; i <= ProjectGetter.EXCLUDE_DEPTH; i++) {
|
2019-05-29 05:21:06 -04:00
|
|
|
excludes[`rootFolder${Array(i).join('.folders')}.docs`] = 0
|
|
|
|
excludes[`rootFolder${Array(i).join('.folders')}.fileRefs`] = 0
|
|
|
|
}
|
2021-02-17 08:00:48 -05:00
|
|
|
ProjectGetter.getProject(projectId, excludes, callback)
|
2019-05-29 05:21:06 -04:00
|
|
|
},
|
|
|
|
|
2021-02-17 08:00:48 -05:00
|
|
|
getProject(projectId, projection, callback) {
|
2019-05-29 05:21:06 -04:00
|
|
|
if (typeof projection === 'function' && callback == null) {
|
|
|
|
callback = projection
|
|
|
|
projection = {}
|
|
|
|
}
|
2021-02-17 08:00:48 -05:00
|
|
|
if (projectId == null) {
|
|
|
|
return callback(new Error('no project id provided'))
|
2019-05-29 05:21:06 -04:00
|
|
|
}
|
|
|
|
if (typeof projection !== 'object') {
|
|
|
|
return callback(new Error('projection is not an object'))
|
|
|
|
}
|
|
|
|
|
2021-02-17 08:00:48 -05:00
|
|
|
if (projection.rootFolder || Object.keys(projection).length === 0) {
|
2019-05-29 05:21:06 -04:00
|
|
|
const ProjectEntityMongoUpdateHandler = require('./ProjectEntityMongoUpdateHandler')
|
2021-02-17 08:00:48 -05:00
|
|
|
LockManager.runWithLock(
|
2019-05-29 05:21:06 -04:00
|
|
|
ProjectEntityMongoUpdateHandler.LOCK_NAMESPACE,
|
2021-02-17 08:00:48 -05:00
|
|
|
projectId,
|
|
|
|
cb => ProjectGetter.getProjectWithoutLock(projectId, projection, cb),
|
2019-05-29 05:21:06 -04:00
|
|
|
callback
|
|
|
|
)
|
|
|
|
} else {
|
2021-02-17 08:00:48 -05:00
|
|
|
ProjectGetter.getProjectWithoutLock(projectId, projection, callback)
|
2019-05-29 05:21:06 -04:00
|
|
|
}
|
|
|
|
},
|
|
|
|
|
2021-02-17 08:00:48 -05:00
|
|
|
getProjectWithoutLock(projectId, projection, callback) {
|
2019-05-29 05:21:06 -04:00
|
|
|
if (typeof projection === 'function' && callback == null) {
|
|
|
|
callback = projection
|
|
|
|
projection = {}
|
|
|
|
}
|
2021-02-17 08:00:48 -05:00
|
|
|
if (projectId == null) {
|
|
|
|
return callback(new Error('no project id provided'))
|
2019-05-29 05:21:06 -04:00
|
|
|
}
|
|
|
|
if (typeof projection !== 'object') {
|
|
|
|
return callback(new Error('projection is not an object'))
|
|
|
|
}
|
|
|
|
|
2020-10-06 06:31:34 -04:00
|
|
|
let query
|
|
|
|
try {
|
2021-02-17 08:00:48 -05:00
|
|
|
query = normalizeQuery(projectId)
|
2020-10-06 06:31:34 -04:00
|
|
|
} catch (err) {
|
2019-05-29 05:21:06 -04:00
|
|
|
return callback(err)
|
|
|
|
}
|
|
|
|
|
2021-04-14 09:17:21 -04:00
|
|
|
db.projects.findOne(query, { projection }, function (err, project) {
|
2021-02-17 08:00:48 -05:00
|
|
|
if (err) {
|
2020-08-11 05:35:08 -04:00
|
|
|
OError.tag(err, 'error getting project', {
|
|
|
|
query,
|
2021-04-27 03:52:58 -04:00
|
|
|
projection,
|
2020-08-11 05:35:08 -04:00
|
|
|
})
|
2019-05-29 05:21:06 -04:00
|
|
|
return callback(err)
|
|
|
|
}
|
2021-02-17 08:00:48 -05:00
|
|
|
callback(null, project)
|
2019-05-29 05:21:06 -04:00
|
|
|
})
|
|
|
|
},
|
|
|
|
|
|
|
|
getProjectIdByReadAndWriteToken(token, callback) {
|
2021-04-14 09:17:21 -04:00
|
|
|
Project.findOne(
|
|
|
|
{ 'tokens.readAndWrite': token },
|
|
|
|
{ _id: 1 },
|
|
|
|
function (err, project) {
|
|
|
|
if (err) {
|
|
|
|
return callback(err)
|
|
|
|
}
|
|
|
|
if (project == null) {
|
|
|
|
return callback()
|
|
|
|
}
|
|
|
|
callback(null, project._id)
|
2019-06-13 04:37:20 -04:00
|
|
|
}
|
2021-04-14 09:17:21 -04:00
|
|
|
)
|
2019-06-13 04:37:20 -04:00
|
|
|
},
|
|
|
|
|
2021-02-17 08:00:48 -05:00
|
|
|
findAllUsersProjects(userId, fields, callback) {
|
2019-10-07 04:30:51 -04:00
|
|
|
const CollaboratorsGetter = require('../Collaborators/CollaboratorsGetter')
|
2021-04-14 09:17:21 -04:00
|
|
|
Project.find(
|
|
|
|
{ owner_ref: userId },
|
|
|
|
fields,
|
|
|
|
function (error, ownedProjects) {
|
2021-02-17 08:00:48 -05:00
|
|
|
if (error) {
|
|
|
|
return callback(error)
|
2019-05-29 05:21:06 -04:00
|
|
|
}
|
2021-04-14 09:17:21 -04:00
|
|
|
CollaboratorsGetter.getProjectsUserIsMemberOf(
|
|
|
|
userId,
|
|
|
|
fields,
|
|
|
|
function (error, projects) {
|
|
|
|
if (error) {
|
|
|
|
return callback(error)
|
|
|
|
}
|
|
|
|
const result = {
|
|
|
|
owned: ownedProjects || [],
|
|
|
|
readAndWrite: projects.readAndWrite || [],
|
|
|
|
readOnly: projects.readOnly || [],
|
|
|
|
tokenReadAndWrite: projects.tokenReadAndWrite || [],
|
2021-04-27 03:52:58 -04:00
|
|
|
tokenReadOnly: projects.tokenReadOnly || [],
|
2021-04-14 09:17:21 -04:00
|
|
|
}
|
2022-11-29 05:11:10 -05:00
|
|
|
|
|
|
|
// Remove duplicate projects. The order of result values is determined by the order they occur.
|
|
|
|
const tempAddedProjectsIds = new Set()
|
|
|
|
const filteredProjects = Object.entries(result).reduce(
|
|
|
|
(prev, current) => {
|
|
|
|
const [key, projects] = current
|
|
|
|
|
|
|
|
prev[key] = []
|
|
|
|
|
|
|
|
projects.forEach(project => {
|
|
|
|
const projectId = project._id.toString()
|
|
|
|
|
|
|
|
if (!tempAddedProjectsIds.has(projectId)) {
|
|
|
|
prev[key].push(project)
|
|
|
|
tempAddedProjectsIds.add(projectId)
|
|
|
|
}
|
|
|
|
})
|
|
|
|
|
|
|
|
return prev
|
|
|
|
},
|
|
|
|
{}
|
|
|
|
)
|
|
|
|
|
|
|
|
callback(null, filteredProjects)
|
2021-04-14 09:17:21 -04:00
|
|
|
}
|
|
|
|
)
|
|
|
|
}
|
|
|
|
)
|
2019-07-18 10:18:56 -04:00
|
|
|
},
|
|
|
|
|
2021-02-17 08:00:48 -05:00
|
|
|
/**
|
|
|
|
* Return all projects with the given name that belong to the given user.
|
|
|
|
*
|
|
|
|
* Projects include the user's own projects as well as collaborations with
|
|
|
|
* read/write access.
|
|
|
|
*/
|
|
|
|
findUsersProjectsByName(userId, projectName, callback) {
|
|
|
|
ProjectGetter.findAllUsersProjects(
|
|
|
|
userId,
|
|
|
|
'name archived trashed',
|
|
|
|
(err, allProjects) => {
|
|
|
|
if (err != null) {
|
|
|
|
return callback(err)
|
|
|
|
}
|
|
|
|
const { owned, readAndWrite } = allProjects
|
|
|
|
const projects = owned.concat(readAndWrite)
|
|
|
|
const lowerCasedProjectName = projectName.toLowerCase()
|
|
|
|
const matches = projects.filter(
|
|
|
|
project => project.name.toLowerCase() === lowerCasedProjectName
|
|
|
|
)
|
|
|
|
callback(null, matches)
|
|
|
|
}
|
|
|
|
)
|
|
|
|
},
|
|
|
|
|
|
|
|
getUsersDeletedProjects(userId, callback) {
|
2019-07-18 10:18:56 -04:00
|
|
|
DeletedProject.find(
|
|
|
|
{
|
2021-04-27 03:52:58 -04:00
|
|
|
'deleterData.deletedProjectOwnerId': userId,
|
2019-07-18 10:18:56 -04:00
|
|
|
},
|
|
|
|
callback
|
|
|
|
)
|
2021-04-27 03:52:58 -04:00
|
|
|
},
|
2019-05-29 05:21:06 -04:00
|
|
|
}
|
2021-02-17 08:00:48 -05:00
|
|
|
|
2019-05-29 05:21:06 -04:00
|
|
|
;['getProject', 'getProjectWithoutDocLines'].map(method =>
|
|
|
|
metrics.timeAsyncMethod(ProjectGetter, method, 'mongo.ProjectGetter', logger)
|
|
|
|
)
|
2019-09-09 07:52:25 -04:00
|
|
|
|
|
|
|
ProjectGetter.promises = promisifyAll(ProjectGetter)
|
|
|
|
module.exports = ProjectGetter
|