User Authentication Flow Works

This commit is contained in:
2026-01-25 15:03:17 -06:00
parent 1bf0acdf39
commit e76caa68f1
22 changed files with 275 additions and 248 deletions
+3 -14
View File
@@ -2,27 +2,16 @@ version: "3"
services:
pgsql:
image: postgres
image: postgres:17
restart: unless-stopped
environment:
POSTGRES_USER: duxcore
POSTGRES_USER: ttscm
POSTGRES_PASSWORD: 123web123
POSTGRES_DB: duxcore
POSTGRES_DB: ttscm
volumes:
- ./postgres:/var/lib/postgresql/data
ports:
- 5432:5432
pgsql-boss:
image: postgres
restart: unless-stopped
environment:
POSTGRES_USER: pg-boss
POSTGRES_PASSWORD: 123web123
POSTGRES_DB: pg-boss
volumes:
- ./postgres-pgb:/var/lib/postgresql/data
ports:
- 2345:5432
redis:
image: redis:6.2-alpine
+12
View File
@@ -5,9 +5,11 @@
"": {
"name": "ttscm-api",
"dependencies": {
"@azure/msal-node": "^5.0.2",
"@discordjs/collection": "^2.1.1",
"@duxcore/eventra": "^1.1.0",
"@prisma/adapter-pg": "^7.3.0",
"@prisma/client": "^7.3.0",
"cors": "^2.8.6",
"cuid": "^3.0.0",
"hono": "^4.11.5",
@@ -27,6 +29,10 @@
},
},
"packages": {
"@azure/msal-common": ["@azure/msal-common@16.0.2", "", {}, "sha512-ZJ/UR7lyqIntURrIJCyvScwJFanM9QhJYcJCheB21jZofGKpP9QxWgvADANo7UkresHKzV+6YwoeZYP7P7HvUg=="],
"@azure/msal-node": ["@azure/msal-node@5.0.2", "", { "dependencies": { "@azure/msal-common": "16.0.2", "jsonwebtoken": "^9.0.0", "uuid": "^8.3.0" } }, "sha512-3tHeJghckgpTX98TowJoXOjKGuds0L+FKfeHJtoZFl2xvwE6RF65shZJzMQ5EQZWXzh3sE1i9gE+m3aRMachjA=="],
"@chevrotain/cst-dts-gen": ["@chevrotain/cst-dts-gen@10.5.0", "", { "dependencies": { "@chevrotain/gast": "10.5.0", "@chevrotain/types": "10.5.0", "lodash": "4.17.21" } }, "sha512-lhmC/FyqQ2o7pGK4Om+hzuDrm9rhFYIJ/AXoQBeongmn870Xeb0L6oGEiuR8nohFNL5sMaQEJWCxr1oIVIVXrw=="],
"@chevrotain/gast": ["@chevrotain/gast@10.5.0", "", { "dependencies": { "@chevrotain/types": "10.5.0", "lodash": "4.17.21" } }, "sha512-pXdMJ9XeDAbgOWKuD1Fldz4ieCs6+nLNmyVhe2gZVqoO7v8HXuHYs5OV2EzUtbuai37TlOAQHrTDvxMnvMJz3A=="],
@@ -51,6 +57,10 @@
"@prisma/adapter-pg": ["@prisma/adapter-pg@7.3.0", "", { "dependencies": { "@prisma/driver-adapter-utils": "7.3.0", "pg": "^8.16.3", "postgres-array": "3.0.4" } }, "sha512-iuYQMbIPO6i9O45Fv8TB7vWu00BXhCaNAShenqF7gLExGDbnGp5BfFB4yz1K59zQ59jF6tQ9YHrg0P6/J3OoLg=="],
"@prisma/client": ["@prisma/client@7.3.0", "", { "dependencies": { "@prisma/client-runtime-utils": "7.3.0" }, "peerDependencies": { "prisma": "*", "typescript": ">=5.4.0" }, "optionalPeers": ["prisma", "typescript"] }, "sha512-FXBIxirqQfdC6b6HnNgxGmU7ydCPEPk7maHMOduJJfnTP+MuOGa15X4omjR/zpPUUpm8ef/mEFQjJudOGkXFcQ=="],
"@prisma/client-runtime-utils": ["@prisma/client-runtime-utils@7.3.0", "", {}, "sha512-dG/ceD9c+tnXATPk8G+USxxYM9E6UdMTnQeQ+1SZUDxTz7SgQcfxEqafqIQHcjdlcNK/pvmmLfSwAs3s2gYwUw=="],
"@prisma/config": ["@prisma/config@7.3.0", "", { "dependencies": { "c12": "3.1.0", "deepmerge-ts": "7.1.5", "effect": "3.18.4", "empathic": "2.0.0" } }, "sha512-QyMV67+eXF7uMtKxTEeQqNu/Be7iH+3iDZOQZW5ttfbSwBamCSdwPszA0dum+Wx27I7anYTPLmRmMORKViSW1A=="],
"@prisma/debug": ["@prisma/debug@7.3.0", "", {}, "sha512-yh/tHhraCzYkffsI1/3a7SHX8tpgbJu1NPnuxS4rEpJdWAUDHUH25F1EDo6PPzirpyLNkgPPZdhojQK804BGtg=="],
@@ -281,6 +291,8 @@
"undici-types": ["undici-types@7.16.0", "", {}, "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw=="],
"uuid": ["uuid@8.3.2", "", { "bin": { "uuid": "dist/bin/uuid" } }, "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg=="],
"valibot": ["valibot@1.2.0", "", { "peerDependencies": { "typescript": ">=5" }, "optionalPeers": ["typescript"] }, "sha512-mm1rxUsmOxzrwnX5arGS+U4T25RdvpPjPN4yR0u9pUBov9+zGVtO84tif1eY4r6zWxVxu3KzIyknJy3rxfRZZg=="],
"vary": ["vary@1.1.2", "", {}, "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg=="],
-54
View File
@@ -130,17 +130,6 @@ export type StringNullableFilter<$PrismaModel = never> = {
not?: Prisma.NestedStringNullableFilter<$PrismaModel> | string | null
}
export type IntFilter<$PrismaModel = never> = {
equals?: number | Prisma.IntFieldRefInput<$PrismaModel>
in?: number[] | Prisma.ListIntFieldRefInput<$PrismaModel>
notIn?: number[] | Prisma.ListIntFieldRefInput<$PrismaModel>
lt?: number | Prisma.IntFieldRefInput<$PrismaModel>
lte?: number | Prisma.IntFieldRefInput<$PrismaModel>
gt?: number | Prisma.IntFieldRefInput<$PrismaModel>
gte?: number | Prisma.IntFieldRefInput<$PrismaModel>
not?: Prisma.NestedIntFilter<$PrismaModel> | number
}
export type StringNullableWithAggregatesFilter<$PrismaModel = never> = {
equals?: string | Prisma.StringFieldRefInput<$PrismaModel> | null
in?: string[] | Prisma.ListStringFieldRefInput<$PrismaModel> | null
@@ -159,22 +148,6 @@ export type StringNullableWithAggregatesFilter<$PrismaModel = never> = {
_max?: Prisma.NestedStringNullableFilter<$PrismaModel>
}
export type IntWithAggregatesFilter<$PrismaModel = never> = {
equals?: number | Prisma.IntFieldRefInput<$PrismaModel>
in?: number[] | Prisma.ListIntFieldRefInput<$PrismaModel>
notIn?: number[] | Prisma.ListIntFieldRefInput<$PrismaModel>
lt?: number | Prisma.IntFieldRefInput<$PrismaModel>
lte?: number | Prisma.IntFieldRefInput<$PrismaModel>
gt?: number | Prisma.IntFieldRefInput<$PrismaModel>
gte?: number | Prisma.IntFieldRefInput<$PrismaModel>
not?: Prisma.NestedIntWithAggregatesFilter<$PrismaModel> | number
_count?: Prisma.NestedIntFilter<$PrismaModel>
_avg?: Prisma.NestedFloatFilter<$PrismaModel>
_sum?: Prisma.NestedIntFilter<$PrismaModel>
_min?: Prisma.NestedIntFilter<$PrismaModel>
_max?: Prisma.NestedIntFilter<$PrismaModel>
}
export type NestedStringFilter<$PrismaModel = never> = {
equals?: string | Prisma.StringFieldRefInput<$PrismaModel>
in?: string[] | Prisma.ListStringFieldRefInput<$PrismaModel>
@@ -322,31 +295,4 @@ export type NestedStringNullableWithAggregatesFilter<$PrismaModel = never> = {
_max?: Prisma.NestedStringNullableFilter<$PrismaModel>
}
export type NestedIntWithAggregatesFilter<$PrismaModel = never> = {
equals?: number | Prisma.IntFieldRefInput<$PrismaModel>
in?: number[] | Prisma.ListIntFieldRefInput<$PrismaModel>
notIn?: number[] | Prisma.ListIntFieldRefInput<$PrismaModel>
lt?: number | Prisma.IntFieldRefInput<$PrismaModel>
lte?: number | Prisma.IntFieldRefInput<$PrismaModel>
gt?: number | Prisma.IntFieldRefInput<$PrismaModel>
gte?: number | Prisma.IntFieldRefInput<$PrismaModel>
not?: Prisma.NestedIntWithAggregatesFilter<$PrismaModel> | number
_count?: Prisma.NestedIntFilter<$PrismaModel>
_avg?: Prisma.NestedFloatFilter<$PrismaModel>
_sum?: Prisma.NestedIntFilter<$PrismaModel>
_min?: Prisma.NestedIntFilter<$PrismaModel>
_max?: Prisma.NestedIntFilter<$PrismaModel>
}
export type NestedFloatFilter<$PrismaModel = never> = {
equals?: number | Prisma.FloatFieldRefInput<$PrismaModel>
in?: number[] | Prisma.ListFloatFieldRefInput<$PrismaModel>
notIn?: number[] | Prisma.ListFloatFieldRefInput<$PrismaModel>
lt?: number | Prisma.FloatFieldRefInput<$PrismaModel>
lte?: number | Prisma.FloatFieldRefInput<$PrismaModel>
gt?: number | Prisma.FloatFieldRefInput<$PrismaModel>
gte?: number | Prisma.FloatFieldRefInput<$PrismaModel>
not?: Prisma.NestedFloatFilter<$PrismaModel> | number
}
+2 -2
View File
@@ -20,7 +20,7 @@ const config: runtime.GetPrismaClientConfig = {
"clientVersion": "7.3.0",
"engineVersion": "9d6ad21cbbceab97458517b147a6a09ff43aa735",
"activeProvider": "postgresql",
"inlineSchema": "// This is your Prisma schema file,\n// learn more about it in the docs: https://pris.ly/d/prisma-schema\n\n// Looking for ways to speed up your queries, or scale easily with your serverless or edge functions?\n// Try Prisma Accelerate: https://pris.ly/cli/accelerate-init\n\ngenerator client {\n provider = \"prisma-client\"\n output = \"../generated/prisma\"\n}\n\ndatasource db {\n provider = \"postgresql\"\n}\n\nmodel Session {\n id String @id @default(uuid())\n sessionKey String @unique @default(cuid())\n userId String\n expires DateTime\n refreshTokenGenerated Boolean @default(false)\n refreshedAt DateTime?\n invalidatedAt DateTime?\n user User @relation(fields: [userId], references: [id], onDelete: Cascade)\n}\n\nmodel User {\n id String @id @default(cuid())\n roles Role[]\n permissions String?\n login String @unique\n name String?\n email String @unique\n emailVerified DateTime?\n image String?\n\n userId Int @unique\n token String?\n\n sessions Session[]\n\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n}\n\nmodel Role {\n id String @id @default(uuid())\n title String\n moniker String @unique // e.g. admin, super_admin, moderator\n\n permissions String\n users User[]\n\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n}\n",
"inlineSchema": "// This is your Prisma schema file,\n// learn more about it in the docs: https://pris.ly/d/prisma-schema\n\n// Looking for ways to speed up your queries, or scale easily with your serverless or edge functions?\n// Try Prisma Accelerate: https://pris.ly/cli/accelerate-init\n\ngenerator client {\n provider = \"prisma-client\"\n output = \"../generated/prisma\"\n}\n\ndatasource db {\n provider = \"postgresql\"\n}\n\nmodel Session {\n id String @id @default(uuid())\n sessionKey String @unique @default(cuid())\n userId String\n expires DateTime\n refreshTokenGenerated Boolean @default(false)\n refreshedAt DateTime?\n invalidatedAt DateTime?\n user User @relation(fields: [userId], references: [id], onDelete: Cascade)\n}\n\nmodel User {\n id String @id @default(cuid())\n roles Role[]\n permissions String?\n login String @unique\n name String?\n email String @unique\n emailVerified DateTime?\n image String?\n\n userId String @unique\n token String?\n\n sessions Session[]\n\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n}\n\nmodel Role {\n id String @id @default(uuid())\n title String\n moniker String @unique // e.g. admin, super_admin, moderator\n\n permissions String\n users User[]\n\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n}\n",
"runtimeDataModel": {
"models": {},
"enums": {},
@@ -28,7 +28,7 @@ const config: runtime.GetPrismaClientConfig = {
}
}
config.runtimeDataModel = JSON.parse("{\"models\":{\"Session\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"sessionKey\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"userId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"expires\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"refreshTokenGenerated\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"refreshedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"invalidatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"user\",\"kind\":\"object\",\"type\":\"User\",\"relationName\":\"SessionToUser\"}],\"dbName\":null},\"User\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"roles\",\"kind\":\"object\",\"type\":\"Role\",\"relationName\":\"RoleToUser\"},{\"name\":\"permissions\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"login\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"name\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"email\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"emailVerified\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"image\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"userId\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"token\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"sessions\",\"kind\":\"object\",\"type\":\"Session\",\"relationName\":\"SessionToUser\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"}],\"dbName\":null},\"Role\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"title\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"moniker\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"permissions\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"users\",\"kind\":\"object\",\"type\":\"User\",\"relationName\":\"RoleToUser\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"}],\"dbName\":null}},\"enums\":{},\"types\":{}}")
config.runtimeDataModel = JSON.parse("{\"models\":{\"Session\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"sessionKey\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"userId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"expires\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"refreshTokenGenerated\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"refreshedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"invalidatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"user\",\"kind\":\"object\",\"type\":\"User\",\"relationName\":\"SessionToUser\"}],\"dbName\":null},\"User\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"roles\",\"kind\":\"object\",\"type\":\"Role\",\"relationName\":\"RoleToUser\"},{\"name\":\"permissions\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"login\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"name\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"email\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"emailVerified\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"image\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"userId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"token\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"sessions\",\"kind\":\"object\",\"type\":\"Session\",\"relationName\":\"SessionToUser\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"}],\"dbName\":null},\"Role\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"title\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"moniker\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"permissions\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"users\",\"kind\":\"object\",\"type\":\"User\",\"relationName\":\"RoleToUser\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"}],\"dbName\":null}},\"enums\":{},\"types\":{}}")
async function decodeBase64AsWasm(wasmBase64: string): Promise<WebAssembly.Module> {
const { Buffer } = await import('node:buffer')
@@ -787,20 +787,6 @@ export type IntFieldRefInput<$PrismaModel> = FieldRefInputType<$PrismaModel, 'In
export type ListIntFieldRefInput<$PrismaModel> = FieldRefInputType<$PrismaModel, 'Int[]'>
/**
* Reference to a field of type 'Float'
*/
export type FloatFieldRefInput<$PrismaModel> = FieldRefInputType<$PrismaModel, 'Float'>
/**
* Reference to a field of type 'Float[]'
*/
export type ListFloatFieldRefInput<$PrismaModel> = FieldRefInputType<$PrismaModel, 'Float[]'>
/**
* Batch Payload for updateMany & deleteMany & createMany
*/
+25 -77
View File
@@ -20,20 +20,10 @@ export type UserModel = runtime.Types.Result.DefaultSelection<Prisma.$UserPayloa
export type AggregateUser = {
_count: UserCountAggregateOutputType | null
_avg: UserAvgAggregateOutputType | null
_sum: UserSumAggregateOutputType | null
_min: UserMinAggregateOutputType | null
_max: UserMaxAggregateOutputType | null
}
export type UserAvgAggregateOutputType = {
userId: number | null
}
export type UserSumAggregateOutputType = {
userId: number | null
}
export type UserMinAggregateOutputType = {
id: string | null
permissions: string | null
@@ -42,7 +32,7 @@ export type UserMinAggregateOutputType = {
email: string | null
emailVerified: Date | null
image: string | null
userId: number | null
userId: string | null
token: string | null
createdAt: Date | null
updatedAt: Date | null
@@ -56,7 +46,7 @@ export type UserMaxAggregateOutputType = {
email: string | null
emailVerified: Date | null
image: string | null
userId: number | null
userId: string | null
token: string | null
createdAt: Date | null
updatedAt: Date | null
@@ -78,14 +68,6 @@ export type UserCountAggregateOutputType = {
}
export type UserAvgAggregateInputType = {
userId?: true
}
export type UserSumAggregateInputType = {
userId?: true
}
export type UserMinAggregateInputType = {
id?: true
permissions?: true
@@ -164,18 +146,6 @@ export type UserAggregateArgs<ExtArgs extends runtime.Types.Extensions.InternalA
* Count returned Users
**/
_count?: true | UserCountAggregateInputType
/**
* {@link https://www.prisma.io/docs/concepts/components/prisma-client/aggregations Aggregation Docs}
*
* Select which fields to average
**/
_avg?: UserAvgAggregateInputType
/**
* {@link https://www.prisma.io/docs/concepts/components/prisma-client/aggregations Aggregation Docs}
*
* Select which fields to sum
**/
_sum?: UserSumAggregateInputType
/**
* {@link https://www.prisma.io/docs/concepts/components/prisma-client/aggregations Aggregation Docs}
*
@@ -209,8 +179,6 @@ export type UserGroupByArgs<ExtArgs extends runtime.Types.Extensions.InternalArg
take?: number
skip?: number
_count?: UserCountAggregateInputType | true
_avg?: UserAvgAggregateInputType
_sum?: UserSumAggregateInputType
_min?: UserMinAggregateInputType
_max?: UserMaxAggregateInputType
}
@@ -223,13 +191,11 @@ export type UserGroupByOutputType = {
email: string
emailVerified: Date | null
image: string | null
userId: number
userId: string
token: string | null
createdAt: Date
updatedAt: Date
_count: UserCountAggregateOutputType | null
_avg: UserAvgAggregateOutputType | null
_sum: UserSumAggregateOutputType | null
_min: UserMinAggregateOutputType | null
_max: UserMaxAggregateOutputType | null
}
@@ -260,7 +226,7 @@ export type UserWhereInput = {
email?: Prisma.StringFilter<"User"> | string
emailVerified?: Prisma.DateTimeNullableFilter<"User"> | Date | string | null
image?: Prisma.StringNullableFilter<"User"> | string | null
userId?: Prisma.IntFilter<"User"> | number
userId?: Prisma.StringFilter<"User"> | string
token?: Prisma.StringNullableFilter<"User"> | string | null
createdAt?: Prisma.DateTimeFilter<"User"> | Date | string
updatedAt?: Prisma.DateTimeFilter<"User"> | Date | string
@@ -288,7 +254,7 @@ export type UserWhereUniqueInput = Prisma.AtLeast<{
id?: string
login?: string
email?: string
userId?: number
userId?: string
AND?: Prisma.UserWhereInput | Prisma.UserWhereInput[]
OR?: Prisma.UserWhereInput[]
NOT?: Prisma.UserWhereInput | Prisma.UserWhereInput[]
@@ -316,10 +282,8 @@ export type UserOrderByWithAggregationInput = {
createdAt?: Prisma.SortOrder
updatedAt?: Prisma.SortOrder
_count?: Prisma.UserCountOrderByAggregateInput
_avg?: Prisma.UserAvgOrderByAggregateInput
_max?: Prisma.UserMaxOrderByAggregateInput
_min?: Prisma.UserMinOrderByAggregateInput
_sum?: Prisma.UserSumOrderByAggregateInput
}
export type UserScalarWhereWithAggregatesInput = {
@@ -333,7 +297,7 @@ export type UserScalarWhereWithAggregatesInput = {
email?: Prisma.StringWithAggregatesFilter<"User"> | string
emailVerified?: Prisma.DateTimeNullableWithAggregatesFilter<"User"> | Date | string | null
image?: Prisma.StringNullableWithAggregatesFilter<"User"> | string | null
userId?: Prisma.IntWithAggregatesFilter<"User"> | number
userId?: Prisma.StringWithAggregatesFilter<"User"> | string
token?: Prisma.StringNullableWithAggregatesFilter<"User"> | string | null
createdAt?: Prisma.DateTimeWithAggregatesFilter<"User"> | Date | string
updatedAt?: Prisma.DateTimeWithAggregatesFilter<"User"> | Date | string
@@ -347,7 +311,7 @@ export type UserCreateInput = {
email: string
emailVerified?: Date | string | null
image?: string | null
userId: number
userId: string
token?: string | null
createdAt?: Date | string
updatedAt?: Date | string
@@ -363,7 +327,7 @@ export type UserUncheckedCreateInput = {
email: string
emailVerified?: Date | string | null
image?: string | null
userId: number
userId: string
token?: string | null
createdAt?: Date | string
updatedAt?: Date | string
@@ -379,7 +343,7 @@ export type UserUpdateInput = {
email?: Prisma.StringFieldUpdateOperationsInput | string
emailVerified?: Prisma.NullableDateTimeFieldUpdateOperationsInput | Date | string | null
image?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
userId?: Prisma.IntFieldUpdateOperationsInput | number
userId?: Prisma.StringFieldUpdateOperationsInput | string
token?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string
updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string
@@ -395,7 +359,7 @@ export type UserUncheckedUpdateInput = {
email?: Prisma.StringFieldUpdateOperationsInput | string
emailVerified?: Prisma.NullableDateTimeFieldUpdateOperationsInput | Date | string | null
image?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
userId?: Prisma.IntFieldUpdateOperationsInput | number
userId?: Prisma.StringFieldUpdateOperationsInput | string
token?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string
updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string
@@ -411,7 +375,7 @@ export type UserCreateManyInput = {
email: string
emailVerified?: Date | string | null
image?: string | null
userId: number
userId: string
token?: string | null
createdAt?: Date | string
updatedAt?: Date | string
@@ -425,7 +389,7 @@ export type UserUpdateManyMutationInput = {
email?: Prisma.StringFieldUpdateOperationsInput | string
emailVerified?: Prisma.NullableDateTimeFieldUpdateOperationsInput | Date | string | null
image?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
userId?: Prisma.IntFieldUpdateOperationsInput | number
userId?: Prisma.StringFieldUpdateOperationsInput | string
token?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string
updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string
@@ -439,7 +403,7 @@ export type UserUncheckedUpdateManyInput = {
email?: Prisma.StringFieldUpdateOperationsInput | string
emailVerified?: Prisma.NullableDateTimeFieldUpdateOperationsInput | Date | string | null
image?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
userId?: Prisma.IntFieldUpdateOperationsInput | number
userId?: Prisma.StringFieldUpdateOperationsInput | string
token?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string
updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string
@@ -464,10 +428,6 @@ export type UserCountOrderByAggregateInput = {
updatedAt?: Prisma.SortOrder
}
export type UserAvgOrderByAggregateInput = {
userId?: Prisma.SortOrder
}
export type UserMaxOrderByAggregateInput = {
id?: Prisma.SortOrder
permissions?: Prisma.SortOrder
@@ -496,10 +456,6 @@ export type UserMinOrderByAggregateInput = {
updatedAt?: Prisma.SortOrder
}
export type UserSumOrderByAggregateInput = {
userId?: Prisma.SortOrder
}
export type UserListRelationFilter = {
every?: Prisma.UserWhereInput
some?: Prisma.UserWhereInput
@@ -528,14 +484,6 @@ export type NullableStringFieldUpdateOperationsInput = {
set?: string | null
}
export type IntFieldUpdateOperationsInput = {
set?: number
increment?: number
decrement?: number
multiply?: number
divide?: number
}
export type UserCreateNestedManyWithoutRolesInput = {
create?: Prisma.XOR<Prisma.UserCreateWithoutRolesInput, Prisma.UserUncheckedCreateWithoutRolesInput> | Prisma.UserCreateWithoutRolesInput[] | Prisma.UserUncheckedCreateWithoutRolesInput[]
connectOrCreate?: Prisma.UserCreateOrConnectWithoutRolesInput | Prisma.UserCreateOrConnectWithoutRolesInput[]
@@ -582,7 +530,7 @@ export type UserCreateWithoutSessionsInput = {
email: string
emailVerified?: Date | string | null
image?: string | null
userId: number
userId: string
token?: string | null
createdAt?: Date | string
updatedAt?: Date | string
@@ -597,7 +545,7 @@ export type UserUncheckedCreateWithoutSessionsInput = {
email: string
emailVerified?: Date | string | null
image?: string | null
userId: number
userId: string
token?: string | null
createdAt?: Date | string
updatedAt?: Date | string
@@ -628,7 +576,7 @@ export type UserUpdateWithoutSessionsInput = {
email?: Prisma.StringFieldUpdateOperationsInput | string
emailVerified?: Prisma.NullableDateTimeFieldUpdateOperationsInput | Date | string | null
image?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
userId?: Prisma.IntFieldUpdateOperationsInput | number
userId?: Prisma.StringFieldUpdateOperationsInput | string
token?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string
updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string
@@ -643,7 +591,7 @@ export type UserUncheckedUpdateWithoutSessionsInput = {
email?: Prisma.StringFieldUpdateOperationsInput | string
emailVerified?: Prisma.NullableDateTimeFieldUpdateOperationsInput | Date | string | null
image?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
userId?: Prisma.IntFieldUpdateOperationsInput | number
userId?: Prisma.StringFieldUpdateOperationsInput | string
token?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string
updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string
@@ -658,7 +606,7 @@ export type UserCreateWithoutRolesInput = {
email: string
emailVerified?: Date | string | null
image?: string | null
userId: number
userId: string
token?: string | null
createdAt?: Date | string
updatedAt?: Date | string
@@ -673,7 +621,7 @@ export type UserUncheckedCreateWithoutRolesInput = {
email: string
emailVerified?: Date | string | null
image?: string | null
userId: number
userId: string
token?: string | null
createdAt?: Date | string
updatedAt?: Date | string
@@ -712,7 +660,7 @@ export type UserScalarWhereInput = {
email?: Prisma.StringFilter<"User"> | string
emailVerified?: Prisma.DateTimeNullableFilter<"User"> | Date | string | null
image?: Prisma.StringNullableFilter<"User"> | string | null
userId?: Prisma.IntFilter<"User"> | number
userId?: Prisma.StringFilter<"User"> | string
token?: Prisma.StringNullableFilter<"User"> | string | null
createdAt?: Prisma.DateTimeFilter<"User"> | Date | string
updatedAt?: Prisma.DateTimeFilter<"User"> | Date | string
@@ -726,7 +674,7 @@ export type UserUpdateWithoutRolesInput = {
email?: Prisma.StringFieldUpdateOperationsInput | string
emailVerified?: Prisma.NullableDateTimeFieldUpdateOperationsInput | Date | string | null
image?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
userId?: Prisma.IntFieldUpdateOperationsInput | number
userId?: Prisma.StringFieldUpdateOperationsInput | string
token?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string
updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string
@@ -741,7 +689,7 @@ export type UserUncheckedUpdateWithoutRolesInput = {
email?: Prisma.StringFieldUpdateOperationsInput | string
emailVerified?: Prisma.NullableDateTimeFieldUpdateOperationsInput | Date | string | null
image?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
userId?: Prisma.IntFieldUpdateOperationsInput | number
userId?: Prisma.StringFieldUpdateOperationsInput | string
token?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string
updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string
@@ -756,7 +704,7 @@ export type UserUncheckedUpdateManyWithoutRolesInput = {
email?: Prisma.StringFieldUpdateOperationsInput | string
emailVerified?: Prisma.NullableDateTimeFieldUpdateOperationsInput | Date | string | null
image?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
userId?: Prisma.IntFieldUpdateOperationsInput | number
userId?: Prisma.StringFieldUpdateOperationsInput | string
token?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string
updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string
@@ -884,7 +832,7 @@ export type $UserPayload<ExtArgs extends runtime.Types.Extensions.InternalArgs =
email: string
emailVerified: Date | null
image: string | null
userId: number
userId: string
token: string | null
createdAt: Date
updatedAt: Date
@@ -1320,7 +1268,7 @@ export interface UserFieldRefs {
readonly email: Prisma.FieldRef<"User", 'String'>
readonly emailVerified: Prisma.FieldRef<"User", 'DateTime'>
readonly image: Prisma.FieldRef<"User", 'String'>
readonly userId: Prisma.FieldRef<"User", 'Int'>
readonly userId: Prisma.FieldRef<"User", 'String'>
readonly token: Prisma.FieldRef<"User", 'String'>
readonly createdAt: Prisma.FieldRef<"User", 'DateTime'>
readonly updatedAt: Prisma.FieldRef<"User", 'DateTime'>
+2
View File
@@ -24,9 +24,11 @@
"utils:gen_private_keys": "bun ./utils/genPrivateKeys"
},
"dependencies": {
"@azure/msal-node": "^5.0.2",
"@discordjs/collection": "^2.1.1",
"@duxcore/eventra": "^1.1.0",
"@prisma/adapter-pg": "^7.3.0",
"@prisma/client": "^7.3.0",
"cors": "^2.8.6",
"cuid": "^3.0.0",
"hono": "^4.11.5",
@@ -0,0 +1,76 @@
-- CreateTable
CREATE TABLE "Session" (
"id" TEXT NOT NULL,
"sessionKey" TEXT NOT NULL,
"userId" TEXT NOT NULL,
"expires" TIMESTAMP(3) NOT NULL,
"refreshTokenGenerated" BOOLEAN NOT NULL DEFAULT false,
"refreshedAt" TIMESTAMP(3),
"invalidatedAt" TIMESTAMP(3),
CONSTRAINT "Session_pkey" PRIMARY KEY ("id")
);
-- CreateTable
CREATE TABLE "User" (
"id" TEXT NOT NULL,
"permissions" TEXT,
"login" TEXT NOT NULL,
"name" TEXT,
"email" TEXT NOT NULL,
"emailVerified" TIMESTAMP(3),
"image" TEXT,
"userId" TEXT NOT NULL,
"token" TEXT,
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" TIMESTAMP(3) NOT NULL,
CONSTRAINT "User_pkey" PRIMARY KEY ("id")
);
-- CreateTable
CREATE TABLE "Role" (
"id" TEXT NOT NULL,
"title" TEXT NOT NULL,
"moniker" TEXT NOT NULL,
"permissions" TEXT NOT NULL,
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" TIMESTAMP(3) NOT NULL,
CONSTRAINT "Role_pkey" PRIMARY KEY ("id")
);
-- CreateTable
CREATE TABLE "_RoleToUser" (
"A" TEXT NOT NULL,
"B" TEXT NOT NULL,
CONSTRAINT "_RoleToUser_AB_pkey" PRIMARY KEY ("A","B")
);
-- CreateIndex
CREATE UNIQUE INDEX "Session_sessionKey_key" ON "Session"("sessionKey");
-- CreateIndex
CREATE UNIQUE INDEX "User_login_key" ON "User"("login");
-- CreateIndex
CREATE UNIQUE INDEX "User_email_key" ON "User"("email");
-- CreateIndex
CREATE UNIQUE INDEX "User_userId_key" ON "User"("userId");
-- CreateIndex
CREATE UNIQUE INDEX "Role_moniker_key" ON "Role"("moniker");
-- CreateIndex
CREATE INDEX "_RoleToUser_B_index" ON "_RoleToUser"("B");
-- AddForeignKey
ALTER TABLE "Session" ADD CONSTRAINT "Session_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE CASCADE ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "_RoleToUser" ADD CONSTRAINT "_RoleToUser_A_fkey" FOREIGN KEY ("A") REFERENCES "Role"("id") ON DELETE CASCADE ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "_RoleToUser" ADD CONSTRAINT "_RoleToUser_B_fkey" FOREIGN KEY ("B") REFERENCES "User"("id") ON DELETE CASCADE ON UPDATE CASCADE;
+3
View File
@@ -0,0 +1,3 @@
# Please do not edit this file manually
# It should be added in your version-control system (e.g., Git)
provider = "postgresql"
+1 -1
View File
@@ -34,7 +34,7 @@ model User {
emailVerified DateTime?
image String?
userId Int @unique
userId String @unique
token String?
sessions Session[]
-5
View File
@@ -1,5 +0,0 @@
node_modules
# Keep environment variables out of version control
.env
/generated/prisma
+36
View File
@@ -0,0 +1,36 @@
import { Hono } from "hono/tiny";
import { createRoute } from "../../modules/api-utils/createRoute";
import * as msal from "@azure/msal-node";
import { msalClient } from "../../constants";
import { users } from "../../managers/users";
/* /v1/authRedirect */
export default createRoute("get", ["/"], async (c) => {
c.status(200);
console.log("Query", c.req.query());
const tokenRequest: msal.AuthorizationCodeRequest = {
code: c.req.query().code as string,
scopes: ["user.read"],
redirectUri: "http://localhost:3000/v1/auth/redirect",
};
const authResult = await msalClient.acquireTokenByCode(tokenRequest);
await users.authenticate(authResult);
// This closes the window because duh
return c.html(`
<script>
window.close();
</script>
`);
/* return c.json({
status: 200,
message: "Auth Redirect Endpoint",
data: authResult,
successful: true,
}); */
});
-12
View File
@@ -1,12 +0,0 @@
// This file was generated by Prisma, and assumes you run Prisma commands using `bun --bun run prisma [command]`.
import { defineConfig, env } from "prisma/config";
export default defineConfig({
schema: "prisma/schema.prisma",
migrations: {
path: "prisma/migrations",
},
datasource: {
url: env("DATABASE_URL"),
},
});
+1
View File
@@ -47,6 +47,7 @@ app.notFound((c) => {
});
v1.route("/teapot", teapot);
v1.route("/auth/redirect", await import("./auth/redirect").then(m => m.default));
app.route("/v1", v1);
+24 -12
View File
@@ -1,34 +1,46 @@
import { readFileSync } from "fs";
import { PrismaPg } from '@prisma/adapter-pg'
import { PrismaClient } from '../generated/prisma/client'
const connectionString = `${process.env.DATABASE_URL}`
const adapter = new PrismaPg({ connectionString })
import { PrismaPg } from "@prisma/adapter-pg";
import { Prisma, PrismaClient } from "../generated/prisma/client";
import * as msal from "@azure/msal-node";
const connectionString = `${process.env.DATABASE_URL}`;
const adapter = new PrismaPg({ connectionString });
interface EnvKey {
PORT: number;
};
PORT: number;
}
// ENV CONSTANTS
export const PORT = process.env.PORT;
export const prisma = new PrismaClient({ adapter })
export const prisma = new PrismaClient({ adapter });
export const sessionDuration = 30 * 24 * 60 * 60000;
export const accessTokenDuration = "10min";
export const refreshTokenDuration = "30d";
export const accessTokenPrivateKey = readFileSync(
`${import.meta.dir}/../.accessToken.key`
`${import.meta.dir}/../.accessToken.key`,
).toString();
export const refreshTokenPrivateKey = readFileSync(
`${import.meta.dir}/../.refreshToken.key`
`${import.meta.dir}/../.refreshToken.key`,
).toString();
export const permissionsPrivateKey = readFileSync(
`${import.meta.dir}/../.permissions.key`
`${import.meta.dir}/../.permissions.key`,
);
export const apiKeyTokenPrivateKey = readFileSync(
`${import.meta.dir}/../.apiKeyToken.key`
`${import.meta.dir}/../.apiKeyToken.key`,
);
// Microsoft Auth Constants
const msalConfig: msal.Configuration = {
auth: {
clientId: process.env.MICROSOFT_CLIENT_ID!,
authority: `https://login.microsoftonline.com/${process.env.MICROSOFT_TENANT_ID!}`,
clientSecret: process.env.MICROSOFT_CLIENT_SECRET!,
},
};
// MSAL Client Instance
export const msalClient = new msal.ConfidentialClientApplication(msalConfig);
+5 -16
View File
@@ -10,8 +10,6 @@ import { events } from "../modules/globalEvents";
import { RoleController } from "./RoleController";
import { roles } from "../managers/roles";
export default class UserController {
public id: string;
public name: string | null;
@@ -116,8 +114,8 @@ export default class UserController {
await Promise.all(
this._roles.map(async (v) =>
collection.set(v.id, await roles.fetch(v.id))
)
collection.set(v.id, await roles.fetch(v.id)),
),
);
return collection;
@@ -140,15 +138,6 @@ export default class UserController {
sessions: {
select: { id: true },
},
apiKeys: {
select: { id: true },
},
projects: {
select: { id: true },
},
services: {
select: { id: true },
},
},
});
@@ -158,7 +147,7 @@ export default class UserController {
(v) =>
`resource.${v}.[${(resources![v] as { id: string }[])
.map((o) => o.id)
.join(",")}].user.${this.id}.implicit`
.join(",")}].user.${this.id}.implicit`,
);
console.log(implicitPermissions);
@@ -190,8 +179,8 @@ export default class UserController {
roles: opts?.safeReturn
? undefined
: this._roles.size > 0
? this._roles.map((v) => v.moniker)
: undefined,
? this._roles.map((v) => v.moniker)
: undefined,
login: opts?.safeReturn ? undefined : this.login,
email: opts?.safeReturn ? undefined : this.email,
image: this.image,
+9 -9
View File
@@ -38,7 +38,7 @@ export const roles = {
if (checkMoniker)
throw new RoleError(
"Moniker is already taken.",
"Another role with this moniker already exists in the databse."
"Another role with this moniker already exists in the databse.",
);
const id = cuid();
@@ -76,7 +76,7 @@ export const roles = {
* @param identifier - Options for fetching a role.
* @returns {RoleController} - Role Controller
*/
async fetch(identifier:string, opt?: { requestingUser?: UserController }) {
async fetch(identifier: string, opt?: { requestingUser?: UserController }) {
const roleData = await prisma.role.findFirst({
where: { OR: [{ id: identifier }, { moniker: identifier }] },
include: {
@@ -98,11 +98,11 @@ export const roles = {
if (
opt?.requestingUser &&
!(await opt.requestingUser.hasPermission(
this._buildPermissionNode(roleData.id, "read")
this._buildPermissionNode(roleData.id, "read"),
))
)
throw new InsufficientPermission(
"You do not have permission to access this role."
"You do not have permission to access this role.",
);
const controller = new RoleController(roleData);
@@ -123,20 +123,20 @@ export const roles = {
include: { users: { include: { roles: true } } },
});
roles. map((v:any) => collection.set(v.id, new RoleController(v)));
roles.map((v: any) => collection.set(v.id, new RoleController(v)));
if (opt?.requestingUser) {
const permittedRoles = await Promise.all(
collection.map(async (v) =>
(await opt.requestingUser?.hasPermission(
this._buildPermissionNode(v.id, "read")
this._buildPermissionNode(v.id, "read"),
))
? v.id
: null
)
: null,
),
);
collection = collection.filter((v) =>
permittedRoles.filter((x) => x !== null).includes(v.id)
permittedRoles.filter((x) => x !== null).includes(v.id),
);
}
-2
View File
@@ -1,8 +1,6 @@
import {
prisma,
refreshTokenDuration,
sessionDuration,
accessTokenDuration,
accessTokenPrivateKey,
refreshTokenPrivateKey,
} from "../constants";
+23 -28
View File
@@ -1,7 +1,12 @@
import { ms } from "zod/locales";
import { User } from "../../generated/prisma/client";
import { prisma } from "../constants";
import { SessionTokensObject } from "../controllers/SessionController";
import UserController from "../controllers/UserController";
import { fetchMicrosoftUser } from "../modules/fetchMicrosoftUser";
import { events } from "../modules/globalEvents";
import { sessions } from "./sessions";
import * as msal from "@azure/msal-node";
export const users = {
/**
@@ -13,25 +18,22 @@ export const users = {
* @summary It creates a user if one doesn't exist and will supply a session id
*
* @async
* @param ghCode - The code supplied in the callback url of a GitHub oAuth transaction
* @param authRequest - The code supplied in the callback url of the Microsoft oAuth transaction
*/
/* async authenticate(ghCode: string): Promise<SessionTokensObject> {
const token = await ghApp.oauth.createToken({ code: ghCode }).catch((e) => {
throw new AuthenticationError("Invalid OAuth code...");
});
const userOK = await ghApp.oauth.getUserOctokit({
token: token.authentication.token,
});
const ghUser = await userOK.request("GET /user");
async authenticate(
authRequest: msal.AuthenticationResult,
): Promise<SessionTokensObject> {
let id = authRequest.uniqueId as string;
let user =
(await this.fetchUser({ userId: ghUser.data.id })) ??
(await this.createUser(token.authentication.token));
(await this.fetchUser({ userId: id })) ??
(await this.createUser(authRequest.accessToken));
const tokens = await sessions.create({ user });
events.emit("user:authenticated", { user, tokens });
return tokens;
}, */
},
/**
* Check to see if the user exists
@@ -59,8 +61,8 @@ export const users = {
id: string;
email: string;
login: string;
userId: number;
}>
userId: string;
}>,
) {
if (Object.keys(identifier).length == 0) return null;
const userData = await prisma.user.findFirst({
@@ -79,28 +81,21 @@ export const users = {
/**
* Create a new user
*
* This method will poll GitHub and get all the information on the user to then create the
* This method will poll Microsoft and get all the information on the user to then create the
* record in our database. On top of that it also pushes it into the user cache.
*
* @param token - The Github token provided by the auth method
* @param token - The Microsoft token provided by the auth method
* @returns {Promise<UserController>} The new user controller for the user
*/
async createUser(token: string): Promise<UserController> {
const ghUser = await (
await ghApp.oauth.getUserOctokit({ token })
).request("GET /user");
const emails = await (
await ghApp.oauth.getUserOctokit({ token })
).request("GET /user/emails");
const msData = await fetchMicrosoftUser(token);
const newUser = await prisma.user.create({
data: {
userId: ghUser.data.id,
email: emails.data[0].email,
image: ghUser.data.avatar_url,
name: ghUser.data.name,
login: ghUser.data.login,
userId: msData.id,
email: msData.mail,
name: `${msData.givenName} ${msData.surname}`,
login: msData.userPrincipalName,
token,
},
include: { roles: true },
+33
View File
@@ -0,0 +1,33 @@
import { MicrosoftGraphUser } from "../types/MSAuthTypes";
/**
* Fetch Microsoft User
*
* This function fetches user data from Microsoft Graph API using the provided access token.
* It makes a GET request to the `/me` endpoint and returns the user data in JSON format.
*
* @param accessToken - This is the access token provided by Microsoft.
* @returns - Raw API Data from Microsoft.
*/
export const fetchMicrosoftUser = async (
accessToken: string,
): Promise<MicrosoftGraphUser> => {
const graphEndpoint = "https://graph.microsoft.com/v1.0/me";
const response = await fetch(graphEndpoint, {
method: "GET",
headers: {
Authorization: `Bearer ${accessToken}`,
},
});
if (!response.ok) {
throw new Error(
`Graph request failed: ${response.status} ${response.statusText}`,
);
}
const data = (await response.json()) as MicrosoftGraphUser;
return data;
};
+14
View File
@@ -0,0 +1,14 @@
export interface MicrosoftGraphUser {
"@odata.context": string;
businessPhones: string[];
displayName: string;
givenName: string;
jobTitle: string | null;
mail: string;
mobilePhone: string | null;
officeLocation: string | null;
preferredLanguage: string | null;
surname: string;
userPrincipalName: string;
id: string;
}
+5 -1
View File
@@ -24,6 +24,10 @@
// Some stricter flags (disabled by default)
"noUnusedLocals": false,
"noUnusedParameters": false,
"noPropertyAccessFromIndexSignature": false
"noPropertyAccessFromIndexSignature": false,
"paths": {
"@prisma/client": ["./generated/prisma"]
}
}
}