Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 36 additions & 7 deletions lib/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1230,22 +1230,36 @@ declare namespace Stardog {
}

type Action =
| 'ALL'
| 'CREATE'
| 'DELETE'
| 'READ'
| 'WRITE'
| 'EXECUTE'
| 'GRANT'
| 'READ'
| 'REVOKE'
| 'EXECUTE';
| 'WRITE';

type ResourceType =
| 'db'
| 'user'
| 'role'
| '*'
| 'admin'
| 'cache'
| 'cache-target'
| 'data-source'
| 'db'
| 'db-export'
| 'dbms-admin'
| 'entity-resolution'
| 'icv-constraints'
| 'metadata'
| 'modeling'
| 'named-graph'
| 'icv-constraints';
| 'permission'
| 'role'
| 'role-assignment'
| 'sensitive-properties'
| 'stored-query'
| 'user'
| 'virtual-graph';

/**
* Gets a list of users.
Expand Down Expand Up @@ -1440,6 +1454,21 @@ declare namespace Stardog {
params?: object
): Promise<HTTP.Body>;

/**
* Checks if the current user has a specific permission.
*
* @param {Connection} conn the Stardog server connection
* @param {Action} action the action to check
* @param {ResourceType} resourceType the type of resource
* @param {string} resource the resource name
*/
function checkPermission(
conn: Connection,
action: Action,
resourceType: ResourceType,
resource: string
): Promise<HTTP.Body>;

/**
* Specifies whether a user is a superuser.
*
Expand Down
22 changes: 22 additions & 0 deletions lib/user/main.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
const { httpBody, httpMessage } = require('../response-transforms');
const { encodeQueryString } = require('../utils');

const list = (conn, params) => {
const headers = conn.headers();
Expand Down Expand Up @@ -162,6 +163,26 @@ const effectivePermissions = (conn, username, params) => {
).then(httpBody);
};

const checkPermission = (conn, action, resourceType, resource) => {
const headers = conn.headers();
headers.set('Accept', 'application/json');
const queryParams = {
action,
resource_type: resourceType,
resource,
};
return fetch(
conn.request(
'admin',
'permissions',
`check${encodeQueryString(queryParams)}`
),
{
headers,
}
).then(httpBody);
};

const superUser = (conn, username, params) => {
const headers = conn.headers();
headers.set('Accept', 'application/json');
Expand Down Expand Up @@ -196,6 +217,7 @@ module.exports = {
assignRole,
assignPermission,
changePassword,
checkPermission,
create,
deletePermission,
effectivePermissions,
Expand Down
89 changes: 89 additions & 0 deletions test/checkPermission.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
/* eslint-env jest */

const { user, Connection } = require('../lib');
const {
seedDatabase,
dropDatabase,
generateDatabaseName,
generateRandomString,
ConnectionFactory,
} = require('./setup-database');

// TODO skipped until Stardog v12 is released
describe.skip('checkPermission()', () => {
const database = generateDatabaseName();
let conn;

beforeAll(seedDatabase(database));
afterAll(dropDatabase(database));

beforeEach(() => {
conn = ConnectionFactory();
});

it('should return true for a permission the admin user has', () =>
user.checkPermission(conn, 'READ', 'db', database).then(res => {
expect(res.status).toBe(200);
expect(res.body.hasPermission).toBe(true);
}));

it('should return false for a permission a new user does not have', () => {
const username = generateRandomString();
const password = generateRandomString();

return user
.create(conn, { username, password })
.then(res => {
expect(res.status).toBe(201);
// Create a new connection for the unprivileged user
const userConn = new Connection({
username,
password,
endpoint: conn.uri(),
});
return user.checkPermission(userConn, 'WRITE', 'db', database);
})
.then(res => {
expect(res.status).toBe(200);
expect(res.body.hasPermission).toBe(false);
});
});

it('should return true after assigning a permission to a user', () => {
const username = generateRandomString();
const password = generateRandomString();
const userConn = new Connection({
username,
password,
endpoint: conn.uri(),
});
const permission = {
action: 'WRITE',
resourceType: 'db',
resources: [database],
};

return user
.create(conn, { username, password })
.then(res => {
expect(res.status).toBe(201);
// First verify the user does not have the permission
return user.checkPermission(userConn, 'WRITE', 'db', database);
})
.then(res => {
expect(res.status).toBe(200);
expect(res.body.hasPermission).toBe(false);
// Now assign the permission
return user.assignPermission(conn, username, permission);
})
.then(res => {
expect(res.status).toBe(201);
// Verify the user now has the permission
return user.checkPermission(userConn, 'WRITE', 'db', database);
})
.then(res => {
expect(res.status).toBe(200);
expect(res.body.hasPermission).toBe(true);
});
});
});