gluestick/src/ldap.ts

105 lines
2.5 KiB
TypeScript

import { ApolloClient, InMemoryCache } from "@apollo/client";
import { Client } from "ldapts";
import { setInterval } from "timers/promises";
import { gql } from "./__generated__";
type LLDAPAuthResponse = {
token: string;
refreshToken: string;
};
type LLDAPRefreshResponse = {
token: string;
};
let ldapClient: Client | null = null;
async function getLdapClient() {
if (ldapClient === null) {
ldapClient = new Client({
url: `ldap://${process.env.LDAP_HOST}:3890`
});
await ldapClient.bind(
process.env.LDAP_BIND_USER,
process.env.LDAP_BIND_PASSWORD
);
}
return ldapClient;
}
let authResponse: LLDAPAuthResponse | null = null;
async function regenAuthToken() {
if (authResponse !== null) {
const url = `http://${process.env.LDAP_HOST}:17170/auth/refresh`;
const req = await fetch(url, {
headers: {
"Refresh-Token": authResponse.refreshToken
}
});
const res: LLDAPRefreshResponse = await req.json();
authResponse.token = res.token;
} else {
const url = `http://${process.env.LDAP_HOST}:17170/auth/simple/login`;
const req = await fetch(url, {
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify({
username: process.env.LDAP_BIND_USER,
password: process.env.LDAP_BIND_PASSWORD
})
});
authResponse = await req.json();
}
// valid for one day, so refresh every 12 hours
setTimeout(regenAuthToken, 12 * 60 * 60 * 1000);
}
async function getAuthToken() {
if (authResponse === null) await regenAuthToken();
return authResponse!.token;
}
let graphQLClient: ApolloClient<any> | null = null;
let graphQLCache = new InMemoryCache();
let graphQLAuthToken: string | null = null;
async function getGraphQLClient() {
if (authResponse === null) {
await regenAuthToken();
graphQLAuthToken = authResponse!.token;
}
// We keep track of the auth token we used in the client, so we can
// recreate it when it expires/refreshes
if (graphQLClient === null || graphQLAuthToken !== authResponse!.token) {
graphQLClient = new ApolloClient({
uri: `http://${process.env.LDAP_HOST}:17170/api/graphql`,
cache: graphQLCache,
headers: {
Authorization: `Bearer ${authResponse!.token}`
}
});
}
return graphQLClient;
}
export async function getUsers() {
const client = await getGraphQLClient();
const query = await client.query({
query: gql(`
query GetUsers {
users {
id
}
}
`)
});
return query.data.users;
}