Skip to content

Commit

Permalink
Adds initial account support
Browse files Browse the repository at this point in the history
  • Loading branch information
michaloo committed Mar 17, 2017
1 parent 3669316 commit 402a699
Show file tree
Hide file tree
Showing 4 changed files with 67 additions and 29 deletions.
17 changes: 12 additions & 5 deletions src/client.js
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ const Client = function Client(config = {}) {
});

this.userToken = function userToken(data = clientConfig.get("userId"), claims) {
return crypto.lookupToken(clientConfig.get(), data, claims);
return crypto.lookupToken(clientConfig.get(), "user", data, claims);
};

this.currentUserMiddleware = currentUserMiddleware.bind(this, clientConfig.get());
Expand Down Expand Up @@ -115,11 +115,18 @@ const Client = function Client(config = {}) {
});
};
} else {
this.as = (userClaims, userClaimsOptions) => {
if (!userClaims) {
throw new Error("User Claims was not defined when calling hull.as()");
this.asUser = (userClaim, additionalClaims) => {
if (!userClaim) {
throw new Error("User Claims was not defined when calling hull.asUser()");
}
return new Client({ ...config, userClaims, userClaimsOptions });
return new Client({ ...config, userClaim, additionalClaims });
};

this.asAccount = (accountClaim, additionalClaims) => {
if (!accountClaim) {
throw new Error("Account Claims was not defined when calling hull.asAccount()");
}
return new Client({ ...config, accountClaim, additionalClaims });
};
}
};
Expand Down
14 changes: 10 additions & 4 deletions src/configuration.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,9 @@ const VALID_PROPS = {
prefix: VALID.string,
domain: VALID.string,
protocol: VALID.string,
userClaims: VALID.object,
userClaimsOptions: VALID.object,
userClaim: VALID.object,
accountClaim: VALID.object,
additionalClaims: VALID.object,
accessToken: VALID.string,
hostSecret: VALID.string,
flushAt: VALID.number,
Expand All @@ -53,8 +54,13 @@ class Configuration {
throw new Error("Configuration is invalid, it should be a non-empty object");
}

if (config.userClaims) {
const accessToken = crypto.lookupToken(config, config.userClaims, config.userClaimsOptions);
if (config.userClaim) {
const accessToken = crypto.lookupToken(config, "user", config.userClaim, config.additionalClaims);
config = { ...config, accessToken };
}

if (config.accountClaim) {
const accessToken = crypto.lookupToken(config, "account", config.accountClaim, config.additionalClaims);
config = { ...config, accessToken };
}

Expand Down
44 changes: 29 additions & 15 deletions src/lib/crypto.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,32 +43,46 @@ module.exports = {
/**
* Calculates the hash for a user lookup - io.hull.as
*
* This is a wrapper over `buildToken` method.
* If the identClaim is a string or has id property, it's considered as an object id,
* and its value is set as a token subject.
* Otherwise it verifies if required ident properties are set
* and saves them as a custom ident claim.
*
* @param {Object} config object
* @param {Object} user object or user ID as string
* @param {Object} additionnal claims
* @param {String} type - "user" or "account"
* @param {String|Object} identClaim main idenditiy claim - object or string
* @param {Object} additionalClaims
* @returns {String} The jwt token to identity the user.
*/
lookupToken(config, user = {}, claimsOptions = {}) {
lookupToken(config, type, identClaim, additionalClaims = {}) {
type = _.toLower(type);
if (!_.includes(["user", "account"], type)) {
throw new Error("Lookup token supports only `user` and `account` types");
}

checkConfig(config);
const claims = {};
if (_.isString(user)) {
if (!user) { throw new Error("Missing user ID"); }
claims.sub = user;
} else if (user.id) {
claims.sub = user.id;
if (_.isString(identClaim)) {
if (!identClaim) { throw new Error(`Missing ${type} ID`); }
claims.sub = identClaim;
} else if (identClaim.id) {
claims.sub = identClaim.id;
} else {
if (!_.isObject(user) || (!user.email && !user.external_id && !user.guest_id)) {
throw new Error("you need to pass a User hash with an `email` or `external_id` or `guest_id` field");
if (type === "user"
&& (!_.isObject(identClaim) || (!identClaim.email && !identClaim.external_id && !identClaim.anonymous_id))) {
throw new Error("You need to pass a user hash with an `email` or `external_id` or `anonymous_id` field");
}
claims["io.hull.as"] = user;

claims[`io.hull.as${_.upperFirst(type)}`] = identClaim;
}

if (_.has(claimsOptions, "create")) {
claims["io.hull.create"] = claimsOptions.create;
if (_.has(additionalClaims, "create")) {
claims["io.hull.create"] = additionalClaims.create;
}

if (_.has(claimsOptions, "active")) {
claims["io.hull.active"] = claimsOptions.active;
if (_.has(additionalClaims, "active")) {
claims["io.hull.active"] = additionalClaims.active;
}

return buildToken(config, claims);
Expand Down
21 changes: 16 additions & 5 deletions tests/client-tests.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,37 +28,48 @@ describe("Hull", () => {
it("should allow to pass create option", () => {
const hull = new Hull({ id: "562123b470df84b740000042", secret: "1234", organization: "test" });

const scoped = hull.as({ email: "foo@bar.com" }, { create: false });
const scoped = hull.asUser({ email: "foo@bar.com" }, { create: false });
const scopedConfig = scoped.configuration();
const scopedJwtClaims = jwt.decode(scopedConfig.accessToken, scopedConfig.secret);
expect(scopedJwtClaims)
.to.have.property("io.hull.create")
.that.eql(false);
expect(scopedJwtClaims)
.to.have.property("io.hull.as")
.to.have.property("io.hull.asUser")
.that.eql({ email: "foo@bar.com" });
});

it("should allow to pass user id as a string", () => {
const hull = new Hull({ id: "562123b470df84b740000042", secret: "1234", organization: "test" });

const scoped = hull.as("123456");
const scoped = hull.asUser("123456");
const scopedConfig = scoped.configuration();
const scopedJwtClaims = jwt.decode(scopedConfig.accessToken, scopedConfig.secret);
expect(scopedJwtClaims)
.to.have.property("sub")
.that.eql("123456");
});

it("should allow to pass user id as an object property", () => {
it("should allow to pass account id as an object property", () => {
const hull = new Hull({ id: "562123b470df84b740000042", secret: "1234", organization: "test" });

const scoped = hull.as({ id: "123456" });
const scoped = hull.asAccount({ id: "123456" });
const scopedConfig = scoped.configuration();
const scopedJwtClaims = jwt.decode(scopedConfig.accessToken, scopedConfig.secret);
expect(scopedJwtClaims)
.to.have.property("sub")
.that.eql("123456");
});

it("should allow to pass account name as an object property", () => {
const hull = new Hull({ id: "562123b470df84b740000042", secret: "1234", organization: "test" });

const scoped = hull.asAccount({ name: "Hull" });
const scopedConfig = scoped.configuration();
const scopedJwtClaims = jwt.decode(scopedConfig.accessToken, scopedConfig.secret);
expect(scopedJwtClaims)
.to.have.property("io.hull.asAccount")
.that.eql({ name: "Hull" });
});
});
});

0 comments on commit 402a699

Please sign in to comment.