diff --git a/package-lock.json b/package-lock.json index da6daaa..7612c11 100644 --- a/package-lock.json +++ b/package-lock.json @@ -16,6 +16,7 @@ "body-parser": "^1.20.2", "cors": "^2.8.5", "express": "^4.18.2", + "ldapts": "^7.0.5", "roboto-fontface": "*", "vue": "^3.2.0", "vue-router": "^4.0.0", @@ -557,6 +558,14 @@ "https://trpc.io/sponsor" ] }, + "node_modules/@types/asn1": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/@types/asn1/-/asn1-0.2.2.tgz", + "integrity": "sha512-bqqktGboBnvFX4FzmkHzxoVgFiPJu5xnJHTK3rnksvhR+jk70pmQCxz4FLqLX6DAPXHVY/eY5ZnoJ552p6JORA==", + "dependencies": { + "@types/node": "*" + } + }, "node_modules/@types/body-parser": { "version": "1.19.3", "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.3.tgz", @@ -648,6 +657,11 @@ "@types/node": "*" } }, + "node_modules/@types/uuid": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-9.0.5.tgz", + "integrity": "sha512-xfHdwa1FMJ082prjSJpoEI57GZITiQz10r3vEJCHa2khEFQjKy91aWKz6+zybzssCvXUwE1LQWgWVwZ4nYUvHQ==" + }, "node_modules/@types/webfontloader": { "version": "1.6.35", "resolved": "https://registry.npmjs.org/@types/webfontloader/-/webfontloader-1.6.35.tgz", @@ -890,6 +904,14 @@ "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==" }, + "node_modules/asn1": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.6.tgz", + "integrity": "sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==", + "dependencies": { + "safer-buffer": "~2.1.0" + } + }, "node_modules/balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", @@ -1149,7 +1171,6 @@ "version": "4.3.4", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "devOptional": true, "dependencies": { "ms": "2.1.2" }, @@ -1646,6 +1667,23 @@ "@pkgjs/parseargs": "^0.11.0" } }, + "node_modules/ldapts": { + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/ldapts/-/ldapts-7.0.5.tgz", + "integrity": "sha512-TIHmcI4GLJY3ZQYNHYS+YMOHoDcXuYi3/gNhXT894hpx4ekQegu8sgBfm2yrmgS3d6K1BHzCOmN3ik/Qqj65dA==", + "dependencies": { + "@types/asn1": ">=0.2.1", + "@types/node": ">=18", + "@types/uuid": ">=9", + "asn1": "~0.2.6", + "debug": "~4.3.4", + "strict-event-emitter-types": "~2.0.0", + "uuid": "~9.0.1" + }, + "engines": { + "node": ">=18" + } + }, "node_modules/locate-path": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", @@ -1780,8 +1818,7 @@ "node_modules/ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "devOptional": true + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" }, "node_modules/muggle-string": { "version": "0.3.1", @@ -2286,6 +2323,11 @@ "node": ">= 0.8" } }, + "node_modules/strict-event-emitter-types": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strict-event-emitter-types/-/strict-event-emitter-types-2.0.0.tgz", + "integrity": "sha512-Nk/brWYpD85WlOgzw5h173aci0Teyv8YdIAEtV+N88nDB0dLlazZyJMIsN6eo1/AR61l+p6CJTG1JIyFaoNEEA==" + }, "node_modules/string-width": { "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", @@ -2455,6 +2497,18 @@ "node": ">= 0.4.0" } }, + "node_modules/uuid": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", + "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "bin": { + "uuid": "dist/bin/uuid" + } + }, "node_modules/vary": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", @@ -3006,6 +3060,14 @@ "resolved": "https://registry.npmjs.org/@trpc/server/-/server-10.38.5.tgz", "integrity": "sha512-J0d2Y3Gpt2bMohOshPBfuzDqVrPaE3OKEDtJYgTmLk5t1pZy3kXHQep4rP2LEIr+ELbmkelhcrSvvFLA+4/w/Q==" }, + "@types/asn1": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/@types/asn1/-/asn1-0.2.2.tgz", + "integrity": "sha512-bqqktGboBnvFX4FzmkHzxoVgFiPJu5xnJHTK3rnksvhR+jk70pmQCxz4FLqLX6DAPXHVY/eY5ZnoJ552p6JORA==", + "requires": { + "@types/node": "*" + } + }, "@types/body-parser": { "version": "1.19.3", "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.3.tgz", @@ -3097,6 +3159,11 @@ "@types/node": "*" } }, + "@types/uuid": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-9.0.5.tgz", + "integrity": "sha512-xfHdwa1FMJ082prjSJpoEI57GZITiQz10r3vEJCHa2khEFQjKy91aWKz6+zybzssCvXUwE1LQWgWVwZ4nYUvHQ==" + }, "@types/webfontloader": { "version": "1.6.35", "resolved": "https://registry.npmjs.org/@types/webfontloader/-/webfontloader-1.6.35.tgz", @@ -3306,6 +3373,14 @@ "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==" }, + "asn1": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.6.tgz", + "integrity": "sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==", + "requires": { + "safer-buffer": "~2.1.0" + } + }, "balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", @@ -3512,7 +3587,6 @@ "version": "4.3.4", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "devOptional": true, "requires": { "ms": "2.1.2" } @@ -3882,6 +3956,20 @@ "@pkgjs/parseargs": "^0.11.0" } }, + "ldapts": { + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/ldapts/-/ldapts-7.0.5.tgz", + "integrity": "sha512-TIHmcI4GLJY3ZQYNHYS+YMOHoDcXuYi3/gNhXT894hpx4ekQegu8sgBfm2yrmgS3d6K1BHzCOmN3ik/Qqj65dA==", + "requires": { + "@types/asn1": ">=0.2.1", + "@types/node": ">=18", + "@types/uuid": ">=9", + "asn1": "~0.2.6", + "debug": "~4.3.4", + "strict-event-emitter-types": "~2.0.0", + "uuid": "~9.0.1" + } + }, "locate-path": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", @@ -3974,8 +4062,7 @@ "ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "devOptional": true + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" }, "muggle-string": { "version": "0.3.1", @@ -4325,6 +4412,11 @@ "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==" }, + "strict-event-emitter-types": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strict-event-emitter-types/-/strict-event-emitter-types-2.0.0.tgz", + "integrity": "sha512-Nk/brWYpD85WlOgzw5h173aci0Teyv8YdIAEtV+N88nDB0dLlazZyJMIsN6eo1/AR61l+p6CJTG1JIyFaoNEEA==" + }, "string-width": { "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", @@ -4440,6 +4532,11 @@ "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==" }, + "uuid": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", + "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==" + }, "vary": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", diff --git a/package.json b/package.json index 3abbe0d..82627b3 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,7 @@ "clean": "rimraf ./dist", "dev:web": "vite --host", "dev:server": "tsx --watch ./src/server/index.ts", - "dev": "concurrently --kill-others -n Server,Web -c bgGreen,bgBlue \"npm run dev:server\" \"npm run dev:web\"", + "dev": "NODE_ENV=development concurrently --kill-others -n Server,Web -c bgGreen,bgBlue \"npm run dev:server\" \"npm run dev:web\"", "build:web": "vue-tsc --noEmit && vite build", "build:server": "tsc --project tsconfig.server.json", "build": "npm run clean && npm run build:web && npm run build:server", @@ -22,6 +22,7 @@ "body-parser": "^1.20.2", "cors": "^2.8.5", "express": "^4.18.2", + "ldapts": "^7.0.5", "roboto-fontface": "*", "vue": "^3.2.0", "vue-router": "^4.0.0", diff --git a/src/server/classes/LdapLogin.ts b/src/server/classes/LdapLogin.ts new file mode 100644 index 0000000..65da40c --- /dev/null +++ b/src/server/classes/LdapLogin.ts @@ -0,0 +1,32 @@ +import { Client } from 'ldapts' + +export class LdapLogin implements Login { + constructor( + private client: Client, + private domain: string, + private searchDN: string + ) {} + + async login(username: string, password: string): Promise { + try { + await this.client.bind(`${this.domain}\\${username}`, password) + + const search = await this.client.search(this.searchDN, { + scope: 'sub', + filter: `(sAMAccountName=${username})`, + attributes: ['displayName'] + }) + + return { + username, + displayName: search.searchEntries[0].displayName as string + } + } catch (error: any) { + console.log('Error:', error) + + throw new Error(`Login failed: ${error.message}`) + } finally { + await this.client.unbind() + } + } +} diff --git a/src/server/interfaces/Login.ts b/src/server/interfaces/Login.ts new file mode 100644 index 0000000..72fc948 --- /dev/null +++ b/src/server/interfaces/Login.ts @@ -0,0 +1,9 @@ +type LoginResult = { + username: string + displayName: string + jwt?: string +} + +interface Login { + login(username: string, password: string): Promise +} diff --git a/src/server/lib/login.ts b/src/server/lib/login.ts index fb5561a..32e53a2 100644 --- a/src/server/lib/login.ts +++ b/src/server/lib/login.ts @@ -1,4 +1,17 @@ -export function login(username: string, password: string) { - console.log('Login', username, password) - return 'ok' +import { Client } from 'ldapts' + +import { LdapLogin } from '../classes/LdapLogin' + +export async function login(username: string, password: string) { + const ldapClient = new Client({ + url: 'ldap://10.7.0.18' + }) + + const ldapLogin = new LdapLogin(ldapClient, 'ifms', 'DC=ifms,DC=edu,DC=br') + + const result = await ldapLogin.login(username, password) + + console.log('Login result:', result) + + return result } diff --git a/src/server/trpc.ts b/src/server/trpc.ts index 348aace..c7f4716 100644 --- a/src/server/trpc.ts +++ b/src/server/trpc.ts @@ -18,12 +18,14 @@ export const appRouter = t.router({ const ip = ctx.ip.split(':').slice(-1)[0] console.log(`IP: ${ip}`) + if (process.env.NODE_ENV === 'development') return '10.7.16.254' + return ip }), login: t.procedure .input(z.object({ username: z.string(), password: z.string() })) .mutation(async ({ input }) => { - return login(input.username, input.password) + return await login(input.username, input.password) }) }) diff --git a/src/web/components/LoginForm.vue b/src/web/components/LoginForm.vue index 72c6a59..5f6cdda 100644 --- a/src/web/components/LoginForm.vue +++ b/src/web/components/LoginForm.vue @@ -1,7 +1,19 @@