Skip to content

Commit ac89f3c

Browse files
authored
Merge pull request #8177 from ProcessMaker/epic/FOUR-22580
FOUR-22580: [SUMMER 25] IFrame Whitelist Configs
2 parents 9cf93a2 + c914493 commit ac89f3c

File tree

8 files changed

+308
-32
lines changed

8 files changed

+308
-32
lines changed

ProcessMaker/Http/Controllers/Api/SettingController.php

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
namespace ProcessMaker\Http\Controllers\Api;
44

55
use DB;
6+
use Illuminate\Database\QueryException;
67
use Illuminate\Http\Request;
78
use Illuminate\Support\Facades\Auth;
89
use Illuminate\Support\Facades\Storage;
@@ -265,6 +266,28 @@ public function update(Setting $setting, Request $request)
265266
return response([], 204);
266267
}
267268

269+
public function store(Request $request)
270+
{
271+
$setting = new Setting();
272+
273+
try {
274+
$setting->fill($request->json()->all());
275+
$setting->saveOrFail();
276+
277+
return response([], 201);
278+
} catch (QueryException $e) {
279+
// Check for duplicate entry error code
280+
if ($e->errorInfo[1] == 1062) {
281+
return response()->json([
282+
'message' => 'The "Site Name" you\'re trying to add already exists. Please select a different name or review the existing entries to avoid duplication.',
283+
], 409);
284+
}
285+
286+
// Handle other query exceptions
287+
return response()->json(['message' => 'An error occurred while saving the setting.'], 500);
288+
}
289+
}
290+
268291
public function destroy(Setting $setting)
269292
{
270293
$setting->delete();

config/session.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -170,7 +170,7 @@
170170
|
171171
*/
172172

173-
'secure' => env('SESSION_SECURE_COOKIE'),
173+
'secure' => env('SESSION_SECURE_COOKIE', false),
174174

175175
/*
176176
|--------------------------------------------------------------------------
@@ -198,6 +198,6 @@
198198
|
199199
*/
200200

201-
'same_site' => 'lax',
201+
'same_site' => env('SESSION_SAME_SITE', 'lax'),
202202

203203
];
Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
<template>
2+
<b-modal
3+
id="bv-modal-whitelist"
4+
ref="bv-modal-whitelist"
5+
hide-footer
6+
>
7+
<template #modal-title>
8+
<div class="tw-self-stretch tw-text-base tw-font-medium tw-text-[#20242A]">
9+
{{ $t("Configure URL Parents for Embedding") }}
10+
</div>
11+
<div class="tw-self-stretch tw-text-sm tw-text-[#596372]">
12+
{{ $t("Please provide a valid URL (e.g., https://example.com ) to specify the allowed origin(s) permitted to embed ProcessMaker.") }}
13+
</div>
14+
</template>
15+
<div class="tw-block">
16+
<div class="form-group col-md-12">
17+
<div class="d-flex flex-column">
18+
<label for="site-name">
19+
{{ $t("Site Name") }}
20+
</label>
21+
<b-form-input
22+
id="site-name"
23+
v-model="siteName"
24+
type="text"
25+
required
26+
:state="stateSiteName"
27+
:placeholder="$t('Site Name')"
28+
/>
29+
</div>
30+
</div>
31+
<div class="form-group col-md-12">
32+
<div class="d-flex flex-column">
33+
<label for="url">
34+
{{ $t("Url") }}
35+
</label>
36+
<b-form-input
37+
id="url"
38+
v-model="url"
39+
type="text"
40+
required
41+
placeholder="https://www.sample.org/head"
42+
:state="stateURL"
43+
/>
44+
<div v-if="urlError" class="text-danger mt-1">
45+
{{ urlError }}
46+
</div>
47+
</div>
48+
</div>
49+
</div>
50+
<div class="tw-block tw-mt-8">
51+
<b-button
52+
id="confirm"
53+
type="submit"
54+
variant="primary"
55+
block
56+
@click="addWhiteListURL"
57+
>
58+
{{ $t('Create') }}
59+
</b-button>
60+
</div>
61+
</b-modal>
62+
</template>
63+
64+
<script>
65+
export default {
66+
data() {
67+
return {
68+
siteName: "",
69+
url: "",
70+
stateSiteName: null,
71+
stateURL: null,
72+
groupName: "",
73+
group_id: 3,
74+
urlError: "",
75+
};
76+
},
77+
methods: {
78+
show(groupName) {
79+
this.clear();
80+
this.groupName = groupName;
81+
return this.$refs["bv-modal-whitelist"].show();
82+
},
83+
clear() {
84+
this.siteName = "";
85+
this.url = "";
86+
this.urlError = "";
87+
},
88+
validateURL(url) {
89+
const pattern = /^(https?:\/\/)?(\*\.)?([a-zA-Z0-9-]+\.)+[a-zA-Z]{2,}(:\d+)?(\/.*)?$/;
90+
return pattern.test(url);
91+
},
92+
addWhiteListURL() {
93+
if (!this.siteName) {
94+
this.stateSiteName = false;
95+
return;
96+
}
97+
if (!this.url) {
98+
this.stateURL = false;
99+
return;
100+
}
101+
// Validate the URL using the regex pattern
102+
if (!this.validateURL(this.url)) {
103+
this.stateURL = false;
104+
this.urlError = __("Please enter a valid URL.");
105+
return;
106+
}
107+
const site = this.siteName.toLocaleLowerCase().trim().replaceAll(" ", "_");
108+
const data = {
109+
key: `white_list.${site}`,
110+
format: "text",
111+
config: this.url,
112+
name: this.siteName,
113+
group: this.groupName,
114+
group_id: this.group_id,
115+
hidden: false,
116+
ui: null,
117+
};
118+
ProcessMaker.apiClient
119+
.post("settings", data)
120+
.then(() => {
121+
this.$parent.refresh();
122+
this.$refs["bv-modal-whitelist"].hide();
123+
});
124+
},
125+
},
126+
};
127+
</script>

