diff --git a/src/api/middlewares/Authentication.ts b/src/api/middlewares/Authentication.ts
index 771f0de8..55527984 100644
--- a/src/api/middlewares/Authentication.ts
+++ b/src/api/middlewares/Authentication.ts
@@ -52,6 +52,8 @@ export const NO_AUTHORIZATION_ROUTES = [
"/oauth2/callback",
// Asset delivery
/\/guilds\/\d+\/widget\.(json|png)/,
+ // Connections
+ /\/connections\/\w+\/callback/
];
export const API_PREFIX = /^\/api(\/v\d+)?/;
diff --git a/src/api/routes/connections/#connection_name/#connection_id/refresh.ts b/src/api/routes/connections/#connection_name/#connection_id/refresh.ts
new file mode 100644
index 00000000..cce50436
--- /dev/null
+++ b/src/api/routes/connections/#connection_name/#connection_id/refresh.ts
@@ -0,0 +1,11 @@
+import { route } from "@fosscord/api";
+import { Request, Response, Router } from "express";
+const router = Router();
+
+router.post("/", route({}), async (req: Request, res: Response) => {
+ // TODO:
+ const { connection_name, connection_id } = req.params;
+ res.sendStatus(204);
+});
+
+export default router;
diff --git a/src/api/routes/connections/#connection_name/authorize.ts b/src/api/routes/connections/#connection_name/authorize.ts
new file mode 100644
index 00000000..8e640a69
--- /dev/null
+++ b/src/api/routes/connections/#connection_name/authorize.ts
@@ -0,0 +1,35 @@
+import { Request, Response, Router } from "express";
+import { FieldErrors } from "../../../../util";
+import { ConnectionStore } from "../../../../util/connections";
+import { route } from "../../../util";
+
+const router = Router();
+
+router.get("/", route({}), async (req: Request, res: Response) => {
+ const { connection_id: connection_name } = req.params;
+ const connection = ConnectionStore.connections.get(connection_name);
+ if (!connection)
+ throw FieldErrors({
+ provider_id: {
+ code: "BASE_TYPE_CHOICES",
+ message: req.t("common:field.BASE_TYPE_CHOICES", {
+ types: Array.from(ConnectionStore.connections.keys()).join(
+ ", ",
+ ),
+ }),
+ },
+ });
+
+ if (!connection.settings.enabled)
+ throw FieldErrors({
+ provider_id: {
+ message: "This connection has been disabled server-side.",
+ },
+ });
+
+ res.json({
+ url: await connection.getAuthorizationUrl(req.user_id),
+ });
+});
+
+export default router;
diff --git a/src/api/routes/connections/#connection_name/callback.ts b/src/api/routes/connections/#connection_name/callback.ts
new file mode 100644
index 00000000..f158a037
--- /dev/null
+++ b/src/api/routes/connections/#connection_name/callback.ts
@@ -0,0 +1,52 @@
+import { Request, Response, Router } from "express";
+import {
+ ConnectionCallbackSchema,
+ emitEvent,
+ FieldErrors,
+} from "../../../../util";
+import { ConnectionStore } from "../../../../util/connections";
+import { route } from "../../../util";
+
+const router = Router();
+
+router.post(
+ "/",
+ route({ body: "ConnectionCallbackSchema" }),
+ async (req: Request, res: Response) => {
+ const { connection_id: connection_name } = req.params;
+ const connection = ConnectionStore.connections.get(connection_name);
+ if (!connection)
+ throw FieldErrors({
+ provider_id: {
+ code: "BASE_TYPE_CHOICES",
+ message: req.t("common:field.BASE_TYPE_CHOICES", {
+ types: Array.from(
+ ConnectionStore.connections.keys(),
+ ).join(", "),
+ }),
+ },
+ });
+
+ if (!connection.settings.enabled)
+ throw FieldErrors({
+ provider_id: {
+ message: "This connection has been disabled server-side.",
+ },
+ });
+
+ const body = req.body as ConnectionCallbackSchema;
+ const userId = connection.getUserId(body.state);
+ const emit = await connection.handleCallback(body);
+
+ // whether we should emit a connections update event, only used when a connection doesnt already exist
+ if (emit)
+ emitEvent({
+ event: "USER_CONNECTIONS_UPDATE",
+ data: {},
+ user_id: userId,
+ });
+ res.sendStatus(204);
+ },
+);
+
+export default router;
diff --git a/src/api/routes/users/@me/connections.ts b/src/api/routes/users/@me/connections.ts
index 74315bfe..a5041be1 100644
--- a/src/api/routes/users/@me/connections.ts
+++ b/src/api/routes/users/@me/connections.ts
@@ -16,14 +16,32 @@
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
-import { Request, Response, Router } from "express";
import { route } from "@fosscord/api";
+import { ConnectedAccount, ConnectedAccountDTO } from "@fosscord/util";
+import { Request, Response, Router } from "express";
const router: Router = Router();
router.get("/", route({}), async (req: Request, res: Response) => {
- //TODO
- res.json([]).status(200);
+ const connections = await ConnectedAccount.find({
+ where: {
+ user_id: req.user_id,
+ },
+ select: [
+ "external_id",
+ "type",
+ "name",
+ "verified",
+ "visibility",
+ "show_activity",
+ "revoked",
+ "access_token",
+ "friend_sync",
+ "integrations",
+ ],
+ });
+
+ res.json(connections.map((x) => new ConnectedAccountDTO(x, true)));
});
export default router;
|