UNPKG

@mamoorali295/rbac

Version:

Complete RBAC (Role-Based Access Control) system for Node.js with Express middleware, NestJS integration, GraphQL support, MongoDB & PostgreSQL support, modern admin dashboard, TypeScript support, and dynamic permission management

214 lines (201 loc) 9.2 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.getFeatureDetailsView = exports.getFeaturesListView = void 0; const layout_1 = require("./layout"); const getFeaturesListView = (features) => { const featuresRows = features.map(feature => ` <tr> <td> <strong>${feature.name}</strong><br> <small style="color: #666;">${feature.description}</small> </td> <td>${feature.createdAt ? new Date(feature.createdAt).toLocaleDateString() : 'N/A'}</td> <td> <button class="btn" onclick="editFeature('${feature._id}', '${feature.name}', '${feature.description}')">Edit</button> <button class="btn btn-danger" onclick="confirmDeleteFeature('${feature._id}', '${feature.name}')">Delete</button> </td> </tr> `).join(''); const content = ` <div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 2rem;"> <h2>Feature Management</h2> <button class="btn btn-success" onclick="openModal('createFeatureModal')">Create New Feature</button> </div> <div class="card"> <div class="card-header"> <h4>All Features (${features.length})</h4> </div> <div class="card-body"> <p style="margin-bottom: 1rem; color: #666;"> Features represent different parts or modules of your application that can have permissions assigned to them. </p> <table class="table"> <thead> <tr> <th>Feature</th> <th>Created</th> <th>Actions</th> </tr> </thead> <tbody> ${featuresRows} </tbody> </table> ${features.length === 0 ? '<p style="text-align: center; color: #666;">No features created yet.</p>' : ''} </div> </div> <!-- Create Feature Modal --> <div id="createFeatureModal" class="modal"> <div class="modal-content"> <span class="close" onclick="closeModal('createFeatureModal')">&times;</span> <h3>Create New Feature</h3> <form method="POST" action="/rbac-admin/features/create"> <div class="form-group"> <label>Feature Name:</label> <input type="text" name="name" class="form-control" required placeholder="e.g., billing, users, reports"> <small style="color: #666;">Use lowercase names that match your route segments (e.g., /billing/invoices)</small> </div> <div class="form-group"> <label>Description:</label> <textarea name="description" class="form-control" rows="3" required placeholder="Describe what this feature controls..."></textarea> </div> <button type="submit" class="btn btn-success">Create Feature</button> <button type="button" class="btn" onclick="closeModal('createFeatureModal')">Cancel</button> </form> </div> </div> <!-- Edit Feature Modal --> <div id="editFeatureModal" class="modal"> <div class="modal-content"> <span class="close" onclick="closeModal('editFeatureModal')">&times;</span> <h3>Edit Feature</h3> <form id="editFeatureForm" method="POST"> <div class="form-group"> <label>Feature Name:</label> <input type="text" name="name" id="editFeatureName" class="form-control" required> </div> <div class="form-group"> <label>Description:</label> <textarea name="description" id="editFeatureDescription" class="form-control" rows="3" required></textarea> </div> <button type="submit" class="btn btn-success">Update Feature</button> <button type="button" class="btn" onclick="closeModal('editFeatureModal')">Cancel</button> </form> </div> </div> <script> function editFeature(featureId, name, description) { document.getElementById('editFeatureName').value = name; document.getElementById('editFeatureDescription').value = description; document.getElementById('editFeatureForm').action = '/rbac-admin/features/' + featureId + '/update'; openModal('editFeatureModal'); } function confirmDeleteFeature(featureId, featureName) { if (confirm('Are you sure you want to delete feature: ' + featureName + '?\\n\\nThis will remove the feature from all roles that use it.')) { fetch('/rbac-admin/features/' + featureId + '/delete', { method: 'POST', headers: { 'Content-Type': 'application/json' } }) .then(response => response.json()) .then(data => { if (data.error) { alert('Error: ' + data.error); } else { window.location.reload(); } }) .catch(err => alert('Error deleting feature: ' + err.message)); } } </script> `; return (0, layout_1.getBaseLayout)('Features', content); }; exports.getFeaturesListView = getFeaturesListView; const getFeatureDetailsView = (feature, relatedRoles) => { const rolesUsingFeature = relatedRoles.filter(role => role.features && role.features.some((f) => f.feature._id.toString() === feature._id.toString())); const rolesHtml = rolesUsingFeature.map(role => { const roleFeature = role.features.find((f) => f.feature._id.toString() === feature._id.toString()); return ` <div class="card" style="margin-bottom: 1rem;"> <div class="card-header"> <h5>${role.name}</h5> </div> <div class="card-body"> <p>${role.description}</p> <strong>Permissions for this feature:</strong> ${roleFeature.permissions.map((p) => `<span class="badge">${p.name}</span>`).join(' ')} <div style="margin-top: 10px;"> <a href="/rbac-admin/roles/${role._id}" class="btn">View Role Details</a> </div> </div> </div> `; }).join(''); const content = ` <div style="margin-bottom: 1rem;"> <a href="/rbac-admin/features" class="btn">← Back to Features</a> </div> <div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 2rem;"> <div> <h2>${feature.name}</h2> <p style="color: #666;">${feature.description}</p> </div> <button class="btn" onclick="editFeature('${feature._id}', '${feature.name}', '${feature.description}')">Edit Feature</button> </div> <div class="card"> <div class="card-header"> <h4>Roles Using This Feature (${rolesUsingFeature.length})</h4> </div> <div class="card-body"> ${rolesUsingFeature.length > 0 ? rolesHtml : '<p>This feature is not currently assigned to any roles.</p>'} </div> </div> <div class="card" style="margin-top: 2rem;"> <div class="card-header"> <h4>Feature Statistics</h4> </div> <div class="card-body"> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 1rem;"> <div style="text-align: center; padding: 1rem; background: #f8f9fa; border-radius: 4px;"> <h3 style="color: #3498db; margin-bottom: 5px;">${rolesUsingFeature.length}</h3> <p style="margin: 0; color: #666;">Roles Using</p> </div> <div style="text-align: center; padding: 1rem; background: #f8f9fa; border-radius: 4px;"> <h3 style="color: #27ae60; margin-bottom: 5px;">${feature.createdAt ? new Date(feature.createdAt).toLocaleDateString() : 'N/A'}</h3> <p style="margin: 0; color: #666;">Created On</p> </div> </div> </div> </div> <!-- Edit Feature Modal --> <div id="editFeatureModal" class="modal"> <div class="modal-content"> <span class="close" onclick="closeModal('editFeatureModal')">&times;</span> <h3>Edit Feature</h3> <form id="editFeatureForm" method="POST"> <div class="form-group"> <label>Feature Name:</label> <input type="text" name="name" id="editFeatureName" class="form-control" required> </div> <div class="form-group"> <label>Description:</label> <textarea name="description" id="editFeatureDescription" class="form-control" rows="3" required></textarea> </div> <button type="submit" class="btn btn-success">Update Feature</button> <button type="button" class="btn" onclick="closeModal('editFeatureModal')">Cancel</button> </form> </div> </div> <script> function editFeature(featureId, name, description) { document.getElementById('editFeatureName').value = name; document.getElementById('editFeatureDescription').value = description; document.getElementById('editFeatureForm').action = '/rbac-admin/features/' + featureId + '/update'; openModal('editFeatureModal'); } </script> `; return (0, layout_1.getBaseLayout)('Feature Details', content); }; exports.getFeatureDetailsView = getFeatureDetailsView;