Skip to content

Add ability to define tenant-level perms for data and tenants perms #274

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Mar 18, 2025
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
114 changes: 108 additions & 6 deletions src/roles/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,15 @@ const roles = (connection: ConnectionREST): Roles => {
};

export const permissions = {
/**
* Create a set of permissions specific to Weaviate's backup functionality.
*
* For all collections, provide the `collection` argument as `'*'`.
*
* @param {string | string[]} args.collection The collection or collections to create permissions for.
* @param {boolean} [args.manage] Whether to allow managing backups. Defaults to `false`.
* @returns {BackupsPermission[]} The permissions for the specified collections.
*/
backup: (args: { collection: string | string[]; manage?: boolean }): BackupsPermission[] => {
const collections = Array.isArray(args.collection) ? args.collection : [args.collection];
return collections.flatMap((collection) => {
Expand All @@ -129,11 +138,27 @@ export const permissions = {
return out;
});
},
/**
* Create a set of permissions specific to Weaviate's cluster endpoints.
*
* @param {boolean} [args.read] Whether to allow reading cluster information. Defaults to `false`.
*/
cluster: (args: { read?: boolean }): ClusterPermission[] => {
const out: ClusterPermission = { actions: [] };
if (args.read) out.actions.push('read_cluster');
return [out];
},
/**
* Create a set of permissions specific to any operations involving collections.
*
* For all collections, provide the `collection` argument as `'*'`.
*
* @param {string | string[]} args.collection The collection or collections to create permissions for.
* @param {boolean} [args.create_collection] Whether to allow creating collections. Defaults to `false`.
* @param {boolean} [args.read_config] Whether to allow reading collection configurations. Defaults to `false`.
* @param {boolean} [args.update_config] Whether to allow updating collection configurations. Defaults to `false`.
* @param {boolean} [args.delete_collection] Whether to allow deleting collections. Defaults to `false`.
*/
collections: (args: {
collection: string | string[];
create_collection?: boolean;
Expand All @@ -151,24 +176,54 @@ export const permissions = {
return out;
});
},
/**
* Create a set of permissions specific to any operations involving objects within collections and tenants.
*
* For all collections, provide the `collection` argument as `'*'`.
* For all tenants, provide the `tenant` argument as `'*'`.
*
* Providing arrays of collections and tenants will create permissions for each combination of collection and tenant.
* E.g., `data({ collection: ['A', 'B'], tenant: ['X', 'Y'] })` will create permissions for tenants `X` and `Y` in both collections `A` and `B`.
*
* @param {string | string[]} args.collection The collection or collections to create permissions for.
* @param {string | string[]} [args.tenant] The tenant or tenants to create permissions for. Defaults to `'*'`.
* @param {boolean} [args.create] Whether to allow creating objects. Defaults to `false`.
* @param {boolean} [args.read] Whether to allow reading objects. Defaults to `false`.
* @param {boolean} [args.update] Whether to allow updating objects. Defaults to `false`.
* @param {boolean} [args.delete] Whether to allow deleting objects. Defaults to `false`.
*/
data: (args: {
collection: string | string[];
tenant?: string | string[];
create?: boolean;
read?: boolean;
update?: boolean;
delete?: boolean;
}): DataPermission[] => {
const collections = Array.isArray(args.collection) ? args.collection : [args.collection];
return collections.flatMap((collection) => {
const out: DataPermission = { collection, actions: [] };
const tenants = Array.isArray(args.tenant) ? args.tenant : [args.tenant ?? '*'];
const combinations = collections.flatMap((collection) =>
tenants.map((tenant) => ({ collection, tenant }))
);
return combinations.flatMap(({ collection, tenant }) => {
const out: DataPermission = { collection, tenant, actions: [] };
if (args.create) out.actions.push('create_data');
if (args.read) out.actions.push('read_data');
if (args.update) out.actions.push('update_data');
if (args.delete) out.actions.push('delete_data');
return out;
});
},
/**
* This namespace contains methods to create permissions specific to nodes.
*/
nodes: {
/**
* Create a set of permissions specific to reading nodes with verbosity set to `minimal`.
*
* @param {boolean} [args.read] Whether to allow reading nodes. Defaults to `false`.
* @returns {NodesPermission[]} The permissions for reading nodes.
*/
minimal: (args: { read?: boolean }): NodesPermission[] => {
const out: NodesPermission = {
collection: '*',
Expand All @@ -178,6 +233,13 @@ export const permissions = {
if (args.read) out.actions.push('read_nodes');
return [out];
},
/**
* Create a set of permissions specific to reading nodes with verbosity set to `verbose`.
*
* @param {string | string[]} args.collection The collection or collections to create permissions for.
* @param {boolean} [args.read] Whether to allow reading nodes. Defaults to `false`.
* @returns {NodesPermission[]} The permissions for reading nodes.
*/
verbose: (args: { collection: string | string[]; read?: boolean }): NodesPermission[] => {
const collections = Array.isArray(args.collection) ? args.collection : [args.collection];
return collections.flatMap((collection) => {
Expand All @@ -191,6 +253,16 @@ export const permissions = {
});
},
},
/**
* Create a set of permissions specific to any operations involving roles.
*
* @param {string | string[]} args.role The role or roles to create permissions for.
* @param {boolean} [args.create] Whether to allow creating roles. Defaults to `false`.
* @param {boolean} [args.read] Whether to allow reading roles. Defaults to `false`.
* @param {boolean} [args.update] Whether to allow updating roles. Defaults to `false`.
* @param {boolean} [args.delete] Whether to allow deleting roles. Defaults to `false`.
* @returns {RolesPermission[]} The permissions for the specified roles.
*/
roles: (args: {
role: string | string[];
create?: boolean;
Expand All @@ -208,32 +280,62 @@ export const permissions = {
return out;
});
},
/**
* Create a set of permissions specific to any operations involving tenants.
*
* For all collections, provide the `collection` argument as `'*'`.
* For all tenants, provide the `tenant` argument as `'*'`.
*
* Providing arrays of collections and tenants will create permissions for each combination of collection and tenant.
* E.g., `tenants({ collection: ['A', 'B'], tenant: ['X', 'Y'] })` will create permissions for tenants `X` and `Y` in both collections `A` and `B`.
*
* @param {string | string[] | Record<string, string | string[]>} args.collection The collection or collections to create permissions for.
* @param {string | string[]} [args.tenant] The tenant or tenants to create permissions for. Defaults to `'*'`.
* @param {boolean} [args.create] Whether to allow creating tenants. Defaults to `false`.
* @param {boolean} [args.read] Whether to allow reading tenants. Defaults to `false`.
* @param {boolean} [args.update] Whether to allow updating tenants. Defaults to `false`.
* @param {boolean} [args.delete] Whether to allow deleting tenants. Defaults to `false`.
* @returns {TenantsPermission[]} The permissions for the specified tenants.
*/
tenants: (args: {
collection: string | string[];
tenant?: string | string[];
create?: boolean;
read?: boolean;
update?: boolean;
delete?: boolean;
}): TenantsPermission[] => {
const collections = Array.isArray(args.collection) ? args.collection : [args.collection];
return collections.flatMap((collection) => {
const out: TenantsPermission = { collection, actions: [] };
const tenants = Array.isArray(args.tenant) ? args.tenant : [args.tenant ?? '*'];
const combinations = collections.flatMap((collection) =>
tenants.map((tenant) => ({ collection, tenant }))
);
return combinations.flatMap(({ collection, tenant }) => {
const out: TenantsPermission = { collection, tenant, actions: [] };
if (args.create) out.actions.push('create_tenants');
if (args.read) out.actions.push('read_tenants');
if (args.update) out.actions.push('update_tenants');
if (args.delete) out.actions.push('delete_tenants');
return out;
});
},
/**
* Create a set of permissions specific to any operations involving users.
*
* @param {string | string[]} args.user The user or users to create permissions for.
* @param {boolean} [args.assignAndRevoke] Whether to allow assigning and revoking users. Defaults to `false`.
* @param {boolean} [args.read] Whether to allow reading users. Defaults to `false`.
* @returns {UsersPermission[]} The permissions for the specified users.
*/
users: (args: {
user: string | string[];
assign_and_revoke?: boolean;
assignAndRevoke?: boolean;
read?: boolean;
}): UsersPermission[] => {
const users = Array.isArray(args.user) ? args.user : [args.user];
return users.flatMap((user) => {
const out: UsersPermission = { users: user, actions: [] };
if (args.assign_and_revoke) out.actions.push('assign_and_revoke_users');
if (args.assignAndRevoke) out.actions.push('assign_and_revoke_users');
if (args.read) out.actions.push('read_users');
return out;
});
Expand Down
Loading