Skip to content

Commit 399f3d0

Browse files
cowboydtaras
andauthored
Prep API and README for testing article (#200)
* Prep API and README for testing article There is an article in the works that references the LDAP simulator as a solution to testing a backstage server. Unfortunately, we don't have a README, and so the [NPM package homepage](https://www.npmjs.com/package/@simulacrum/ldap-simulator/v/0.4.0) looks quite bad. This adds a basic readme and shows how to start an LDAP server from both a vanilla JavaScript context as well from an Effection context. There is a third way, which is via a simulacrum server, but this does not add that since it's a bit more fiddly, likely to change, and not relevant for the content of the blog post. It also adds the actual vanilla javascript integration since it didn't exist before (it just wraps the resource in a run); * Code formatting was broken Co-authored-by: Taras Mankovski <taras@frontside.com>
1 parent 3939705 commit 399f3d0

File tree

3 files changed

+99
-0
lines changed

3 files changed

+99
-0
lines changed

.changes/ldap-readme.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@simulacrum/ldap-simulator": minor
3+
---
4+
Add a README to the NPM package as well as an async api around an LDAP server
5+
resource

packages/ldap/README.md

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
# @simulacrum/ldap-simulator
2+
3+
Simulate an actual LDAP server for testing and development.
4+
5+
Often you are working on software that depends on the presence of an
6+
LDAP directory. This let's you create an LDAP server in a known state
7+
that can be used for offline development and testing.
8+
9+
There are two different ways to start an LDAP simulator, but they both involve
10+
the same set of options. If you are running in a vanilla JavaScript
11+
environment, you can use promise-based API.
12+
13+
## Plain JavaScript
14+
15+
```js
16+
import { runLDAPServer } from "@simulacrum/ldap-simulator";
17+
18+
async function run() {
19+
let server = await runLDAPServer({
20+
port: 3890,
21+
baseDN: "ou=users,dc=org.com",
22+
bindDn: "admin@org.com",
23+
bindPassword: "password",
24+
groupDN:"ou=groups,dc=org.com",
25+
users: [{
26+
//required
27+
cn: 'Charles Lowell',
28+
//optional to bind using this user
29+
password: "super-secret-but-not-really",
30+
//optional:
31+
uid: 'cowboyd',
32+
33+
}]
34+
});
35+
console.log(`LDAP server running on ${server.port}`);
36+
try {
37+
//.... do some stuff;
38+
} finally {
39+
// don't forget to release the server resources!
40+
await server.close();
41+
}
42+
}
43+
```
44+
45+
## Effection
46+
47+
However, if you are already using [Effection][effection], the LDAP
48+
server is available as a [Resource][resource], and so you can use it
49+
freely in any context:
50+
51+
```js
52+
import { createLDAPServer } from "@simulacrum/ldap-simulator";
53+
54+
function* run() {
55+
let server = yield runLDAPServer({
56+
port: 3890,
57+
baseDN: "ou=users,dc=org.com",
58+
bindDn: "admin@org.com",
59+
bindPassword: "password",
60+
groupDN:"ou=groups,dc=org.com",
61+
users: [{
62+
//required
63+
cn: 'Charles Lowell',
64+
//optional to bind using this user
65+
password: "super-secret-but-not-really",
66+
//optional:
67+
uid: 'cowboyd',
68+
69+
}]
70+
});
71+
72+
//... do some stuff
73+
}
74+
```
75+
76+
[effection]: https://frontside.com/effection
77+
[resource]: https://frontside.com/effection/docs/guides/resources

packages/ldap/src/index.ts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import type { SearchRequest, Server, SearchResponse, CompareRequest, CompareResponse, BindResponse, BindRequest } from 'ldapjs';
22
import type { Operation } from 'effection';
3+
import { run } from 'effection';
34
import { createServer, InvalidCredentialsError, NoSuchObjectError, OperationsError } from 'ldapjs';
45
import type { LDAPOptions, LDAPStoreOptions, Port, UserData } from './types';
56
import type { SimulationState, Simulator } from '@simulacrum/server';
@@ -166,6 +167,22 @@ UserBaseDN: ${bindDn}
166167
};
167168
}
168169

170+
export interface Close {
171+
close(): Promise<void>;
172+
}
173+
174+
/**
175+
* Wraps an LDAP server resource into an Promise based API
176+
*/
177+
export async function runLDAPServer<T extends UserData>(options: LDAPOptions & LDAPStoreOptions<T>): Promise<Server & Port & Close> {
178+
let task = run(createLDAPServer(options));
179+
let server = await task;
180+
return Object.create(server, {
181+
close: { value: () => task.halt() }
182+
});
183+
184+
}
185+
169186
export function createLdapService<T extends UserData>(options: LDAPOptions, state: Slice<SimulationState>): ResourceServiceCreator {
170187
return () => {
171188
let users = {

0 commit comments

Comments
 (0)