rbac-engine
Version:
Role-based access control engine with policy-based permissions
351 lines • 11.5 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.DynamoDBRepository = void 0;
const client_dynamodb_1 = require("@aws-sdk/client-dynamodb");
const lib_dynamodb_1 = require("@aws-sdk/lib-dynamodb");
class DynamoDBRepository {
constructor(client) {
this.client = client;
this.docClient = lib_dynamodb_1.DynamoDBDocumentClient.from(client);
this.tableName = process.env.TABLE_NAME || 'Access-Control';
}
async setupTables() {
try {
await this.client.send(new client_dynamodb_1.DescribeTableCommand({
TableName: this.tableName
}));
console.log("Table already exists");
}
catch (err) {
if (err.name === "ResourceNotFoundException") {
const params = {
TableName: this.tableName,
KeySchema: [
{ AttributeName: "PK", KeyType: "HASH" },
{ AttributeName: "SK", KeyType: "RANGE" }
],
AttributeDefinitions: [
{ AttributeName: "PK", AttributeType: "S" },
{ AttributeName: "SK", AttributeType: "S" }
],
BillingMode: "PAY_PER_REQUEST"
};
await this.client.send(new client_dynamodb_1.CreateTableCommand(params));
console.log("Table created");
}
else {
throw new Error(`Something went wrong: ${err}`);
}
}
}
async createUser(user) {
const item = {
PK: `USER#${user.id}`,
SK: `USER#${user.id}`,
type: "USER",
name: user.name,
roles: user.roles || [],
policies: user.policies || []
};
await this.docClient.send(new lib_dynamodb_1.PutCommand({
TableName: this.tableName,
Item: item
}));
return user;
}
async getUser(userId) {
try {
const result = await this.docClient.send(new lib_dynamodb_1.GetCommand({
TableName: this.tableName,
Key: {
PK: `USER#${userId}`,
SK: `USER#${userId}`
},
}));
if (!result.Item) {
throw new Error(`User not found: ${userId}`);
}
return {
id: userId,
name: result.Item.name,
roles: result.Item.roles,
policies: result.Item.policies
};
}
catch (err) {
throw new Error(`Something went wrong: ${err}`);
}
}
async createRole(role) {
const item = {
PK: `ROLE#${role.id}`,
SK: `ROLE#${role.id}`,
type: "ROLE",
name: role.name,
policies: role.policies || []
};
await this.docClient.send(new lib_dynamodb_1.PutCommand({
TableName: this.tableName,
Item: item
}));
return role;
}
async getRole(roleId) {
try {
const result = await this.docClient.send(new lib_dynamodb_1.GetCommand({
TableName: this.tableName,
Key: {
PK: `ROLE#${roleId}`,
SK: `ROLE#${roleId}`
},
}));
if (!result.Item) {
throw new Error(`Role not found: ${roleId}`);
}
return {
id: roleId,
name: result.Item.name,
policies: result.Item.policies
};
}
catch (err) {
throw new Error(`Something went wrong: ${err}`);
}
}
async assignRoleToUser(userId, roleId) {
const user = await this.getUser(userId);
if (!user.roles) {
user.roles = [];
}
const roles = new Set(user.roles);
roles.add(roleId);
const updatedRoles = Array.from(roles);
await this.docClient.send(new lib_dynamodb_1.UpdateCommand({
TableName: this.tableName,
Key: {
PK: `USER#${userId}`,
SK: `USER#${userId}`
},
UpdateExpression: "SET #rolesAttr = :roles",
ExpressionAttributeNames: {
"#rolesAttr": "roles"
},
ExpressionAttributeValues: {
":roles": updatedRoles
}
}));
return user;
}
async createPolicy(policy) {
const item = {
PK: `POLICY#${policy.id}`,
SK: `POLICY#${policy.id}`,
type: "POLICY",
document: policy.document
};
await this.docClient.send(new lib_dynamodb_1.PutCommand({
TableName: this.tableName,
Item: item
}));
return policy;
}
async attachPolicyToRole(policyId, roleId) {
const role = await this.getRole(roleId);
if (!role.policies) {
role.policies = [];
}
const policies = new Set(role.policies);
policies.add(policyId);
const updatedPolicies = Array.from(policies);
await this.docClient.send(new lib_dynamodb_1.UpdateCommand({
TableName: this.tableName,
Key: {
PK: `ROLE#${roleId}`,
SK: `ROLE#${roleId}`
},
UpdateExpression: "SET #policiesAttr = :policies",
ExpressionAttributeNames: {
"#policiesAttr": "policies"
},
ExpressionAttributeValues: {
":policies": updatedPolicies
}
}));
}
async getUserPolicies(userId) {
const user = await this.getUser(userId);
const policies = [];
if (user.policies) {
for (const policyId of user.policies) {
const policy = await this.getPolicy(policyId);
policies.push(policy);
}
}
return policies;
}
async getRolePolicies(roleId) {
const role = await this.getRole(roleId);
const policies = [];
if (role.policies) {
for (const policyId of role.policies) {
const policy = await this.getPolicy(policyId);
policies.push(policy);
}
}
return policies;
}
async updateRole(role) {
const item = {
PK: `ROLE#${role.id}`,
SK: `ROLE#${role.id}`,
type: "ROLE",
name: role.name,
policies: role.policies || []
};
await this.docClient.send(new lib_dynamodb_1.PutCommand({
TableName: this.tableName,
Item: item
}));
return role;
}
async updatePolicy(policy) {
const item = {
PK: `POLICY#${policy.id}`,
SK: `POLICY#${policy.id}`,
type: "POLICY",
document: policy.document
};
await this.docClient.send(new lib_dynamodb_1.PutCommand({
TableName: this.tableName,
Item: item
}));
return policy;
}
async deletePolicy(policyId) {
await this.docClient.send(new lib_dynamodb_1.DeleteCommand({
TableName: this.tableName,
Key: {
PK: `POLICY#${policyId}`,
SK: `POLICY#${policyId}`
}
}));
}
async deleteRole(roleId) {
await this.docClient.send(new lib_dynamodb_1.DeleteCommand({
TableName: this.tableName,
Key: {
PK: `ROLE#${roleId}`,
SK: `ROLE#${roleId}`
}
}));
}
async detachPolicyFromUser(policyId, userId) {
const user = await this.getUser(userId);
if (!user.policies) {
return;
}
const policies = user.policies.filter(p => p !== policyId);
await this.docClient.send(new lib_dynamodb_1.UpdateCommand({
TableName: this.tableName,
Key: {
PK: `USER#${userId}`,
SK: `USER#${userId}`
},
UpdateExpression: "SET #policiesAttr = :policies",
ExpressionAttributeNames: {
"#policiesAttr": "policies"
},
ExpressionAttributeValues: {
":policies": policies
},
}));
}
async detachPolicyFromRole(policyId, roleId) {
const role = await this.getRole(roleId);
if (!role.policies) {
return;
}
const policies = role.policies.filter(p => p !== policyId);
await this.docClient.send(new lib_dynamodb_1.UpdateCommand({
TableName: this.tableName,
Key: {
PK: `ROLE#${roleId}`,
SK: `ROLE#${roleId}`
},
UpdateExpression: "SET #policiesAttr = :policies",
ExpressionAttributeNames: {
"#policiesAttr": "policies"
},
ExpressionAttributeValues: {
":policies": policies
},
}));
}
async removeRoleFromUser(userId, roleId) {
const user = await this.getUser(userId);
if (!user.roles) {
return;
}
const roles = user.roles.filter(r => r !== roleId);
await this.docClient.send(new lib_dynamodb_1.UpdateCommand({
TableName: this.tableName,
Key: {
PK: `USER#${userId}`,
SK: `USER#${userId}`
},
UpdateExpression: "SET #rolesAttr = :roles",
ExpressionAttributeNames: {
"#rolesAttr": "roles"
},
ExpressionAttributeValues: {
":roles": roles
},
}));
}
async attachPolicyToUser(policyId, userId) {
const user = await this.getUser(userId);
if (!user.policies) {
user.policies = [];
}
const policies = new Set(user.policies);
policies.add(policyId);
const updatedPolicies = Array.from(policies);
await this.docClient.send(new lib_dynamodb_1.UpdateCommand({
TableName: this.tableName,
Key: {
PK: `USER#${userId}`,
SK: `USER#${userId}`
},
UpdateExpression: "SET #policiesAttr = :policies",
ExpressionAttributeNames: {
"#policiesAttr": "policies"
},
ExpressionAttributeValues: {
":policies": updatedPolicies
}
}));
}
async getPolicy(policyId) {
try {
const result = await this.docClient.send(new lib_dynamodb_1.GetCommand({
TableName: this.tableName,
Key: {
PK: `POLICY#${policyId}`,
SK: `POLICY#${policyId}`
},
}));
if (!result.Item) {
throw new Error(`Policy not found: ${policyId}`);
}
return {
id: policyId,
document: result.Item.document
};
}
catch (err) {
throw new Error(`Something went wrong: ${err}`);
}
}
}
exports.DynamoDBRepository = DynamoDBRepository;
//# sourceMappingURL=dynamodb-repo.js.map