oauth-token.ts 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206
  1. import {
  2. AfterDestroy,
  3. AfterUpdate,
  4. AllowNull,
  5. BelongsTo,
  6. Column,
  7. CreatedAt,
  8. ForeignKey,
  9. Model,
  10. Scopes,
  11. Table,
  12. UpdatedAt
  13. } from 'sequelize-typescript'
  14. import { logger } from '../../helpers/logger'
  15. import { UserModel } from '../account/user'
  16. import { OAuthClientModel } from './oauth-client'
  17. import { Transaction } from 'sequelize'
  18. import { AccountModel } from '../account/account'
  19. import { ActorModel } from '../activitypub/actor'
  20. import { clearCacheByToken } from '../../lib/oauth-model'
  21. export type OAuthTokenInfo = {
  22. refreshToken: string
  23. refreshTokenExpiresAt: Date,
  24. client: {
  25. id: number
  26. },
  27. user: {
  28. id: number
  29. }
  30. }
  31. enum ScopeNames {
  32. WITH_USER = 'WITH_USER'
  33. }
  34. @Scopes({
  35. [ScopeNames.WITH_USER]: {
  36. include: [
  37. {
  38. model: () => UserModel.unscoped(),
  39. required: true,
  40. include: [
  41. {
  42. attributes: [ 'id' ],
  43. model: () => AccountModel.unscoped(),
  44. required: true,
  45. include: [
  46. {
  47. attributes: [ 'id', 'url' ],
  48. model: () => ActorModel.unscoped(),
  49. required: true
  50. }
  51. ]
  52. }
  53. ]
  54. }
  55. ]
  56. }
  57. })
  58. @Table({
  59. tableName: 'oAuthToken',
  60. indexes: [
  61. {
  62. fields: [ 'refreshToken' ],
  63. unique: true
  64. },
  65. {
  66. fields: [ 'accessToken' ],
  67. unique: true
  68. },
  69. {
  70. fields: [ 'userId' ]
  71. },
  72. {
  73. fields: [ 'oAuthClientId' ]
  74. }
  75. ]
  76. })
  77. export class OAuthTokenModel extends Model<OAuthTokenModel> {
  78. @AllowNull(false)
  79. @Column
  80. accessToken: string
  81. @AllowNull(false)
  82. @Column
  83. accessTokenExpiresAt: Date
  84. @AllowNull(false)
  85. @Column
  86. refreshToken: string
  87. @AllowNull(false)
  88. @Column
  89. refreshTokenExpiresAt: Date
  90. @CreatedAt
  91. createdAt: Date
  92. @UpdatedAt
  93. updatedAt: Date
  94. @ForeignKey(() => UserModel)
  95. @Column
  96. userId: number
  97. @BelongsTo(() => UserModel, {
  98. foreignKey: {
  99. allowNull: false
  100. },
  101. onDelete: 'cascade'
  102. })
  103. User: UserModel
  104. @ForeignKey(() => OAuthClientModel)
  105. @Column
  106. oAuthClientId: number
  107. @BelongsTo(() => OAuthClientModel, {
  108. foreignKey: {
  109. allowNull: false
  110. },
  111. onDelete: 'cascade'
  112. })
  113. OAuthClients: OAuthClientModel[]
  114. @AfterUpdate
  115. @AfterDestroy
  116. static removeTokenCache (token: OAuthTokenModel) {
  117. return clearCacheByToken(token.accessToken)
  118. }
  119. static getByRefreshTokenAndPopulateClient (refreshToken: string) {
  120. const query = {
  121. where: {
  122. refreshToken: refreshToken
  123. },
  124. include: [ OAuthClientModel ]
  125. }
  126. return OAuthTokenModel.findOne(query)
  127. .then(token => {
  128. if (!token) return null
  129. return {
  130. refreshToken: token.refreshToken,
  131. refreshTokenExpiresAt: token.refreshTokenExpiresAt,
  132. client: {
  133. id: token.oAuthClientId
  134. },
  135. user: {
  136. id: token.userId
  137. }
  138. } as OAuthTokenInfo
  139. })
  140. .catch(err => {
  141. logger.error('getRefreshToken error.', { err })
  142. throw err
  143. })
  144. }
  145. static getByTokenAndPopulateUser (bearerToken: string) {
  146. const query = {
  147. where: {
  148. accessToken: bearerToken
  149. }
  150. }
  151. return OAuthTokenModel.scope(ScopeNames.WITH_USER).findOne(query).then(token => {
  152. if (token) token['user'] = token.User
  153. return token
  154. })
  155. }
  156. static getByRefreshTokenAndPopulateUser (refreshToken: string) {
  157. const query = {
  158. where: {
  159. refreshToken: refreshToken
  160. }
  161. }
  162. return OAuthTokenModel.scope(ScopeNames.WITH_USER)
  163. .findOne(query)
  164. .then(token => {
  165. if (token) {
  166. token['user'] = token.User
  167. return token
  168. } else {
  169. return new OAuthTokenModel()
  170. }
  171. })
  172. }
  173. static deleteUserToken (userId: number, t?: Transaction) {
  174. const query = {
  175. where: {
  176. userId
  177. },
  178. transaction: t
  179. }
  180. return OAuthTokenModel.destroy(query)
  181. }
  182. }