mirror of
https://github.com/overleaf/overleaf.git
synced 2024-12-01 15:51:31 -05:00
Merge pull request #6690 from overleaf/ta-max-dictionary-size
Add Dictionary Size Limit GitOrigin-RevId: f3b8be11de5a1480c8bc1a7fe26e9d67bd047757
This commit is contained in:
parent
01f63e810a
commit
1b4d675b0a
3 changed files with 95 additions and 32 deletions
|
@ -3,10 +3,20 @@ const logger = require('@overleaf/logger')
|
||||||
const metrics = require('@overleaf/metrics')
|
const metrics = require('@overleaf/metrics')
|
||||||
const { promisify } = require('util')
|
const { promisify } = require('util')
|
||||||
const OError = require('@overleaf/o-error')
|
const OError = require('@overleaf/o-error')
|
||||||
|
const Settings = require('@overleaf/settings')
|
||||||
|
const { InvalidError } = require('../Errors/Errors')
|
||||||
|
|
||||||
const LearnedWordsManager = {
|
const LearnedWordsManager = {
|
||||||
learnWord(userToken, word, callback) {
|
learnWord(userToken, word, callback) {
|
||||||
return db.spellingPreferences.updateOne(
|
LearnedWordsManager.getLearnedWordsSize(userToken, (error, wordsSize) => {
|
||||||
|
if (error != null) {
|
||||||
|
return callback(OError.tag(error))
|
||||||
|
}
|
||||||
|
const wordSize = Buffer.from(word).length
|
||||||
|
if (wordsSize + wordSize > Settings.maxDictionarySize) {
|
||||||
|
return callback(new InvalidError('Max dictionary size reached'))
|
||||||
|
}
|
||||||
|
db.spellingPreferences.updateOne(
|
||||||
{
|
{
|
||||||
token: userToken,
|
token: userToken,
|
||||||
},
|
},
|
||||||
|
@ -18,6 +28,7 @@ const LearnedWordsManager = {
|
||||||
},
|
},
|
||||||
callback
|
callback
|
||||||
)
|
)
|
||||||
|
})
|
||||||
},
|
},
|
||||||
|
|
||||||
unlearnWord(userToken, word, callback) {
|
unlearnWord(userToken, word, callback) {
|
||||||
|
@ -52,6 +63,20 @@ const LearnedWordsManager = {
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
|
|
||||||
|
getLearnedWordsSize(userToken, callback) {
|
||||||
|
db.spellingPreferences.findOne(
|
||||||
|
{ token: userToken },
|
||||||
|
function (error, preferences) {
|
||||||
|
if (error != null) {
|
||||||
|
return callback(OError.tag(error))
|
||||||
|
}
|
||||||
|
const words = (preferences && preferences.learnedWords) || []
|
||||||
|
const wordsSize = Buffer.from(JSON.stringify(words)).length
|
||||||
|
callback(null, wordsSize)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
},
|
||||||
|
|
||||||
deleteUsersLearnedWords(userToken, callback) {
|
deleteUsersLearnedWords(userToken, callback) {
|
||||||
db.spellingPreferences.deleteOne({ token: userToken }, callback)
|
db.spellingPreferences.deleteOne({ token: userToken }, callback)
|
||||||
},
|
},
|
||||||
|
|
|
@ -423,6 +423,8 @@ module.exports = {
|
||||||
'zh-CN': '简体中文',
|
'zh-CN': '简体中文',
|
||||||
},
|
},
|
||||||
|
|
||||||
|
maxDictionarySize: 1024 * 1024, // 1 MB
|
||||||
|
|
||||||
// Password Settings
|
// Password Settings
|
||||||
// -----------
|
// -----------
|
||||||
// These restrict the passwords users can use when registering
|
// These restrict the passwords users can use when registering
|
||||||
|
|
|
@ -5,6 +5,7 @@ const modulePath = require('path').join(
|
||||||
__dirname,
|
__dirname,
|
||||||
'/../../../../app/src/Features/Spelling/LearnedWordsManager'
|
'/../../../../app/src/Features/Spelling/LearnedWordsManager'
|
||||||
)
|
)
|
||||||
|
const { InvalidError } = require('../../../../app/src/Features/Errors/Errors')
|
||||||
|
|
||||||
describe('LearnedWordsManager', function () {
|
describe('LearnedWordsManager', function () {
|
||||||
beforeEach(function () {
|
beforeEach(function () {
|
||||||
|
@ -13,6 +14,7 @@ describe('LearnedWordsManager', function () {
|
||||||
this.db = {
|
this.db = {
|
||||||
spellingPreferences: {
|
spellingPreferences: {
|
||||||
updateOne: sinon.stub().yields(),
|
updateOne: sinon.stub().yields(),
|
||||||
|
findOne: sinon.stub().yields(null, ['pear']),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
this.LearnedWordsManager = SandboxedModule.require(modulePath, {
|
this.LearnedWordsManager = SandboxedModule.require(modulePath, {
|
||||||
|
@ -22,11 +24,15 @@ describe('LearnedWordsManager', function () {
|
||||||
timeAsyncMethod: sinon.stub(),
|
timeAsyncMethod: sinon.stub(),
|
||||||
inc: sinon.stub(),
|
inc: sinon.stub(),
|
||||||
},
|
},
|
||||||
|
'@overleaf/settings': {
|
||||||
|
maxDictionarySize: 20,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('learnWord', function () {
|
describe('learnWord', function () {
|
||||||
|
describe('under size limit', function () {
|
||||||
beforeEach(function () {
|
beforeEach(function () {
|
||||||
this.word = 'instanton'
|
this.word = 'instanton'
|
||||||
this.LearnedWordsManager.learnWord(this.token, this.word, this.callback)
|
this.LearnedWordsManager.learnWord(this.token, this.word, this.callback)
|
||||||
|
@ -48,8 +54,26 @@ describe('LearnedWordsManager', function () {
|
||||||
).to.equal(true)
|
).to.equal(true)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should call the callback', function () {
|
it('should call the callback without error', function () {
|
||||||
expect(this.callback.called).to.equal(true)
|
sinon.assert.called(this.callback)
|
||||||
|
expect(this.callback.lastCall.args.length).to.equal(0)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('over size limit', function () {
|
||||||
|
beforeEach(function () {
|
||||||
|
this.word = 'superlongwordthatwillgobeyondthelimit'
|
||||||
|
this.LearnedWordsManager.learnWord(this.token, this.word, this.callback)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should not insert the word in the word list in the database', function () {
|
||||||
|
expect(this.db.spellingPreferences.updateOne.notCalled).to.equal(true)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should call the callback with error', function () {
|
||||||
|
sinon.assert.called(this.callback)
|
||||||
|
expect(this.callback.lastCall.args[0]).to.be.instanceof(InvalidError)
|
||||||
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -100,6 +124,18 @@ describe('LearnedWordsManager', function () {
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
describe('getLearnedWordsSize', function () {
|
||||||
|
it('should return the word list size in the callback', function () {
|
||||||
|
this.db.spellingPreferences.findOne = (conditions, callback) => {
|
||||||
|
callback(null, {
|
||||||
|
learnedWords: ['apples', 'bananas', 'pears', 'bananas'],
|
||||||
|
})
|
||||||
|
}
|
||||||
|
this.LearnedWordsManager.getLearnedWordsSize(this.token, this.callback)
|
||||||
|
sinon.assert.calledWith(this.callback, null, 38)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
describe('deleteUsersLearnedWords', function () {
|
describe('deleteUsersLearnedWords', function () {
|
||||||
beforeEach(function () {
|
beforeEach(function () {
|
||||||
this.db.spellingPreferences.deleteOne = sinon.stub().callsArgWith(1)
|
this.db.spellingPreferences.deleteOne = sinon.stub().callsArgWith(1)
|
||||||
|
|
Loading…
Reference in a new issue