UNPKG

oso-cloud

Version:

Oso Cloud Node.js Client SDK

392 lines 15.3 kB
"use strict"; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; Object.defineProperty(exports, "__esModule", { value: true }); exports.Oso = exports.ParityHandle = exports.LogLevel = exports.typedVar = void 0; const helpers_1 = require("./helpers"); const api_1 = require("./api"); const query_1 = require("./query"); const parity_handle_1 = require("./parity-handle"); var query_2 = require("./query"); Object.defineProperty(exports, "typedVar", { enumerable: true, get: function () { return query_2.typedVar; } }); // Custom log levels sent to the logging function. var LogLevel; (function (LogLevel) { LogLevel["error"] = "error"; LogLevel["info"] = "info"; LogLevel["debug"] = "debug"; })(LogLevel || (exports.LogLevel = LogLevel = {})); var parity_handle_2 = require("./parity-handle"); Object.defineProperty(exports, "ParityHandle", { enumerable: true, get: function () { return parity_handle_2.ParityHandle; } }); /** * Oso Cloud client * * For more detailed documentation, see * https://www.osohq.com/docs/app-integration/client-apis/node */ class Oso { constructor(url, apiKey, options) { this.api = new api_1.Api(url, apiKey, options || {}); } /** * Check a permission. * * @param {IntoValue} actor * @param {string} action * @param {IntoValue} resource * @param {IntoFact[]} [contextFacts] * @param {ParityHandle} parityHandle * @returns {Promise<boolean>} */ authorize() { return __awaiter(this, arguments, void 0, function* (...[actor, action, resource, authArgOptions]) { if (typeof action !== "string") { throw new TypeError(`'action' should be a string: ${action}`); } let contextFacts; let parityHandle; if (Array.isArray(authArgOptions)) { contextFacts = authArgOptions; } else if (authArgOptions) { contextFacts = authArgOptions.contextFacts; parityHandle = authArgOptions.parityHandle; } if (parityHandle) { if (!(parityHandle instanceof parity_handle_1.ParityHandle)) { throw new TypeError(`Expected a ParityHandle, got ${typeof parityHandle}`); } } let { type: actor_type, id: actor_id } = (0, helpers_1.toValue)(actor); let { type: resource_type, id: resource_id } = (0, helpers_1.toValue)(resource); if (actor_type == null || actor_id == null) { throw new TypeError(`'actor' can not be a wildcard: ${actor}`); } if (resource_type == null || resource_id == null) { throw new TypeError(`'resource' can not be a wildcard: ${resource}`); } let result = yield this.api.postAuthorize({ actor_type, actor_id, action, resource_type, resource_id, context_facts: (0, helpers_1.mapParamsToConcreteFacts)(contextFacts !== null && contextFacts !== void 0 ? contextFacts : []), }, parityHandle); return result.allowed; }); } /** * List authorized resources: * * Fetches a list of resource ids on which an actor can perform a particular action. * * @param {IntoValue} actor * @param {string} action * @param {string} resourceType * @param {IntoFact[]} [contextFacts] * @returns {Promise<string[]>} */ list() { return __awaiter(this, arguments, void 0, function* (...[actor, action, resourceType, contextFacts]) { if (typeof action !== "string") throw new TypeError(`'action' should be a string: ${action}`); const { type: actor_type, id: actor_id } = (0, helpers_1.toValue)(actor); if (actor_type == null || actor_id == null) { throw new TypeError(`'actor' can not be a wildcard: ${actor}`); } const { results } = yield this.api.postList({ actor_type, actor_id, action, resource_type: resourceType, context_facts: (0, helpers_1.mapParamsToConcreteFacts)(contextFacts), }); return results; }); } /** * List authorized actions: * * Fetches a list of actions which an actor can perform on a particular resource. * * @param {IntoValue} actor * @param {IntoValue} resource * @param {IntoFact[]} [contextFacts] * @returns {Promise<string[]>} */ actions() { return __awaiter(this, arguments, void 0, function* (...[actor, resource, contextFacts]) { let { type: actor_type, id: actor_id } = (0, helpers_1.toValue)(actor); let { type: resource_type, id: resource_id } = (0, helpers_1.toValue)(resource); if (actor_type == null || actor_id == null) { throw new TypeError(`'actor' can not be a wildcard: ${actor}`); } if (resource_type == null || resource_id == null) { throw new TypeError(`'actor' can not be a wildcard: ${actor}`); } const { results } = yield this.api.postActions({ actor_type, actor_id, resource_type, resource_id, context_facts: (0, helpers_1.mapParamsToConcreteFacts)(contextFacts), }); return results; }); } /** * Update the active policy: * * Updates the policy in Oso Cloud. The string passed into this method should be * written in Polar. * * NOTE: If you're using types generated from your policy, it's recommended that you * avoid this method in production, as updating your policy will likely * affect the set of generated types. Instead, use the Oso Cloud CLI to * manage your policy and generate new types. * * @param {string} src */ policy(src) { return __awaiter(this, void 0, void 0, function* () { yield this.api.postPolicy({ src, filename: "" }); }); } /** * Returns metadata about the currently active policy */ getPolicyMetadata() { return __awaiter(this, void 0, void 0, function* () { return (yield this.api.getPolicyMetadata()).metadata; }); } /** * Get facts: * * Get facts that are stored in Oso Cloud. Can be used to check the existence * of a particular fact, or used to fetch all facts that have a particular * argument. * * `oso.get()` only returns facts you've added. If you want to return a list of authorized resources, use * the Check API. For example, to answer "on which resouces can a given user * perform a given action", use `oso.list()`. * * @param {IntoFactPattern} fact * @returns {Promise<Fact[]>} */ get(_a) { return __awaiter(this, arguments, void 0, function* ([predicate, ...args]) { let varArgs = args.map(helpers_1.toValuePattern); return (0, helpers_1.mapFactsToParams)(yield this.api.getFacts(predicate, varArgs)); }); } /** * Fetches a query that can be run against your database to determine the actions * an actor can perform on a resource. * * Returns a SQL query to run against the local database. * * @param {IntoValue} actor * @param {IntoValue} resource * @param {IntoFact[]?} contextFacts * @returns {Promise<string>} */ actionsLocal() { return __awaiter(this, arguments, void 0, function* (...[actor, resource, contextFacts]) { const { type: actor_type, id: actor_id } = (0, helpers_1.toValue)(actor); const { type: resource_type, id: resource_id } = (0, helpers_1.toValue)(resource); if (actor_type == null || actor_id == null) { throw new TypeError(`'actor' can not be a wildcard: ${actor}`); } if (resource_type == null || resource_id == null) { throw new TypeError(`'resource' can not be a wildcard: ${resource}`); } const result = yield this.api.postActionsQuery({ actor_type, actor_id, resource_type, resource_id, context_facts: (0, helpers_1.mapParamsToConcreteFacts)(contextFacts), }); return result.sql; }); } /** * Check a permission depending on data both in Oso Cloud and stored in a local database. * * Returns a SQL query to run against the local database. * * @param {IntoValue} actor * @param {string} action * @param {IntoValue} resource * @param {IntoFact[]?} contextFacts * @returns {Promise<string>} */ authorizeLocal() { return __awaiter(this, arguments, void 0, function* (...[actor, action, resource, authArgOptions]) { if (typeof action !== "string") { throw new TypeError(`'action' should be a string: ${action}`); } const { type: actor_type, id: actor_id } = (0, helpers_1.toValue)(actor); const { type: resource_type, id: resource_id } = (0, helpers_1.toValue)(resource); if (actor_type == null || actor_id == null) { throw new TypeError(`'actor' can not be a wildcard: ${actor}`); } if (resource_type == null || resource_id == null) { throw new TypeError(`'resource' can not be a wildcard: ${resource}`); } let contextFacts; let parityHandle; if (Array.isArray(authArgOptions)) { contextFacts = authArgOptions; } else if (authArgOptions) { contextFacts = authArgOptions.contextFacts; parityHandle = authArgOptions.parityHandle; } const result = yield this.api.postAuthorizeQuery({ actor_type, actor_id, action, resource_type, resource_id, context_facts: (0, helpers_1.mapParamsToConcreteFacts)(contextFacts !== null && contextFacts !== void 0 ? contextFacts : []), }, parityHandle); return result.sql; }); } /** * List authorized resources depending on data both in Oso Cloud and stored in a local database. * * Returns a SQL query to run against the local database. * * @param {IntoValue} actor * @param {string} action * @param {string} resourceType * @param {string} column * @param {IntoFact[]?} contextFacts * @returns {Promise<string>} */ listLocal() { return __awaiter(this, arguments, void 0, function* (...[actor, action, resourceType, column, contextFacts]) { if (typeof action !== "string") throw new TypeError(`'action' should be a string: ${action}`); const { type: actor_type, id: actor_id } = (0, helpers_1.toValue)(actor); if (actor_type == null || actor_id == null) { throw new TypeError(`'actor' can not be a wildcard: ${actor}`); } const result = yield this.api.postListQuery({ actor_type, actor_id, action, resource_type: resourceType, context_facts: (0, helpers_1.mapParamsToConcreteFacts)(contextFacts), }, column); return result.sql; }); } /** * Query for an arbitrary expression. * Use `typedVar` to create variables to use in the query, * and refer to them in the final `evaluate` call to get their values. * * @param query * @returns {QueryBuilder} */ buildQuery(query) { return query_1.QueryBuilder.init(this, query); } /** * Add a fact: * * Adds a fact with the given predicate and arguments. * * @param {IntoFact} fact */ insert(fact) { return __awaiter(this, void 0, void 0, function* () { const fact_ = (0, helpers_1.paramToFact)(fact); yield this.api.postBatch([{ inserts: [fact_] }]); }); } /** * Delete fact: * * Deletes a fact. Does not throw an error if the fact is not found. * You can use `null` as a wildcard argument. * * @param {IntoFactPattern} fact */ delete(fact) { return __awaiter(this, void 0, void 0, function* () { const fact_ = (0, helpers_1.paramToFact)(fact); yield this.api.postBatch([{ deletes: [fact_] }]); }); } /** * Transactionally delete and add facts: * * Allows deleting and inserting many facts in one atomic transaction. * Deletions and insertions are run in the order they appear in the closure. * * @param {(tx: BatchTransaction) => void | Promise<void>} f - the callback which runs the `insert`s and `delete`s. * These changes can be issued via `tx.insert(fact)` and `tx.delete(fact)` within the closure. */ batch(f) { return __awaiter(this, void 0, void 0, function* () { let txn = new BatchTransaction(); yield f(txn); if (txn.changes.length) { yield this.api.postBatch(txn.changes); } }); } } exports.Oso = Oso; class BatchTransaction { constructor() { this.changes = []; } /** * Add a fact: * * Adds a fact with the given predicate and arguments. * * @param {IntoFact} fact */ insert(fact) { const fact_ = (0, helpers_1.paramToFact)(fact); let last = this.changes[this.changes.length - 1]; if (last === undefined || !("inserts" in last)) { last = { inserts: [] }; this.changes.push(last); } last.inserts.push(fact_); } /** * Delete fact: * * Deletes a fact. Does not throw an error if the fact is not found. * You can use `null` as a wildcard argument. * * @param {IntoFactPattern} fact */ delete(fact) { const fact_ = (0, helpers_1.paramToFact)(fact); let last = this.changes[this.changes.length - 1]; if (last === undefined || !("deletes" in last)) { last = { deletes: [] }; this.changes.push(last); } last.deletes.push(fact_); } } //# sourceMappingURL=index.js.map