resources/js/admin/settings/components/SettingsListing.vue

Lines changed: 43 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,7 @@
188188
</div>
189189
</div>
190190
</div>
191+
<modal-white-list ref="modal-whitelist" />
191192
</div>
192193
</template>
193194

@@ -211,8 +212,10 @@ import SettingsRange from './SettingsRange';
211212
import SettingDriverAuthorization from './SettingDriverAuthorization';
212213
import { createUniqIdsMixin } from "vue-uniq-ids";
213214
import SettingsEmpty from "./SettingsEmpty.vue";
215+
import ModalWhiteList from "./ModalWhiteList.vue";
214216
215217
const uniqIdsMixin = createUniqIdsMixin();
218+
const whiteListName = "IFrame Whitelist Config";
216219
217220
export default {
218221
components: {
@@ -232,6 +235,7 @@ export default {
232235
SettingsRange,
233236
SettingSelect,
234237
SettingsEmpty,
238+
ModalWhiteList,
235239
},
236240
mixins:[dataLoadingMixin, uniqIdsMixin],
237241
props: ['group'],
@@ -272,46 +276,55 @@ export default {
272276
},
273277
},
274278
mounted() {
275-
this.$on("refresh-menu", this.removeElement);
276-
if (! this.group) {
277-
this.orderBy = "group";
278-
this.fields.push({
279-
key: "group",
280-
label: "Group",
281-
sortable: true,
282-
tdClass: "td-group",
283-
});
284-
}
285-
286-
this.fields.push({
287-
key: "name",
288-
label: "Setting",
289-
sortable: true,
290-
tdClass: "align-middle td-name settings-listing-td1",
291-
});
279+
const that = this;
292280
293-
this.fields.push({
294-
key: "config",
295-
label: "Configuration",
296-
sortable: false,
297-
tdClass: "align-middle td-config settings-listing-td2",
298-
});
299-
300-
this.fields.push({
301-
key: "actions",
302-
label: "",
303-
sortable: false,
304-
tdClass: "align-middle settings-listing-td3",
305-
});
281+
this.$on("refresh-menu", this.removeElement);
282+
this.fillFields();
306283
307284
ProcessMaker.EventBus.$on('setting-added-from-modal', () => {
308285
this.shouldDisplayNoDataMessage = false;
309286
this.$nextTick(() => {
310287
this.refresh();
311288
});
312289
});
290+
291+
window.addWhiteListURL = function (owner) {
292+
that.$refs["modal-whitelist"].show(owner.group);
293+
};
313294
},
314295
methods: {
296+
fillFields() {
297+
if (!this.group) {
298+
this.orderBy = "group";
299+
this.fields.push({
300+
key: "group",
301+
label: "Group",
302+
sortable: true,
303+
tdClass: "td-group",
304+
});
305+
}
306+
307+
this.fields.push({
308+
key: "name",
309+
label: this.group === whiteListName ? "Name" : "Setting",
310+
sortable: true,
311+
tdClass: "align-middle td-name settings-listing-td1",
312+
});
313+
314+
this.fields.push({
315+
key: "config",
316+
label: this.group === whiteListName ? "Links" : "Configuration",
317+
sortable: false,
318+
tdClass: "align-middle td-config settings-listing-td2",
319+
});
320+
321+
this.fields.push({
322+
key: "actions",
323+
label: "",
324+
sortable: false,
325+
tdClass: "align-middle settings-listing-td3",
326+
});
327+
},
315328
loadButtons() {
316329
ProcessMaker.apiClient.get(`/settings/group/${this.group}/buttons`)
317330
.then((response) => {

resources/lang/en.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -444,6 +444,7 @@
444444
"Configure Script": "Configure Script",
445445
"Configure Template": "Configure Template",
446446
"Configure the authenticator app": "Configure the authenticator app",
447+
"Configure URL Parents for Embedding": "Configure URL Parents for Embedding",
447448
"Configure": "Configure",
448449
"Confirm and Save": "Confirm and Save",
449450
"Confirm New Password": "Confirm New Password",
@@ -1549,6 +1550,7 @@
15491550
"Please choose the tasks in your inbox that this new rule should apply to. <b>Use the column filters</b> to achieve this.": "Please choose the tasks in your inbox that this new rule should apply to. <b>Use the column filters</b> to achieve this.",
15501551
"Please contact your administrator to get started.": "Please contact your administrator to get started.",
15511552
"Please enter Tab Name": "Please enter Tab Name",
1553+
"Please provide a valid URL (e.g., https://example.com ) to specify the allowed origin(s) permitted to embed ProcessMaker.": "Please provide a valid URL (e.g., https://example.com ) to specify the allowed origin(s) permitted to embed ProcessMaker.",
15521554
"Please log in to continue your work on this page.": "Please log in to continue your work on this page.",
15531555
"Please select a Saved Search": "Please select a Saved Search",
15541556
"Please take a look at it in the 'Rules' section located within your Inbox.": "Please take a look at it in the 'Rules' section located within your Inbox.",

routes/api.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -321,6 +321,8 @@
321321
->name('settings.menu_groups')->middleware($viewSettings);
322322
Route::post('settings/import', [SettingController::class, 'import'])
323323
->name('settings.import')->middleware($updateSettings);
324+
Route::post('settings', [SettingController::class, 'store'])
325+
->name('settings.store')->middleware($updateSettings);
324326
Route::delete('settings/{setting}', [SettingController::class, 'destroy'])
325327
->name('settings.destroy')->middleware($updateSettings);
326328
Route::put('settings/{setting}', [SettingController::class, 'update'])

tests/Feature/Api/SettingsTest.php

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -174,4 +174,59 @@ public function testUpdateExtendedPropertiesWithInvalidVariableName()
174174
//Verify variable were not updated
175175
$this->assertDatabaseMissing('settings', ['config' => '{"1myVar":"This is my variable 1","myVar space":"This is my variable 2"}']);
176176
}
177+
178+
public function test_it_can_create_a_setting()
179+
{
180+
$menu = SettingsMenus::create([
181+
'menu_group' => 'Log-In & Auth',
182+
]);
183+
$data = [
184+
'key' => 'white_list.drive',
185+
'format' => 'text',
186+
'config' => 'https://drive.google.com',
187+
'name' => 'Drive',
188+
'group' => 'IFrame Whitelist Config',
189+
'group_id' => $menu->id,
190+
'hidden' => false,
191+
'ui' => null,
192+
];
193+
$route = route('api.settings.store');
194+
$response = $this->apiCall('POST', $route, $data);
195+
//Verify the status
196+
$response->assertStatus(201);
197+
}
198+
199+
public function test_it_returns_error_for_duplicate_entry()
200+
{
201+
$menu = SettingsMenus::create([
202+
'menu_group' => 'Log-In & Auth',
203+
]);
204+
// Create a setting first
205+
Setting::create([
206+
'key' => 'white_list.drive',
207+
'format' => 'text',
208+
'config' => 'https://drive.google.com',
209+
'name' => 'Drive',
210+
'group' => 'IFrame Whitelist Config',
211+
'group_id' => $menu->id,
212+
'hidden' => false,
213+
'ui' => null,
214+
]);
215+
// Data to create
216+
$data = [
217+
'key' => 'white_list.drive',
218+
'format' => 'text',
219+
'config' => 'https://drive.google.com',
220+
'name' => 'Drive',
221+
'group' => 'IFrame Whitelist Config',
222+
'group_id' => $menu->id,
223+
'hidden' => false,
224+
'ui' => null,
225+
];
226+
$route = route('api.settings.store');
227+
$response = $this->apiCall('POST', $route, $data);
228+
//Verify the status
229+
$response->assertStatus(409)
230+
->assertJson(['message' => 'The "Site Name" you\'re trying to add already exists. Please select a different name or review the existing entries to avoid duplication.']);
231+
}
177232
}

0 commit comments

Comments
 (0)