diff options
Diffstat (limited to 'server/models/oauth')
-rw-r--r-- | server/models/oauth/index.ts | 2 | ||||
-rw-r--r-- | server/models/oauth/oauth-client-interface.ts | 32 | ||||
-rw-r--r-- | server/models/oauth/oauth-client.ts | 87 | ||||
-rw-r--r-- | server/models/oauth/oauth-token-interface.ts | 48 | ||||
-rw-r--r-- | server/models/oauth/oauth-token.ts | 160 |
5 files changed, 329 insertions, 0 deletions
diff --git a/server/models/oauth/index.ts b/server/models/oauth/index.ts new file mode 100644 index 000000000..a20d3a56a --- /dev/null +++ b/server/models/oauth/index.ts | |||
@@ -0,0 +1,2 @@ | |||
1 | export * from './oauth-client-interface' | ||
2 | export * from './oauth-token-interface' | ||
diff --git a/server/models/oauth/oauth-client-interface.ts b/server/models/oauth/oauth-client-interface.ts new file mode 100644 index 000000000..3b4325740 --- /dev/null +++ b/server/models/oauth/oauth-client-interface.ts | |||
@@ -0,0 +1,32 @@ | |||
1 | import * as Sequelize from 'sequelize' | ||
2 | |||
3 | export namespace OAuthClientMethods { | ||
4 | export type CountTotalCallback = (err: Error, total: number) => void | ||
5 | export type CountTotal = (callback: CountTotalCallback) => void | ||
6 | |||
7 | export type LoadFirstClientCallback = (err: Error, client: OAuthClientInstance) => void | ||
8 | export type LoadFirstClient = (callback: LoadFirstClientCallback) => void | ||
9 | |||
10 | export type GetByIdAndSecret = (clientId, clientSecret) => void | ||
11 | } | ||
12 | |||
13 | export interface OAuthClientClass { | ||
14 | countTotal: OAuthClientMethods.CountTotal | ||
15 | loadFirstClient: OAuthClientMethods.LoadFirstClient | ||
16 | getByIdAndSecret: OAuthClientMethods.GetByIdAndSecret | ||
17 | } | ||
18 | |||
19 | export interface OAuthClientAttributes { | ||
20 | clientId: string | ||
21 | clientSecret: string | ||
22 | grants: string[] | ||
23 | redirectUris: string[] | ||
24 | } | ||
25 | |||
26 | export interface OAuthClientInstance extends OAuthClientClass, OAuthClientAttributes, Sequelize.Instance<OAuthClientAttributes> { | ||
27 | id: number | ||
28 | createdAt: Date | ||
29 | updatedAt: Date | ||
30 | } | ||
31 | |||
32 | export interface OAuthClientModel extends OAuthClientClass, Sequelize.Model<OAuthClientInstance, OAuthClientAttributes> {} | ||
diff --git a/server/models/oauth/oauth-client.ts b/server/models/oauth/oauth-client.ts new file mode 100644 index 000000000..fbc2a3393 --- /dev/null +++ b/server/models/oauth/oauth-client.ts | |||
@@ -0,0 +1,87 @@ | |||
1 | import * as Sequelize from 'sequelize' | ||
2 | |||
3 | import { addMethodsToModel } from '../utils' | ||
4 | import { | ||
5 | OAuthClientClass, | ||
6 | OAuthClientInstance, | ||
7 | OAuthClientAttributes, | ||
8 | |||
9 | OAuthClientMethods | ||
10 | } from './oauth-client-interface' | ||
11 | |||
12 | let OAuthClient: Sequelize.Model<OAuthClientInstance, OAuthClientAttributes> | ||
13 | let countTotal: OAuthClientMethods.CountTotal | ||
14 | let loadFirstClient: OAuthClientMethods.LoadFirstClient | ||
15 | let getByIdAndSecret: OAuthClientMethods.GetByIdAndSecret | ||
16 | |||
17 | export default function (sequelize: Sequelize.Sequelize, DataTypes: Sequelize.DataTypes) { | ||
18 | OAuthClient = sequelize.define<OAuthClientInstance, OAuthClientAttributes>('OAuthClient', | ||
19 | { | ||
20 | clientId: { | ||
21 | type: DataTypes.STRING, | ||
22 | allowNull: false | ||
23 | }, | ||
24 | clientSecret: { | ||
25 | type: DataTypes.STRING, | ||
26 | allowNull: false | ||
27 | }, | ||
28 | grants: { | ||
29 | type: DataTypes.ARRAY(DataTypes.STRING) | ||
30 | }, | ||
31 | redirectUris: { | ||
32 | type: DataTypes.ARRAY(DataTypes.STRING) | ||
33 | } | ||
34 | }, | ||
35 | { | ||
36 | indexes: [ | ||
37 | { | ||
38 | fields: [ 'clientId' ], | ||
39 | unique: true | ||
40 | }, | ||
41 | { | ||
42 | fields: [ 'clientId', 'clientSecret' ], | ||
43 | unique: true | ||
44 | } | ||
45 | ] | ||
46 | } | ||
47 | ) | ||
48 | |||
49 | const classMethods = [ | ||
50 | associate, | ||
51 | |||
52 | countTotal, | ||
53 | getByIdAndSecret, | ||
54 | loadFirstClient | ||
55 | ] | ||
56 | addMethodsToModel(OAuthClient, classMethods) | ||
57 | |||
58 | return OAuthClient | ||
59 | } | ||
60 | |||
61 | // --------------------------------------------------------------------------- | ||
62 | |||
63 | function associate (models) { | ||
64 | OAuthClient.hasMany(models.OAuthToken, { | ||
65 | foreignKey: 'oAuthClientId', | ||
66 | onDelete: 'cascade' | ||
67 | }) | ||
68 | } | ||
69 | |||
70 | countTotal = function (callback: OAuthClientMethods.CountTotalCallback) { | ||
71 | return OAuthClient.count().asCallback(callback) | ||
72 | } | ||
73 | |||
74 | loadFirstClient = function (callback: OAuthClientMethods.LoadFirstClientCallback) { | ||
75 | return OAuthClient.findOne().asCallback(callback) | ||
76 | } | ||
77 | |||
78 | getByIdAndSecret = function (clientId: string, clientSecret: string) { | ||
79 | const query = { | ||
80 | where: { | ||
81 | clientId: clientId, | ||
82 | clientSecret: clientSecret | ||
83 | } | ||
84 | } | ||
85 | |||
86 | return OAuthClient.findOne(query) | ||
87 | } | ||
diff --git a/server/models/oauth/oauth-token-interface.ts b/server/models/oauth/oauth-token-interface.ts new file mode 100644 index 000000000..815ad5eef --- /dev/null +++ b/server/models/oauth/oauth-token-interface.ts | |||
@@ -0,0 +1,48 @@ | |||
1 | import * as Sequelize from 'sequelize' | ||
2 | import * as Bluebird from 'bluebird' | ||
3 | |||
4 | import { UserModel } from '../user' | ||
5 | |||
6 | export type OAuthTokenInfo = { | ||
7 | refreshToken: string | ||
8 | refreshTokenExpiresAt: Date, | ||
9 | client: { | ||
10 | id: number | ||
11 | }, | ||
12 | user: { | ||
13 | id: number | ||
14 | } | ||
15 | } | ||
16 | |||
17 | export namespace OAuthTokenMethods { | ||
18 | export type GetByRefreshTokenAndPopulateClient = (refreshToken: string) => Bluebird<OAuthTokenInfo> | ||
19 | export type GetByTokenAndPopulateUser = (bearerToken: string) => Bluebird<OAuthTokenInstance> | ||
20 | export type GetByRefreshTokenAndPopulateUser = (refreshToken: string) => Bluebird<OAuthTokenInstance> | ||
21 | |||
22 | export type RemoveByUserIdCallback = (err: Error) => void | ||
23 | export type RemoveByUserId = (userId, callback) => void | ||
24 | } | ||
25 | |||
26 | export interface OAuthTokenClass { | ||
27 | getByRefreshTokenAndPopulateClient: OAuthTokenMethods.GetByRefreshTokenAndPopulateClient | ||
28 | getByTokenAndPopulateUser: OAuthTokenMethods.GetByTokenAndPopulateUser | ||
29 | getByRefreshTokenAndPopulateUser: OAuthTokenMethods.GetByRefreshTokenAndPopulateUser | ||
30 | removeByUserId: OAuthTokenMethods.RemoveByUserId | ||
31 | } | ||
32 | |||
33 | export interface OAuthTokenAttributes { | ||
34 | accessToken: string | ||
35 | accessTokenExpiresAt: Date | ||
36 | refreshToken: string | ||
37 | refreshTokenExpiresAt: Date | ||
38 | |||
39 | User?: UserModel | ||
40 | } | ||
41 | |||
42 | export interface OAuthTokenInstance extends OAuthTokenClass, OAuthTokenAttributes, Sequelize.Instance<OAuthTokenAttributes> { | ||
43 | id: number | ||
44 | createdAt: Date | ||
45 | updatedAt: Date | ||
46 | } | ||
47 | |||
48 | export interface OAuthTokenModel extends OAuthTokenClass, Sequelize.Model<OAuthTokenInstance, OAuthTokenAttributes> {} | ||
diff --git a/server/models/oauth/oauth-token.ts b/server/models/oauth/oauth-token.ts new file mode 100644 index 000000000..eab9cf858 --- /dev/null +++ b/server/models/oauth/oauth-token.ts | |||
@@ -0,0 +1,160 @@ | |||
1 | import * as Sequelize from 'sequelize' | ||
2 | |||
3 | import { logger } from '../../helpers' | ||
4 | |||
5 | import { addMethodsToModel } from '../utils' | ||
6 | import { | ||
7 | OAuthTokenClass, | ||
8 | OAuthTokenInstance, | ||
9 | OAuthTokenAttributes, | ||
10 | |||
11 | OAuthTokenMethods, | ||
12 | OAuthTokenInfo | ||
13 | } from './oauth-token-interface' | ||
14 | |||
15 | let OAuthToken: Sequelize.Model<OAuthTokenInstance, OAuthTokenAttributes> | ||
16 | let getByRefreshTokenAndPopulateClient: OAuthTokenMethods.GetByRefreshTokenAndPopulateClient | ||
17 | let getByTokenAndPopulateUser: OAuthTokenMethods.GetByTokenAndPopulateUser | ||
18 | let getByRefreshTokenAndPopulateUser: OAuthTokenMethods.GetByRefreshTokenAndPopulateUser | ||
19 | let removeByUserId: OAuthTokenMethods.RemoveByUserId | ||
20 | |||
21 | export default function (sequelize: Sequelize.Sequelize, DataTypes: Sequelize.DataTypes) { | ||
22 | OAuthToken = sequelize.define<OAuthTokenInstance, OAuthTokenAttributes>('OAuthToken', | ||
23 | { | ||
24 | accessToken: { | ||
25 | type: DataTypes.STRING, | ||
26 | allowNull: false | ||
27 | }, | ||
28 | accessTokenExpiresAt: { | ||
29 | type: DataTypes.DATE, | ||
30 | allowNull: false | ||
31 | }, | ||
32 | refreshToken: { | ||
33 | type: DataTypes.STRING, | ||
34 | allowNull: false | ||
35 | }, | ||
36 | refreshTokenExpiresAt: { | ||
37 | type: DataTypes.DATE, | ||
38 | allowNull: false | ||
39 | } | ||
40 | }, | ||
41 | { | ||
42 | indexes: [ | ||
43 | { | ||
44 | fields: [ 'refreshToken' ], | ||
45 | unique: true | ||
46 | }, | ||
47 | { | ||
48 | fields: [ 'accessToken' ], | ||
49 | unique: true | ||
50 | }, | ||
51 | { | ||
52 | fields: [ 'userId' ] | ||
53 | }, | ||
54 | { | ||
55 | fields: [ 'oAuthClientId' ] | ||
56 | } | ||
57 | ] | ||
58 | } | ||
59 | ) | ||
60 | |||
61 | const classMethods = [ | ||
62 | associate, | ||
63 | |||
64 | getByRefreshTokenAndPopulateClient, | ||
65 | getByTokenAndPopulateUser, | ||
66 | getByRefreshTokenAndPopulateUser, | ||
67 | removeByUserId | ||
68 | ] | ||
69 | addMethodsToModel(OAuthToken, classMethods) | ||
70 | |||
71 | return OAuthToken | ||
72 | } | ||
73 | |||
74 | // --------------------------------------------------------------------------- | ||
75 | |||
76 | function associate (models) { | ||
77 | OAuthToken.belongsTo(models.User, { | ||
78 | foreignKey: { | ||
79 | name: 'userId', | ||
80 | allowNull: false | ||
81 | }, | ||
82 | onDelete: 'cascade' | ||
83 | }) | ||
84 | |||
85 | OAuthToken.belongsTo(models.OAuthClient, { | ||
86 | foreignKey: { | ||
87 | name: 'oAuthClientId', | ||
88 | allowNull: false | ||
89 | }, | ||
90 | onDelete: 'cascade' | ||
91 | }) | ||
92 | } | ||
93 | |||
94 | getByRefreshTokenAndPopulateClient = function (refreshToken: string) { | ||
95 | const query = { | ||
96 | where: { | ||
97 | refreshToken: refreshToken | ||
98 | }, | ||
99 | include: [ OAuthToken['sequelize'].models.OAuthClient ] | ||
100 | } | ||
101 | |||
102 | return OAuthToken.findOne(query).then(function (token) { | ||
103 | if (!token) return null | ||
104 | |||
105 | const tokenInfos: OAuthTokenInfo = { | ||
106 | refreshToken: token.refreshToken, | ||
107 | refreshTokenExpiresAt: token.refreshTokenExpiresAt, | ||
108 | client: { | ||
109 | id: token['client'].id | ||
110 | }, | ||
111 | user: { | ||
112 | id: token['user'] | ||
113 | } | ||
114 | } | ||
115 | |||
116 | return tokenInfos | ||
117 | }).catch(function (err) { | ||
118 | logger.info('getRefreshToken error.', { error: err }) | ||
119 | }) | ||
120 | } | ||
121 | |||
122 | getByTokenAndPopulateUser = function (bearerToken: string) { | ||
123 | const query = { | ||
124 | where: { | ||
125 | accessToken: bearerToken | ||
126 | }, | ||
127 | include: [ OAuthToken['sequelize'].models.User ] | ||
128 | } | ||
129 | |||
130 | return OAuthToken.findOne(query).then(function (token) { | ||
131 | if (token) token['user'] = token.User | ||
132 | |||
133 | return token | ||
134 | }) | ||
135 | } | ||
136 | |||
137 | getByRefreshTokenAndPopulateUser = function (refreshToken: string) { | ||
138 | const query = { | ||
139 | where: { | ||
140 | refreshToken: refreshToken | ||
141 | }, | ||
142 | include: [ OAuthToken['sequelize'].models.User ] | ||
143 | } | ||
144 | |||
145 | return OAuthToken.findOne(query).then(function (token) { | ||
146 | token['user'] = token.User | ||
147 | |||
148 | return token | ||
149 | }) | ||
150 | } | ||
151 | |||
152 | removeByUserId = function (userId, callback) { | ||
153 | const query = { | ||
154 | where: { | ||
155 | userId: userId | ||
156 | } | ||
157 | } | ||
158 | |||
159 | return OAuthToken.destroy(query).asCallback(callback) | ||
160 | } | ||