e73c4be7d54a8496e09350448bb665cad639f306
[oweals/peertube.git] / server / models / oauth / oauth-token.ts
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 import * as Bluebird from 'bluebird'
22 import { MOAuthTokenUser } from '@server/typings/models/oauth/oauth-token'
23
24 export type OAuthTokenInfo = {
25   refreshToken: string
26   refreshTokenExpiresAt: Date
27   client: {
28     id: number
29   }
30   user: {
31     id: number
32   }
33 }
34
35 enum ScopeNames {
36   WITH_USER = 'WITH_USER'
37 }
38
39 @Scopes(() => ({
40   [ScopeNames.WITH_USER]: {
41     include: [
42       {
43         model: UserModel.unscoped(),
44         required: true,
45         include: [
46           {
47             attributes: [ 'id' ],
48             model: AccountModel.unscoped(),
49             required: true,
50             include: [
51               {
52                 attributes: [ 'id', 'url' ],
53                 model: ActorModel.unscoped(),
54                 required: true
55               }
56             ]
57           }
58         ]
59       }
60     ]
61   }
62 }))
63 @Table({
64   tableName: 'oAuthToken',
65   indexes: [
66     {
67       fields: [ 'refreshToken' ],
68       unique: true
69     },
70     {
71       fields: [ 'accessToken' ],
72       unique: true
73     },
74     {
75       fields: [ 'userId' ]
76     },
77     {
78       fields: [ 'oAuthClientId' ]
79     }
80   ]
81 })
82 export class OAuthTokenModel extends Model<OAuthTokenModel> {
83
84   @AllowNull(false)
85   @Column
86   accessToken: string
87
88   @AllowNull(false)
89   @Column
90   accessTokenExpiresAt: Date
91
92   @AllowNull(false)
93   @Column
94   refreshToken: string
95
96   @AllowNull(false)
97   @Column
98   refreshTokenExpiresAt: Date
99
100   @Column
101   authName: string
102
103   @CreatedAt
104   createdAt: Date
105
106   @UpdatedAt
107   updatedAt: Date
108
109   @ForeignKey(() => UserModel)
110   @Column
111   userId: number
112
113   @BelongsTo(() => UserModel, {
114     foreignKey: {
115       allowNull: false
116     },
117     onDelete: 'cascade'
118   })
119   User: UserModel
120
121   @ForeignKey(() => OAuthClientModel)
122   @Column
123   oAuthClientId: number
124
125   @BelongsTo(() => OAuthClientModel, {
126     foreignKey: {
127       allowNull: false
128     },
129     onDelete: 'cascade'
130   })
131   OAuthClients: OAuthClientModel[]
132
133   @AfterUpdate
134   @AfterDestroy
135   static removeTokenCache (token: OAuthTokenModel) {
136     return clearCacheByToken(token.accessToken)
137   }
138
139   static getByRefreshTokenAndPopulateClient (refreshToken: string) {
140     const query = {
141       where: {
142         refreshToken: refreshToken
143       },
144       include: [ OAuthClientModel ]
145     }
146
147     return OAuthTokenModel.findOne(query)
148       .then(token => {
149         if (!token) return null
150
151         return {
152           refreshToken: token.refreshToken,
153           refreshTokenExpiresAt: token.refreshTokenExpiresAt,
154           client: {
155             id: token.oAuthClientId
156           },
157           user: {
158             id: token.userId
159           }
160         } as OAuthTokenInfo
161       })
162       .catch(err => {
163         logger.error('getRefreshToken error.', { err })
164         throw err
165       })
166   }
167
168   static getByTokenAndPopulateUser (bearerToken: string): Bluebird<MOAuthTokenUser> {
169     const query = {
170       where: {
171         accessToken: bearerToken
172       }
173     }
174
175     return OAuthTokenModel.scope(ScopeNames.WITH_USER)
176                           .findOne(query)
177                           .then(token => {
178                             if (!token) return null
179
180                             return Object.assign(token, { user: token.User })
181                           })
182   }
183
184   static getByRefreshTokenAndPopulateUser (refreshToken: string): Bluebird<MOAuthTokenUser> {
185     const query = {
186       where: {
187         refreshToken: refreshToken
188       }
189     }
190
191     return OAuthTokenModel.scope(ScopeNames.WITH_USER)
192       .findOne(query)
193       .then(token => {
194         if (!token) return new OAuthTokenModel()
195
196         return Object.assign(token, { user: token.User })
197       })
198   }
199
200   static deleteUserToken (userId: number, t?: Transaction) {
201     const query = {
202       where: {
203         userId
204       },
205       transaction: t
206     }
207
208     return OAuthTokenModel.destroy(query)
209   }
210 }