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 | 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; }