Enable address to alias conversion (#1784)
This commit updates the alias module so that we may convert node addresses into aliases. Naturally, the node address needs to be some kind of user node address that is known to the aliasing scheme. It's a big in-elegant that this creates a "hidden" integration point for plugins, where plugins creating new user node types should add hardcoded logic into the identity plugin's alias system. However, it is a convenience and we currently use this system, so I'm just going to add this functionality for now, and think about how the alias system should work long term (or whether we should phase it out) for another discussion. This is needed for #1773. I have `toAlias` return `null` when the address doesn't correspond to a known aliasing scheme, rather than erroring. I think erroring would be too harsh, given that it's quite possible that the user has loaded third-party plugins that haven't registered aliasing schemes upstream with us. In that case, the application should make a best effort attempt to proceed without an alias (e.g. fallback to the full address), for robustness. Test plan: Unit tests included; `yarn test` passes.
This commit is contained in:
parent
f183c51159
commit
96c34e3c6c
|
@ -3,11 +3,15 @@
|
||||||
import {type NodeAddressT} from "../../core/graph";
|
import {type NodeAddressT} from "../../core/graph";
|
||||||
import {githubOwnerPattern} from "../github/repoId";
|
import {githubOwnerPattern} from "../github/repoId";
|
||||||
import {loginAddress as githubAddress} from "../github/nodes";
|
import {loginAddress as githubAddress} from "../github/nodes";
|
||||||
|
import {userNodeType as githubUserType} from "../github/declaration";
|
||||||
import {userAddress as discourseAddress} from "../discourse/address";
|
import {userAddress as discourseAddress} from "../discourse/address";
|
||||||
|
import {userNodeType as discourseUserType} from "../discourse/declaration";
|
||||||
|
import {identityType} from "./declaration";
|
||||||
import {
|
import {
|
||||||
identityAddress,
|
identityAddress,
|
||||||
USERNAME_PATTERN as _VALID_IDENTITY_PATTERN,
|
USERNAME_PATTERN as _VALID_IDENTITY_PATTERN,
|
||||||
} from "./identity";
|
} from "./identity";
|
||||||
|
import {NodeAddress} from "../../core/graph";
|
||||||
|
|
||||||
/** An Alias is a string specification of an identity within another plugin.
|
/** An Alias is a string specification of an identity within another plugin.
|
||||||
*
|
*
|
||||||
|
@ -64,3 +68,29 @@ export function resolveAlias(
|
||||||
throw new Error(`Unknown type for alias: ${alias}`);
|
throw new Error(`Unknown type for alias: ${alias}`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Attempt to convert a NodeAddressT to an Alias.
|
||||||
|
*
|
||||||
|
* If the provided node address corresponds to a known aliasing scheme, an
|
||||||
|
* alias will be returned. Otherwise, null is returned. Since it's possible
|
||||||
|
* that the node address is a valid user node address provided by a plugin that
|
||||||
|
* didn't update this alias registry, clients should endeavor to accomodate
|
||||||
|
* those addresses rather than erroring.
|
||||||
|
*/
|
||||||
|
export function toAlias(n: NodeAddressT): Alias | null {
|
||||||
|
const parts = NodeAddress.toParts(n);
|
||||||
|
const terminator = parts[parts.length - 1];
|
||||||
|
const prefixes: Map<string, NodeAddressT> = new Map([
|
||||||
|
["github", githubUserType.prefix],
|
||||||
|
["discourse", discourseUserType.prefix],
|
||||||
|
["sourcecred", identityType.prefix],
|
||||||
|
]);
|
||||||
|
|
||||||
|
for (const [prefix, nodePrefix] of prefixes.entries()) {
|
||||||
|
if (NodeAddress.hasPrefix(n, nodePrefix)) {
|
||||||
|
return `${prefix}/${terminator}`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
|
@ -1,9 +1,10 @@
|
||||||
// @flow
|
// @flow
|
||||||
|
|
||||||
import {resolveAlias} from "./alias";
|
import {resolveAlias, toAlias} from "./alias";
|
||||||
import {loginAddress as githubAddress} from "../github/nodes";
|
import {loginAddress as githubAddress} from "../github/nodes";
|
||||||
import {userAddress as discourseAddress} from "../discourse/address";
|
import {userAddress as discourseAddress} from "../discourse/address";
|
||||||
import {identityAddress} from "./identity";
|
import {identityAddress} from "./identity";
|
||||||
|
import {NodeAddress} from "../../core/graph";
|
||||||
|
|
||||||
describe("src/plugins/identity/alias", () => {
|
describe("src/plugins/identity/alias", () => {
|
||||||
describe("resolveAlias", () => {
|
describe("resolveAlias", () => {
|
||||||
|
@ -90,4 +91,23 @@ describe("src/plugins/identity/alias", () => {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
describe("toAlias", () => {
|
||||||
|
function checkRoundTrip(alias) {
|
||||||
|
const addr = resolveAlias(alias, "https://example.com");
|
||||||
|
expect(toAlias(addr)).toEqual(alias);
|
||||||
|
}
|
||||||
|
it("works for a GitHub node address", () => {
|
||||||
|
checkRoundTrip("github/example");
|
||||||
|
});
|
||||||
|
it("works for a Discourse node address", () => {
|
||||||
|
checkRoundTrip("discourse/example");
|
||||||
|
});
|
||||||
|
it("works for a identity node address", () => {
|
||||||
|
checkRoundTrip("sourcecred/example");
|
||||||
|
});
|
||||||
|
it("returns null for an address without an aliasing scheme", () => {
|
||||||
|
const address = NodeAddress.fromParts(["sourcecred", "plugin", "foo"]);
|
||||||
|
expect(toAlias(address)).toEqual(null);
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in New Issue