| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566 |
- crypto = require 'crypto'
- V1Api = require('../V1/V1Api')
- Async = require('async')
- logger = require('logger-sharelatex')
- # This module mirrors the token generation in Overleaf (`random_token.rb`),
- # for the purposes of implementing token-based project access, like the
- # 'unlisted-projects' feature in Overleaf
- module.exports = 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'
- _randomString: (length, alphabet) ->
- result = crypto.randomBytes(length).toJSON().data.map(
- (b) -> alphabet[b % alphabet.length]
- ).join('')
- return result
- # Generate a 12-char token with only characters from TOKEN_ALPHA,
- # suitable for use as a read-only token for a project
- readOnlyToken: () ->
- return ProjectTokenGenerator._randomString(
- 12,
- ProjectTokenGenerator.TOKEN_ALPHA
- )
- # Generate a longer token, with a numeric prefix,
- # suitable for use as a read-and-write token for a project
- readAndWriteToken: () ->
- numerics = ProjectTokenGenerator._randomString(
- 10,
- ProjectTokenGenerator.TOKEN_NUMERICS
- )
- token = ProjectTokenGenerator._randomString(
- 12,
- ProjectTokenGenerator.TOKEN_ALPHA
- )
- fullToken = "#{numerics}#{token}"
- return fullToken
- generateUniqueReadOnlyToken: (callback=(err, token)->) ->
- Async.retry 10
- , (cb) ->
- token = ProjectTokenGenerator.readOnlyToken()
- logger.log {token}, "Generated read-only token"
- V1Api.request {
- url: "/api/v1/sharelatex/docs/read_token/#{token}/exists",
- json: true
- }, (err, response, body) ->
- return cb(err) if err?
- if response.statusCode != 200
- return cb(new Error("non-200 response from v1 read-token-exists api: #{response.statusCode}"))
- if body.exists == true
- cb(new Error("token already exists in v1: #{token}"))
- else
- logger.log {token}, "Read-only token does not exist in v1, good to use"
- cb(null, token)
- , callback
|