add support for creating unique project names

This commit is contained in:
Brian Gough 2018-09-14 11:08:03 +01:00
parent 45bd46bc01
commit 6b80d3563d
2 changed files with 72 additions and 0 deletions

View file

@ -67,6 +67,36 @@ module.exports = ProjectDetailsHandler =
else
return callback()
_addSuffixToProjectName: (name, suffix = '') ->
# append the suffix and truncate the project title if needed
truncatedLength = ProjectDetailsHandler.MAX_PROJECT_NAME_LENGTH - suffix.length
return name.substr(0, truncatedLength) + suffix
# FIXME: we should put a lock around this to make it completely safe, but we would need to do that at
# the point of project creation, rather than just checking the name at the start of the import.
# If we later move this check into ProjectCreationHandler we can ensure all new projects are created
# with a unique name. But that requires thinking through how we would handle incoming projects from
# dropbox for example.
ensureProjectNameIsUnique: (user_id, name, suffixes = [], callback = (error, name, changed)->) ->
ProjectGetter.findAllUsersProjects user_id, {name: 1}, (error, allUsersProjects) ->
return callback(error) if error?
{owned, readAndWrite, readOnly, tokenReadAndWrite, tokenReadOnly} = allUsersProjects
# create a set of all project names
allProjectNames = new Set()
for projectName in owned.concat(readAndWrite, readOnly, tokenReadAndWrite, tokenReadOnly)
allProjectNames.add(projectName)
isUnique = (x) -> !allProjectNames.has(x)
# check if the supplied name is already unique
if isUnique(name)
return callback(null, name, false)
# the name already exists, try adding the user-supplied suffixes to generate a unique name
for suffix in suffixes
candidateName = ProjectDetailsHandler._addSuffixToProjectName(name, suffix)
if isUnique(candidateName)
return callback(null, candidateName, true)
# we couldn't make the name unique, something is wrong
return callback new Errors.InvalidNameError("Project name could not be made unique")
setPublicAccessLevel : (project_id, newAccessLevel, callback = ->)->
logger.log project_id: project_id, level: newAccessLevel, "set public access level"
# DEPRECATED: `READ_ONLY` and `READ_AND_WRITE` are still valid in, but should no longer

View file

@ -155,6 +155,48 @@ describe 'ProjectDetailsHandler', ->
expect(error).to.not.exist
done()
describe "ensureProjectNameIsUnique", ->
beforeEach ->
@result = {
owned: ["name", "name1", "name11"]
readAndWrite: ["name2", "name22"]
readOnly: ["name3", "name33"]
tokenReadAndWrite: ["name4", "name44"]
tokenReadOnly: ["name5", "name55", "x".repeat(15)]
}
@ProjectGetter.findAllUsersProjects = sinon.stub().callsArgWith(2, null, @result)
it "should leave a unique name unchanged", (done) ->
@handler.ensureProjectNameIsUnique @user_id, "unique-name", ["-test-suffix"], (error, name, changed) ->
expect(name).to.equal "unique-name"
expect(changed).to.equal false
done()
it "should append a suffix to an existing name", (done) ->
@handler.ensureProjectNameIsUnique @user_id, "name1", ["-test-suffix"], (error, name, changed) ->
expect(name).to.equal "name1-test-suffix"
expect(changed).to.equal true
done()
it "should fallback to a second suffix when needed", (done) ->
@handler.ensureProjectNameIsUnique @user_id, "name1", ["1", "-test-suffix"], (error, name, changed) ->
expect(name).to.equal "name1-test-suffix"
expect(changed).to.equal true
done()
it "should truncate the name when append a suffix if the result is too long", (done) ->
@handler.MAX_PROJECT_NAME_LENGTH = 20
@handler.ensureProjectNameIsUnique @user_id, "x".repeat(15), ["-test-suffix"], (error, name, changed) ->
expect(name).to.equal "x".repeat(8) + "-test-suffix"
expect(changed).to.equal true
done()
it "should return an error if the name cannot be made unique", (done) ->
@handler.ensureProjectNameIsUnique @user_id, "name", ["1", "5", "55"], (error, name, changed) ->
expect(error).to.eql new Errors.InvalidNameError("Project name could not be made unique")
done()
describe "setPublicAccessLevel", ->
beforeEach ->
@ProjectModel.update.callsArgWith(2)