oso-cloud
Version:
Oso Cloud Node.js Client SDK
392 lines • 15.3 kB
JavaScript
;
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