|
@@ -16,19 +16,21 @@ const Features = require('../../infrastructure/Features')
|
|
|
const Async = require('async')
|
|
const Async = require('async')
|
|
|
const { promisify } = require('util')
|
|
const { promisify } = require('util')
|
|
|
|
|
|
|
|
|
|
+// (From Overleaf `random_token.rb`)
|
|
|
|
|
+// Letters (not numbers! see generate_token) used in tokens. They're all
|
|
|
|
|
+// consonants, to avoid embarassing words (I can't think of any that use only
|
|
|
|
|
+// a y), and lower case "l" is omitted, because in many fonts it is
|
|
|
|
|
+// indistinguishable from an upper case "I" (and sometimes even the number 1).
|
|
|
|
|
+const TOKEN_LOWERCASE_ALPHA = 'bcdfghjkmnpqrstvwxyz'
|
|
|
|
|
+const TOKEN_NUMERICS = '123456789'
|
|
|
|
|
+const TOKEN_ALPHANUMERICS =
|
|
|
|
|
+ TOKEN_LOWERCASE_ALPHA + TOKEN_LOWERCASE_ALPHA.toUpperCase() + TOKEN_NUMERICS
|
|
|
|
|
+
|
|
|
// This module mirrors the token generation in Overleaf (`random_token.rb`),
|
|
// This module mirrors the token generation in Overleaf (`random_token.rb`),
|
|
|
// for the purposes of implementing token-based project access, like the
|
|
// for the purposes of implementing token-based project access, like the
|
|
|
// 'unlisted-projects' feature in Overleaf
|
|
// 'unlisted-projects' feature in Overleaf
|
|
|
|
|
|
|
|
-const ProjectTokenGenerator = {
|
|
|
|
|
- // (From Overleaf `random_token.rb`)
|
|
|
|
|
- // Letters (not numbers! see generate_token) used in tokens. They're all
|
|
|
|
|
- // consonants, to avoid embarassing words (I can't think of any that use only
|
|
|
|
|
- // a y), and lower case "l" is omitted, because in many fonts it is
|
|
|
|
|
- // indistinguishable from an upper case "I" (and sometimes even the number 1).
|
|
|
|
|
- TOKEN_ALPHA: 'bcdfghjkmnpqrstvwxyz',
|
|
|
|
|
- TOKEN_NUMERICS: '123456789',
|
|
|
|
|
-
|
|
|
|
|
|
|
+const TokenGenerator = {
|
|
|
_randomString(length, alphabet) {
|
|
_randomString(length, alphabet) {
|
|
|
const result = crypto
|
|
const result = crypto
|
|
|
.randomBytes(length)
|
|
.randomBytes(length)
|
|
@@ -38,30 +40,25 @@ const ProjectTokenGenerator = {
|
|
|
return result
|
|
return result
|
|
|
},
|
|
},
|
|
|
|
|
|
|
|
- // Generate a 12-char token with only characters from TOKEN_ALPHA,
|
|
|
|
|
|
|
+ // Generate a 12-char token with only characters from TOKEN_LOWERCASE_ALPHA,
|
|
|
// suitable for use as a read-only token for a project
|
|
// suitable for use as a read-only token for a project
|
|
|
readOnlyToken() {
|
|
readOnlyToken() {
|
|
|
- return ProjectTokenGenerator._randomString(
|
|
|
|
|
- 12,
|
|
|
|
|
- ProjectTokenGenerator.TOKEN_ALPHA
|
|
|
|
|
- )
|
|
|
|
|
|
|
+ return TokenGenerator._randomString(12, TOKEN_LOWERCASE_ALPHA)
|
|
|
},
|
|
},
|
|
|
|
|
|
|
|
// Generate a longer token, with a numeric prefix,
|
|
// Generate a longer token, with a numeric prefix,
|
|
|
// suitable for use as a read-and-write token for a project
|
|
// suitable for use as a read-and-write token for a project
|
|
|
readAndWriteToken() {
|
|
readAndWriteToken() {
|
|
|
- const numerics = ProjectTokenGenerator._randomString(
|
|
|
|
|
- 10,
|
|
|
|
|
- ProjectTokenGenerator.TOKEN_NUMERICS
|
|
|
|
|
- )
|
|
|
|
|
- const token = ProjectTokenGenerator._randomString(
|
|
|
|
|
- 12,
|
|
|
|
|
- ProjectTokenGenerator.TOKEN_ALPHA
|
|
|
|
|
- )
|
|
|
|
|
|
|
+ const numerics = TokenGenerator._randomString(10, TOKEN_NUMERICS)
|
|
|
|
|
+ const token = TokenGenerator._randomString(12, TOKEN_LOWERCASE_ALPHA)
|
|
|
const fullToken = `${numerics}${token}`
|
|
const fullToken = `${numerics}${token}`
|
|
|
return { token: fullToken, numericPrefix: numerics }
|
|
return { token: fullToken, numericPrefix: numerics }
|
|
|
},
|
|
},
|
|
|
|
|
|
|
|
|
|
+ generateReferralId() {
|
|
|
|
|
+ return TokenGenerator._randomString(16, TOKEN_ALPHANUMERICS)
|
|
|
|
|
+ },
|
|
|
|
|
+
|
|
|
generateUniqueReadOnlyToken(callback) {
|
|
generateUniqueReadOnlyToken(callback) {
|
|
|
if (callback == null) {
|
|
if (callback == null) {
|
|
|
callback = function(err, token) {}
|
|
callback = function(err, token) {}
|
|
@@ -69,7 +66,7 @@ const ProjectTokenGenerator = {
|
|
|
return Async.retry(
|
|
return Async.retry(
|
|
|
10,
|
|
10,
|
|
|
function(cb) {
|
|
function(cb) {
|
|
|
- const token = ProjectTokenGenerator.readOnlyToken()
|
|
|
|
|
|
|
+ const token = TokenGenerator.readOnlyToken()
|
|
|
|
|
|
|
|
if (!Features.hasFeature('overleaf-integration')) {
|
|
if (!Features.hasFeature('overleaf-integration')) {
|
|
|
return cb(null, token)
|
|
return cb(null, token)
|
|
@@ -104,9 +101,9 @@ const ProjectTokenGenerator = {
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-ProjectTokenGenerator.promises = {
|
|
|
|
|
|
|
+TokenGenerator.promises = {
|
|
|
generateUniqueReadOnlyToken: promisify(
|
|
generateUniqueReadOnlyToken: promisify(
|
|
|
- ProjectTokenGenerator.generateUniqueReadOnlyToken
|
|
|
|
|
|
|
+ TokenGenerator.generateUniqueReadOnlyToken
|
|
|
)
|
|
)
|
|
|
}
|
|
}
|
|
|
-module.exports = ProjectTokenGenerator
|
|
|
|
|
|
|
+module.exports = TokenGenerator
|