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