oauth-token.ts 4.8 KB

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