Basic server setup
This commit is contained in:
parent
60af230a2d
commit
68273802cc
3
.gitignore
vendored
3
.gitignore
vendored
|
@ -2,7 +2,6 @@
|
|||
node_modules
|
||||
/dist
|
||||
|
||||
|
||||
# local env files
|
||||
.env.local
|
||||
.env.*.local
|
||||
|
@ -21,3 +20,5 @@ pnpm-debug.log*
|
|||
*.njsproj
|
||||
*.sln
|
||||
*.sw?
|
||||
|
||||
.env
|
||||
|
|
14
.prettierrc
Executable file
14
.prettierrc
Executable file
|
@ -0,0 +1,14 @@
|
|||
{
|
||||
"trailingComma": "none",
|
||||
"tabWidth": 2,
|
||||
"semi": false,
|
||||
"singleQuote": true,
|
||||
"bracketSpacing": true,
|
||||
"arrowParens": "avoid",
|
||||
"overrides": [
|
||||
{
|
||||
"files": "*.js, *.vue, *.css, *.scss",
|
||||
"excludeFiles": "**/dist/**, **/node_modules/**"
|
||||
}
|
||||
]
|
||||
}
|
33
README.md
33
README.md
|
@ -1,44 +1,17 @@
|
|||
# default
|
||||
# IFMS Password updater - Web
|
||||
|
||||
## Project setup
|
||||
|
||||
```
|
||||
# yarn
|
||||
yarn
|
||||
|
||||
# npm
|
||||
npm install
|
||||
|
||||
# pnpm
|
||||
pnpm install
|
||||
```
|
||||
|
||||
### Compiles and hot-reloads for development
|
||||
|
||||
```
|
||||
# yarn
|
||||
yarn dev
|
||||
|
||||
# npm
|
||||
npm run dev
|
||||
|
||||
# pnpm
|
||||
pnpm dev
|
||||
```
|
||||
npm run dev
|
||||
|
||||
### Compiles and minifies for production
|
||||
|
||||
```
|
||||
# yarn
|
||||
yarn build
|
||||
|
||||
# npm
|
||||
|
||||
npm run build
|
||||
|
||||
# pnpm
|
||||
pnpm build
|
||||
```
|
||||
|
||||
### Customize configuration
|
||||
|
||||
See [Configuration Reference](https://vitejs.dev/config/).
|
||||
|
|
75
package-lock.json
generated
75
package-lock.json
generated
|
@ -13,7 +13,9 @@
|
|||
"@trpc/server": "^10.44.1",
|
||||
"body-parser": "^1.20.2",
|
||||
"cors": "^2.8.5",
|
||||
"dotenv": "^16.3.1",
|
||||
"express": "^4.18.2",
|
||||
"ldapts": "^7.0.7",
|
||||
"roboto-fontface": "*",
|
||||
"vue": "^3.2.0",
|
||||
"vue-router": "^4.0.0",
|
||||
|
@ -589,6 +591,14 @@
|
|||
"node": ">=18.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/asn1": {
|
||||
"version": "0.2.4",
|
||||
"resolved": "https://registry.npmjs.org/@types/asn1/-/asn1-0.2.4.tgz",
|
||||
"integrity": "sha512-V91DSJ2l0h0gRhVP4oBfBzRBN9lAbPUkGDMCnwedqPKX2d84aAMc9CulOvxdw1f7DfEYx99afab+Rsm3e52jhA==",
|
||||
"dependencies": {
|
||||
"@types/node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/body-parser": {
|
||||
"version": "1.19.5",
|
||||
"resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.5.tgz",
|
||||
|
@ -663,7 +673,6 @@
|
|||
"version": "18.19.3",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.3.tgz",
|
||||
"integrity": "sha512-k5fggr14DwAytoA/t8rPrIz++lXK7/DqckthCmoZOKNsEbJkId4Z//BqgApXBUGrGddrigYa1oqheo/7YmW4rg==",
|
||||
"devOptional": true,
|
||||
"dependencies": {
|
||||
"undici-types": "~5.26.4"
|
||||
}
|
||||
|
@ -707,6 +716,11 @@
|
|||
"@types/node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/uuid": {
|
||||
"version": "9.0.7",
|
||||
"resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-9.0.7.tgz",
|
||||
"integrity": "sha512-WUtIVRUZ9i5dYXefDEAI7sh9/O7jGvHg7Df/5O/gtH3Yabe5odI3UWopVR1qbPXQtvOxWu3mM4XxlYeZtMWF4g=="
|
||||
},
|
||||
"node_modules/@types/webfontloader": {
|
||||
"version": "1.6.38",
|
||||
"resolved": "https://registry.npmjs.org/@types/webfontloader/-/webfontloader-1.6.38.tgz",
|
||||
|
@ -1235,6 +1249,14 @@
|
|||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"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",
|
||||
|
@ -1544,7 +1566,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"
|
||||
},
|
||||
|
@ -1617,6 +1638,17 @@
|
|||
"node": ">=6.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/dotenv": {
|
||||
"version": "16.3.1",
|
||||
"resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.3.1.tgz",
|
||||
"integrity": "sha512-IPzF4w4/Rd94bA9imS68tZBaYyBWSCE47V1RGuMrB94iyTOIEwRmVL2x/4An+6mETpLrKJ5hQkB8W4kFAadeIQ==",
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/motdotla/dotenv?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/ee-first": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
|
||||
|
@ -2568,6 +2600,22 @@
|
|||
"json-buffer": "3.0.1"
|
||||
}
|
||||
},
|
||||
"node_modules/ldapts": {
|
||||
"version": "7.0.7",
|
||||
"resolved": "https://registry.npmjs.org/ldapts/-/ldapts-7.0.7.tgz",
|
||||
"integrity": "sha512-c/W9jZJ2WiGiAIBnkzUmYkIw1d5jebfVfp+vpR9Z6xh4QXm+kwwaQbmHFJHKsW4OwFARdOaQ03H3fBky4+XcVg==",
|
||||
"dependencies": {
|
||||
"@types/asn1": ">=0.2.4",
|
||||
"@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/levn": {
|
||||
"version": "0.4.1",
|
||||
"resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz",
|
||||
|
@ -2743,8 +2791,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",
|
||||
|
@ -3471,6 +3518,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",
|
||||
|
@ -3657,8 +3709,7 @@
|
|||
"node_modules/undici-types": {
|
||||
"version": "5.26.5",
|
||||
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz",
|
||||
"integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==",
|
||||
"devOptional": true
|
||||
"integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA=="
|
||||
},
|
||||
"node_modules/unpipe": {
|
||||
"version": "1.0.0",
|
||||
|
@ -3701,6 +3752,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",
|
||||
|
|
|
@ -19,7 +19,9 @@
|
|||
"@trpc/server": "^10.44.1",
|
||||
"body-parser": "^1.20.2",
|
||||
"cors": "^2.8.5",
|
||||
"dotenv": "^16.3.1",
|
||||
"express": "^4.18.2",
|
||||
"ldapts": "^7.0.7",
|
||||
"roboto-fontface": "*",
|
||||
"vue": "^3.2.0",
|
||||
"vue-router": "^4.0.0",
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
import "dotenv/config";
|
||||
|
||||
import { server } from "./server";
|
||||
|
||||
process.env.NODE_TLS_REJECT_UNAUTHORIZED = "0";
|
||||
|
|
12
src/server/lib/encodePassword.ts
Normal file
12
src/server/lib/encodePassword.ts
Normal file
|
@ -0,0 +1,12 @@
|
|||
export function encodePassword(password: string): string {
|
||||
let encodedPassword = "";
|
||||
password = '"' + password + '"';
|
||||
|
||||
for (let i = 0; i < password.length; i++)
|
||||
encodedPassword += String.fromCharCode(
|
||||
password.charCodeAt(i) & 0xff,
|
||||
(password.charCodeAt(i) >>> 8) & 0xff
|
||||
);
|
||||
|
||||
return encodedPassword;
|
||||
}
|
66
src/server/lib/updatePassword.ts
Normal file
66
src/server/lib/updatePassword.ts
Normal file
|
@ -0,0 +1,66 @@
|
|||
import { Client, Change, Attribute } from 'ldapts'
|
||||
import { encodePassword } from './encodePassword'
|
||||
|
||||
const ldapClient = new Client({
|
||||
url: process.env.LDAP_URL || 'ldap://10.1.0.16'
|
||||
})
|
||||
|
||||
const bindUser = process.env.AD_BIND_USER || ''
|
||||
const bindPassword = process.env.AD_BIND_PASSWORD || ''
|
||||
const baseDN = process.env.AD_BASE_DN || ''
|
||||
|
||||
async function getUserDN(username: string): Promise<string> {
|
||||
try {
|
||||
await ldapClient.bind(bindUser, bindPassword)
|
||||
|
||||
const { searchEntries } = await ldapClient.search(baseDN, {
|
||||
scope: 'sub',
|
||||
attributes: ['dn'],
|
||||
filter: `(sAMAccountName=${username})`
|
||||
})
|
||||
|
||||
return searchEntries[0]?.dn
|
||||
} catch (err) {
|
||||
console.error(err)
|
||||
} finally {
|
||||
await ldapClient.unbind()
|
||||
}
|
||||
|
||||
throw new Error('User not found')
|
||||
}
|
||||
|
||||
export async function updatePassword({
|
||||
username,
|
||||
password,
|
||||
newPassword
|
||||
}: {
|
||||
username: string
|
||||
password: string
|
||||
newPassword: string
|
||||
}) {
|
||||
try {
|
||||
const userDN = await getUserDN(username)
|
||||
await ldapClient.bind(userDN, password)
|
||||
|
||||
await ldapClient.modify(userDN, [
|
||||
new Change({
|
||||
operation: 'delete',
|
||||
modification: new Attribute({
|
||||
type: 'unicodePwd',
|
||||
values: [encodePassword(password)]
|
||||
})
|
||||
}),
|
||||
new Change({
|
||||
operation: 'add',
|
||||
modification: new Attribute({
|
||||
type: 'unicodePwd',
|
||||
values: [encodePassword(newPassword)]
|
||||
})
|
||||
})
|
||||
])
|
||||
} catch (err) {
|
||||
console.error(err)
|
||||
} finally {
|
||||
await ldapClient.unbind()
|
||||
}
|
||||
}
|
|
@ -1,16 +1,24 @@
|
|||
import { initTRPC, TRPCError } from "@trpc/server";
|
||||
import * as trpcExpress from "@trpc/server/adapters/express";
|
||||
|
||||
// import { z } from "zod";
|
||||
import { z } from "zod";
|
||||
|
||||
export const t = initTRPC.create();
|
||||
export const { procedure, router } = initTRPC.create();
|
||||
|
||||
const { query, mutation, input } = t.procedure;
|
||||
const { query, mutation, input } = procedure;
|
||||
|
||||
export const appRouter = t.router({
|
||||
export const appRouter = router({
|
||||
hello: query(async () => {
|
||||
return "Hello World!";
|
||||
}),
|
||||
|
||||
updatePassword: input(
|
||||
z.object({
|
||||
username: z.string(),
|
||||
password: z.string(),
|
||||
newPassword: z.string().min(8),
|
||||
})
|
||||
).mutation(async () => {}),
|
||||
});
|
||||
|
||||
// export type definition of API
|
||||
|
|
Loading…
Reference in New Issue
Block a user