Skip to content
Open
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
11 changes: 11 additions & 0 deletions interface.html
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,17 @@ <h3>No results found</h3>
</div>
</div>
</div>
<div class="form-group">
<div class="col-sm-4 control-label">
<label for="access-rules-json">Data source Security rules</label>
<p class="help-block">Configure data source security rules using JSON format. This includes access permissions, field-level operator restrictions, and context-specific rules for select, insert, update, and delete operations. Supports both field-specific operator rules (allowedOperators/deniedOperators) and global operator restrictions. Saving settings will overwrite the current security rules.</p>
</div>
<div class="col-sm-8">
<div class="checkbox checkbox-icon">
<textarea class="form-control form-code" id="access-rules-json" rows="15" placeholder="[]"></textarea>
</div>
</div>
</div>
<div class="form-group">
<hr />
<button class="btn text-danger" data-delete-source>Move to trash</button>
Expand Down
64 changes: 59 additions & 5 deletions js/interface.js
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,11 @@ var customRuleEditor = CodeMirror.fromTextArea($('#custom-rule')[0], {
lineNumbers: true,
mode: 'javascript'
});
var accessRulesEditor = CodeMirror.fromTextArea($('#access-rules-json')[0], {
lineNumbers: true,
mode: 'javascript'
});


var emptyColumnNameRegex = /^Column\s\([0-9]+\)$/;

Expand Down Expand Up @@ -263,6 +268,7 @@ function renderError(options) {
function fetchCurrentDataSourceDetails() {
definitionEditor.setValue('');
hooksEditor.setValue('');
accessRulesEditor.setValue('[]');

return Fliplet.DataSources.getById(currentDataSourceId, { cache: false }).then(function(dataSource) {
$settings.find('#id').html(dataSource.id);
Expand All @@ -273,10 +279,15 @@ function fetchCurrentDataSourceDetails() {
}

currentDataSourceType = dataSource.type;
currentDataSourceRules = dataSource.accessRules;
currentFinalRules = dataSource.accessRules;

let accessRules = Array.isArray(dataSource.accessRules) ? dataSource.accessRules : [];

currentDataSourceRules = Array.isArray(dataSource.accessRules) ? JSON.parse(JSON.stringify(dataSource.accessRules)) : dataSource.accessRules;
currentFinalRules = Array.isArray(dataSource.accessRules) ? JSON.parse(JSON.stringify(dataSource.accessRules)) : dataSource.accessRules;
currentDataSourceDefinition = dataSource.definition || {};

accessRulesEditor.setValue(JSON.stringify(accessRules, null, 2));

if (dataSource.apps && dataSource.apps.length > 0) {
dataSourceIsLive = _.some(dataSource.apps, function(app) {
return app.productionAppId;
Expand Down Expand Up @@ -1529,6 +1540,7 @@ $('#app')
var bundle = !$('#bundle').is(':checked');
var definition = definitionEditor.getValue();
var hooks = hooksEditor.getValue();
var accessRulesValue = accessRulesEditor.getValue();

$settings.find('#name').parents(':eq(1)').removeClass('has-error');

Expand Down Expand Up @@ -1563,6 +1575,39 @@ $('#app')
return;
}

var trimmedAccessRules = (accessRulesValue || '').trim();
var accessRulesData;

if (trimmedAccessRules) {
try {
var parsedAccessRules = JSON.parse(accessRulesValue);
} catch (e) {
Fliplet.Navigate.popup({
popupTitle: 'Invalid settings',
popupMessage: 'Access rules must be a valid JSON'
});

return;
}

if (Array.isArray(parsedAccessRules)) {
accessRulesData = parsedAccessRules;
} else if (parsedAccessRules && typeof parsedAccessRules === 'object' && Array.isArray(parsedAccessRules.accessRules)) {
accessRulesData = parsedAccessRules.accessRules;
} else {
Fliplet.Navigate.popup({
popupTitle: 'Invalid access rules',
popupMessage: 'Access rules JSON must be an array or an object containing an "accessRules" array.'
});

return;
}
} else {
accessRulesData = [];
}

var formattedAccessRules = JSON.stringify(accessRulesData, null, 2);

try {
hooks.forEach(function(hook) {
if (typeof hook.type !== 'string' || !hook.type) {
Expand Down Expand Up @@ -1595,9 +1640,13 @@ $('#app')
name: name,
bundle: bundle,
definition: definition,
hooks: hooks
hooks: hooks,
accessRules: accessRulesData
})
.then(function() {
currentDataSourceRules = JSON.parse(JSON.stringify(accessRulesData));
currentFinalRules = JSON.parse(JSON.stringify(accessRulesData));
accessRulesEditor.setValue(formattedAccessRules);
// Update name on UI
$('.editing-data-source-name').text(name);

Expand Down Expand Up @@ -1807,6 +1856,7 @@ $('#show-settings').click(function() {
setTimeout(function() {
definitionEditor.refresh();
hooksEditor.refresh();
accessRulesEditor.refresh();
}, 0);
});

Expand Down Expand Up @@ -2396,8 +2446,8 @@ $('#show-access-rules').click(function() {

return '-';
})(),
apps: rule.appId ?
_.compact(rule.appId.map(function(appId) {
apps: rule.appId
? _.compact(rule.appId.map(function(appId) {
var app = _.find(apps, {
id: appId
});
Expand Down Expand Up @@ -2754,6 +2804,10 @@ function updateDataSourceRules() {
return Fliplet.DataSources.update(currentDataSourceId, {
accessRules: currentDataSourceRules
}).then(function() {
var formattedRules = JSON.stringify(Array.isArray(currentDataSourceRules) ? currentDataSourceRules : [], null, 2);

currentFinalRules = JSON.parse(JSON.stringify(currentDataSourceRules));
accessRulesEditor.setValue(formattedRules);
$saveButton.html(buttonLabel).removeClass('disabled').addClass('hidden');

Fliplet.Modal.alert({
Expand Down