You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

76 lines
1.8 KiB

  1. /* global WIKI */
  2. const Model = require('objection').Model
  3. const { DateTime } = require('luxon')
  4. const { nanoid } = require('nanoid')
  5. /**
  6. * Users model
  7. */
  8. module.exports = class UserKey extends Model {
  9. static get tableName() { return 'userKeys' }
  10. static get jsonSchema () {
  11. return {
  12. type: 'object',
  13. required: ['kind', 'token', 'validUntil'],
  14. properties: {
  15. id: {type: 'integer'},
  16. kind: {type: 'string'},
  17. token: {type: 'string'},
  18. createdAt: {type: 'string'},
  19. validUntil: {type: 'string'}
  20. }
  21. }
  22. }
  23. static get relationMappings() {
  24. return {
  25. user: {
  26. relation: Model.BelongsToOneRelation,
  27. modelClass: require('./users'),
  28. join: {
  29. from: 'userKeys.userId',
  30. to: 'users.id'
  31. }
  32. }
  33. }
  34. }
  35. async $beforeInsert(context) {
  36. await super.$beforeInsert(context)
  37. this.createdAt = DateTime.utc().toISO()
  38. }
  39. static async generateToken ({ userId, kind }, context) {
  40. const token = await nanoid()
  41. await WIKI.models.userKeys.query().insert({
  42. kind,
  43. token,
  44. validUntil: DateTime.utc().plus({ days: 1 }).toISO(),
  45. userId
  46. })
  47. return token
  48. }
  49. static async validateToken ({ kind, token, skipDelete }, context) {
  50. const res = await WIKI.models.userKeys.query().findOne({ kind, token }).withGraphJoined('user')
  51. if (res) {
  52. if (skipDelete !== true) {
  53. await WIKI.models.userKeys.query().deleteById(res.id)
  54. }
  55. if (DateTime.utc() > DateTime.fromISO(res.validUntil)) {
  56. throw new WIKI.Error.AuthValidationTokenInvalid()
  57. }
  58. return res.user
  59. } else {
  60. throw new WIKI.Error.AuthValidationTokenInvalid()
  61. }
  62. }
  63. static async destroyToken ({ token }) {
  64. return WIKI.models.userKeys.query().findOne({ token }).delete()
  65. }
  66. }