-import * as Sequelize from 'sequelize'
-
-import { logger } from '../../helpers'
-
-import { addMethodsToModel } from '../utils'
+import { Transaction } from 'sequelize'
import {
- OAuthTokenInstance,
- OAuthTokenAttributes,
-
- OAuthTokenMethods,
- OAuthTokenInfo
-} from './oauth-token-interface'
+ AfterDestroy,
+ AfterUpdate,
+ AllowNull,
+ BelongsTo,
+ Column,
+ CreatedAt,
+ ForeignKey,
+ Model,
+ Scopes,
+ Table,
+ UpdatedAt
+} from 'sequelize-typescript'
+import { TokensCache } from '@server/lib/auth/tokens-cache'
+import { MUserAccountId } from '@server/types/models'
+import { MOAuthTokenUser } from '@server/types/models/oauth/oauth-token'
+import { AttributesOnly } from '@shared/typescript-utils'
+import { logger } from '../../helpers/logger'
+import { AccountModel } from '../account/account'
+import { ActorModel } from '../actor/actor'
+import { UserModel } from '../user/user'
+import { OAuthClientModel } from './oauth-client'
+
+export type OAuthTokenInfo = {
+ refreshToken: string
+ refreshTokenExpiresAt: Date
+ client: {
+ id: number
+ }
+ user: MUserAccountId
+ token: MOAuthTokenUser
+}
-let OAuthToken: Sequelize.Model<OAuthTokenInstance, OAuthTokenAttributes>
-let getByRefreshTokenAndPopulateClient: OAuthTokenMethods.GetByRefreshTokenAndPopulateClient
-let getByTokenAndPopulateUser: OAuthTokenMethods.GetByTokenAndPopulateUser
-let getByRefreshTokenAndPopulateUser: OAuthTokenMethods.GetByRefreshTokenAndPopulateUser
-let removeByUserId: OAuthTokenMethods.RemoveByUserId
+enum ScopeNames {
+ WITH_USER = 'WITH_USER'
+}
-export default function (sequelize: Sequelize.Sequelize, DataTypes: Sequelize.DataTypes) {
- OAuthToken = sequelize.define<OAuthTokenInstance, OAuthTokenAttributes>('OAuthToken',
- {
- accessToken: {
- type: DataTypes.STRING,
- allowNull: false
- },
- accessTokenExpiresAt: {
- type: DataTypes.DATE,
- allowNull: false
- },
- refreshToken: {
- type: DataTypes.STRING,
- allowNull: false
- },
- refreshTokenExpiresAt: {
- type: DataTypes.DATE,
- allowNull: false
+@Scopes(() => ({
+ [ScopeNames.WITH_USER]: {
+ include: [
+ {
+ model: UserModel.unscoped(),
+ required: true,
+ include: [
+ {
+ attributes: [ 'id' ],
+ model: AccountModel.unscoped(),
+ required: true,
+ include: [
+ {
+ attributes: [ 'id', 'url' ],
+ model: ActorModel.unscoped(),
+ required: true
+ }
+ ]
+ }
+ ]
}
+ ]
+ }
+}))
+@Table({
+ tableName: 'oAuthToken',
+ indexes: [
+ {
+ fields: [ 'refreshToken' ],
+ unique: true
},
{
- indexes: [
- {
- fields: [ 'refreshToken' ],
- unique: true
- },
- {
- fields: [ 'accessToken' ],
- unique: true
- },
- {
- fields: [ 'userId' ]
- },
- {
- fields: [ 'oAuthClientId' ]
- }
- ]
+ fields: [ 'accessToken' ],
+ unique: true
+ },
+ {
+ fields: [ 'userId' ]
+ },
+ {
+ fields: [ 'oAuthClientId' ]
}
- )
+ ]
+})
+export class OAuthTokenModel extends Model<Partial<AttributesOnly<OAuthTokenModel>>> {
- const classMethods = [
- associate,
+ @AllowNull(false)
+ @Column
+ accessToken: string
- getByRefreshTokenAndPopulateClient,
- getByTokenAndPopulateUser,
- getByRefreshTokenAndPopulateUser,
- removeByUserId
- ]
- addMethodsToModel(OAuthToken, classMethods)
+ @AllowNull(false)
+ @Column
+ accessTokenExpiresAt: Date
- return OAuthToken
-}
+ @AllowNull(false)
+ @Column
+ refreshToken: string
+
+ @AllowNull(false)
+ @Column
+ refreshTokenExpiresAt: Date
+
+ @Column
+ authName: string
-// ---------------------------------------------------------------------------
+ @CreatedAt
+ createdAt: Date
-function associate (models) {
- OAuthToken.belongsTo(models.User, {
+ @UpdatedAt
+ updatedAt: Date
+
+ @ForeignKey(() => UserModel)
+ @Column
+ userId: number
+
+ @BelongsTo(() => UserModel, {
foreignKey: {
- name: 'userId',
allowNull: false
},
onDelete: 'cascade'
})
+ User: UserModel
+
+ @ForeignKey(() => OAuthClientModel)
+ @Column
+ oAuthClientId: number
- OAuthToken.belongsTo(models.OAuthClient, {
+ @BelongsTo(() => OAuthClientModel, {
foreignKey: {
- name: 'oAuthClientId',
allowNull: false
},
onDelete: 'cascade'
})
-}
+ OAuthClients: OAuthClientModel[]
-getByRefreshTokenAndPopulateClient = function (refreshToken: string) {
- const query = {
- where: {
- refreshToken: refreshToken
- },
- include: [ OAuthToken['sequelize'].models.OAuthClient ]
+ @AfterUpdate
+ @AfterDestroy
+ static removeTokenCache (token: OAuthTokenModel) {
+ return TokensCache.Instance.clearCacheByToken(token.accessToken)
}
- return OAuthToken.findOne(query).then(function (token) {
- if (!token) return null
+ static loadByRefreshToken (refreshToken: string) {
+ const query = {
+ where: { refreshToken }
+ }
+
+ return OAuthTokenModel.findOne(query)
+ }
- const tokenInfos: OAuthTokenInfo = {
- refreshToken: token.refreshToken,
- refreshTokenExpiresAt: token.refreshTokenExpiresAt,
- client: {
- id: token['client'].id
+ static getByRefreshTokenAndPopulateClient (refreshToken: string) {
+ const query = {
+ where: {
+ refreshToken
},
- user: {
- id: token['user']
+ include: [ OAuthClientModel ]
+ }
+
+ return OAuthTokenModel.scope(ScopeNames.WITH_USER)
+ .findOne(query)
+ .then(token => {
+ if (!token) return null
+
+ return {
+ refreshToken: token.refreshToken,
+ refreshTokenExpiresAt: token.refreshTokenExpiresAt,
+ client: {
+ id: token.oAuthClientId
+ },
+ user: token.User,
+ token
+ } as OAuthTokenInfo
+ })
+ .catch(err => {
+ logger.error('getRefreshToken error.', { err })
+ throw err
+ })
+ }
+
+ static getByTokenAndPopulateUser (bearerToken: string): Promise<MOAuthTokenUser> {
+ const query = {
+ where: {
+ accessToken: bearerToken
}
}
- return tokenInfos
- }).catch(function (err) {
- logger.info('getRefreshToken error.', { error: err })
- })
-}
+ return OAuthTokenModel.scope(ScopeNames.WITH_USER)
+ .findOne(query)
+ .then(token => {
+ if (!token) return null
-getByTokenAndPopulateUser = function (bearerToken: string) {
- const query = {
- where: {
- accessToken: bearerToken
- },
- include: [ OAuthToken['sequelize'].models.User ]
+ return Object.assign(token, { user: token.User })
+ })
}
- return OAuthToken.findOne(query).then(function (token) {
- if (token) token['user'] = token.User
+ static getByRefreshTokenAndPopulateUser (refreshToken: string): Promise<MOAuthTokenUser> {
+ const query = {
+ where: {
+ refreshToken
+ }
+ }
- return token
- })
-}
+ return OAuthTokenModel.scope(ScopeNames.WITH_USER)
+ .findOne(query)
+ .then(token => {
+ if (!token) return undefined
-getByRefreshTokenAndPopulateUser = function (refreshToken: string) {
- const query = {
- where: {
- refreshToken: refreshToken
- },
- include: [ OAuthToken['sequelize'].models.User ]
+ return Object.assign(token, { user: token.User })
+ })
}
- return OAuthToken.findOne(query).then(function (token) {
- token['user'] = token.User
+ static deleteUserToken (userId: number, t?: Transaction) {
+ TokensCache.Instance.deleteUserToken(userId)
- return token
- })
-}
-
-removeByUserId = function (userId: number) {
- const query = {
- where: {
- userId: userId
+ const query = {
+ where: {
+ userId
+ },
+ transaction: t
}
- }
- return OAuthToken.destroy(query)
+ return OAuthTokenModel.destroy(query)
+ }
}