diff --git a/src/util/connections/Connection.ts b/src/util/connections/Connection.ts
index 164cfac7..8b60b0d2 100644
--- a/src/util/connections/Connection.ts
+++ b/src/util/connections/Connection.ts
@@ -1,9 +1,11 @@
import crypto from "crypto";
import { ConnectedAccount } from "../entities";
-import { OrmUtils } from "../imports";
import { ConnectedAccountSchema, ConnectionCallbackSchema } from "../schemas";
import { DiscordApiErrors } from "../util";
+/**
+ * A connection that can be used to connect to an external service.
+ */
export default abstract class Connection {
id: string;
settings: { enabled: boolean };
@@ -21,7 +23,9 @@ export default abstract class Connection {
* Processes the callback
* @param args Callback arguments
*/
- abstract handleCallback(params: ConnectionCallbackSchema): Promise<ConnectedAccount | null>;
+ abstract handleCallback(
+ params: ConnectionCallbackSchema,
+ ): Promise<ConnectedAccount | null>;
/**
* Gets a user id from state
@@ -54,12 +58,25 @@ export default abstract class Connection {
this.states.delete(state);
}
- async createConnection(data: ConnectedAccountSchema): Promise<ConnectedAccount> {
- const ca = OrmUtils.mergeDeep(new ConnectedAccount(), data) as ConnectedAccount;
+ /**
+ * Creates a Connected Account in the database.
+ * @param data connected account data
+ * @returns the new connected account
+ */
+ async createConnection(
+ data: ConnectedAccountSchema,
+ ): Promise<ConnectedAccount> {
+ const ca = ConnectedAccount.create({ ...data });
await ca.save();
return ca;
}
+ /**
+ * Checks if a user has an exist connected account for the given extenal id.
+ * @param userId the user id
+ * @param externalId the connection id to find
+ * @returns
+ */
async hasConnection(userId: string, externalId: string): Promise<boolean> {
const existing = await ConnectedAccount.findOne({
where: {
diff --git a/src/util/connections/ConnectionStore.ts b/src/util/connections/ConnectionStore.ts
index 406e8232..759b6de7 100644
--- a/src/util/connections/ConnectionStore.ts
+++ b/src/util/connections/ConnectionStore.ts
@@ -1,5 +1,7 @@
import Connection from "./Connection";
+import RefreshableConnection from "./RefreshableConnection";
export class ConnectionStore {
- public static connections: Map<string, Connection> = new Map();
+ public static connections: Map<string, Connection | RefreshableConnection> =
+ new Map();
}
diff --git a/src/util/connections/RefreshableConnection.ts b/src/util/connections/RefreshableConnection.ts
new file mode 100644
index 00000000..0008cbc0
--- /dev/null
+++ b/src/util/connections/RefreshableConnection.ts
@@ -0,0 +1,30 @@
+import { ConnectedAccount } from "../entities";
+import { ConnectedAccountCommonOAuthTokenResponse } from "../interfaces";
+import Connection from "./Connection";
+
+/**
+ * A connection that can refresh its token.
+ */
+export default abstract class RefreshableConnection extends Connection {
+ refreshEnabled = true;
+ /**
+ * Refreshes the token for a connected account.
+ * @param connectedAccount The connected account to refresh
+ */
+ abstract refreshToken(
+ connectedAccount: ConnectedAccount,
+ ): Promise<ConnectedAccountCommonOAuthTokenResponse>;
+
+ /**
+ * Refreshes the token for a connected account and saves it to the database.
+ * @param connectedAccount The connected account to refresh
+ */
+ async refresh(
+ connectedAccount: ConnectedAccount,
+ ): Promise<ConnectedAccountCommonOAuthTokenResponse> {
+ const tokenData = await this.refreshToken(connectedAccount);
+ connectedAccount.token_data = tokenData;
+ await connectedAccount.save();
+ return tokenData;
+ }
+}
diff --git a/src/util/connections/index.ts b/src/util/connections/index.ts
index e15d0c8c..8d20bf27 100644
--- a/src/util/connections/index.ts
+++ b/src/util/connections/index.ts
@@ -2,3 +2,4 @@ export * from "./Connection";
export * from "./ConnectionConfig";
export * from "./ConnectionLoader";
export * from "./ConnectionStore";
+export * from "./RefreshableConnection";
diff --git a/src/util/dtos/ConnectedAccountDTO.ts b/src/util/dtos/ConnectedAccountDTO.ts
index debc5535..ca15ff41 100644
--- a/src/util/dtos/ConnectedAccountDTO.ts
+++ b/src/util/dtos/ConnectedAccountDTO.ts
@@ -23,8 +23,8 @@ export class ConnectedAccountDTO {
this.id = connectedAccount.external_id;
this.user_id = connectedAccount.user_id;
this.access_token =
- connectedAccount.access_token && with_token
- ? connectedAccount.access_token
+ connectedAccount.token_data && with_token
+ ? connectedAccount.token_data.access_token
: undefined;
this.friend_sync = connectedAccount.friend_sync;
this.name = connectedAccount.name;
diff --git a/src/util/entities/ConnectedAccount.ts b/src/util/entities/ConnectedAccount.ts
index 25d5a0c7..beb53e41 100644
--- a/src/util/entities/ConnectedAccount.ts
+++ b/src/util/entities/ConnectedAccount.ts
@@ -17,6 +17,7 @@
*/
import { Column, Entity, JoinColumn, ManyToOne, RelationId } from "typeorm";
+import { ConnectedAccountTokenData } from "../interfaces";
import { BaseClass } from "./BaseClass";
import { User } from "./User";
@@ -40,9 +41,6 @@ export class ConnectedAccount extends BaseClass {
})
user: User;
- @Column({ select: false, nullable: true })
- access_token?: string;
-
@Column({ select: false })
friend_sync?: boolean = false;
@@ -75,4 +73,7 @@ export class ConnectedAccount extends BaseClass {
@Column()
two_way_link?: boolean = false;
+
+ @Column({ select: false, nullable: true, type: "simple-json" })
+ token_data?: ConnectedAccountTokenData;
}
diff --git a/src/util/interfaces/ConnectedAccount.ts b/src/util/interfaces/ConnectedAccount.ts
new file mode 100644
index 00000000..c96e5f79
--- /dev/null
+++ b/src/util/interfaces/ConnectedAccount.ts
@@ -0,0 +1,16 @@
+export interface ConnectedAccountCommonOAuthTokenResponse {
+ access_token: string;
+ token_type: string;
+ scope: string;
+ refresh_token?: string;
+ expires_in?: number;
+}
+
+export interface ConnectedAccountTokenData {
+ access_token: string;
+ token_type?: string;
+ scope?: string;
+ refresh_token?: string;
+ expires_in?: number;
+ expires_at?: number;
+}
diff --git a/src/util/interfaces/index.ts b/src/util/interfaces/index.ts
index fa259ce1..e194d174 100644
--- a/src/util/interfaces/index.ts
+++ b/src/util/interfaces/index.ts
@@ -17,7 +17,8 @@
*/
export * from "./Activity";
-export * from "./Presence";
-export * from "./Interaction";
+export * from "./ConnectedAccount";
export * from "./Event";
+export * from "./Interaction";
+export * from "./Presence";
export * from "./Status";
diff --git a/src/util/schemas/ConnectedAccountSchema.ts b/src/util/schemas/ConnectedAccountSchema.ts
index e00e4fa1..e5f838d0 100644
--- a/src/util/schemas/ConnectedAccountSchema.ts
+++ b/src/util/schemas/ConnectedAccountSchema.ts
@@ -1,7 +1,9 @@
+import { ConnectedAccountTokenData } from "../interfaces";
+
export interface ConnectedAccountSchema {
external_id: string;
user_id: string;
- access_token?: string;
+ token_data?: ConnectedAccountTokenData;
friend_sync?: boolean;
name: string;
revoked?: boolean;
|