import_oauth_access_tokens.js 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  1. /* eslint-disable max-len */
  2. /**
  3. * run with: node import_oauth_access_tokens /path/import_oauth_access_tokens.csv
  4. *
  5. * where csv is generated from v1 with sql statement like:
  6. *
  7. * \copy ( SELECT oat.token, oat.refresh_token, oat.scopes, oat.resource_owner_id AS user_id, u.email, u.confirmed_at, oa.uid AS client_id, oat.created_at + oat.expires_in * interval '1 second' AS expires_at FROM oauth_access_tokens oat LEFT JOIN oauth_access_tokens oat2 ON oat2.previous_refresh_token = oat.refresh_token JOIN oauth_applications oa ON oat.application_id = oa.id JOIN users u ON u.id = oat.resource_owner_id WHERE (oat2.id IS NULL OR oat2.created_at > NOW() - interval '24 hour') AND oat.revoked_at IS NULL AND (oat.application_id = 1 OR (oat.application_id = 2 AND oat.created_at + oat.expires_in * interval '1 second' > NOW())) ) to 'oauth_access_tokens.csv' WITH CSV HEADER;
  8. *
  9. * this query exports the most recent collabractec (1) and gitbridge (2) tokens for
  10. * each user. expired tokens are exported for collabratec but not for gitbridge.
  11. *
  12. * tokens that have been refreshed are not exported if it has been over 24 hours
  13. * since the new token was issued.
  14. */
  15. /* eslint-enable */
  16. 'use strict'
  17. const OauthApplication = require('../../app/src/models/OauthApplication')
  18. .OauthApplication
  19. const OauthAccessToken = require('../../app/src/models/OauthAccessToken')
  20. .OauthAccessToken
  21. const User = require('../../app/src/models/User').User
  22. const UserMapper = require('../../modules/overleaf-integration/app/src/OverleafUsers/UserMapper')
  23. const async = require('async')
  24. const csvParser = require('csv-parser')
  25. const fs = require('fs')
  26. const minimist = require('minimist')
  27. const argv = minimist(process.argv.slice(2))
  28. let lineNum = 0
  29. const records = []
  30. fs.createReadStream(argv._[0])
  31. .pipe(csvParser())
  32. .on('data', data => {
  33. data.lineNum = ++lineNum
  34. records.push(data)
  35. })
  36. .on('end', () => {
  37. async.mapSeries(records, loadRecord, function(err) {
  38. if (err) console.error(err)
  39. process.exit()
  40. })
  41. })
  42. function loadRecord(record, cb) {
  43. getOauthApplication(record.client_id, function(err, oauthApplication) {
  44. if (err) return cb(err)
  45. const overleafId = parseInt(record.user_id)
  46. User.findOne({ 'overleaf.id': overleafId }, { _id: 1 }, function(
  47. err,
  48. user
  49. ) {
  50. if (err) return cb(err)
  51. if (user) {
  52. console.log(
  53. record.lineNum + ': Creating OauthAccessToken for User ' + user._id
  54. )
  55. createOauthAccessToken(user._id, oauthApplication._id, record, cb)
  56. } else {
  57. // create user stub
  58. const olUser = {
  59. confirmed_at: record.confirmed_at,
  60. email: record.email,
  61. id: overleafId
  62. }
  63. console.log(record.lineNum + ': User not found for ' + record.user_id)
  64. return UserMapper.getSlIdFromOlUser(olUser, function(err, userStubId) {
  65. if (err) return cb(err)
  66. console.log(
  67. record.lineNum +
  68. ': Creating OauthAccessToken for UserStub ' +
  69. userStubId
  70. )
  71. createOauthAccessToken(userStubId, oauthApplication._id, record, cb)
  72. })
  73. }
  74. })
  75. })
  76. }
  77. function createOauthAccessToken(userId, oauthApplicationId, record, cb) {
  78. const newRecord = {
  79. accessToken: record.token,
  80. accessTokenExpiresAt: record.expires_at,
  81. oauthApplication_id: oauthApplicationId,
  82. refreshToken: record.refresh_token,
  83. scope: record.scopes,
  84. user_id: userId
  85. }
  86. OauthAccessToken.update(newRecord, newRecord, { upsert: true }, cb)
  87. }
  88. const oauthApplications = {}
  89. function getOauthApplication(clientId, cb) {
  90. if (oauthApplications[clientId]) return cb(null, oauthApplications[clientId])
  91. OauthApplication.findOne({ id: clientId }, { _id: 1 }, function(
  92. err,
  93. oauthApplication
  94. ) {
  95. if (err) return cb(err)
  96. if (!oauthApplication) return cb(new Error('oauthApplication not found'))
  97. oauthApplications[clientId] = oauthApplication
  98. cb(null, oauthApplication)
  99. })
  100. }