diff --git a/src/stores/settings.ts b/src/stores/settings.ts
index 0d235200..8ad9b331 100644
--- a/src/stores/settings.ts
+++ b/src/stores/settings.ts
@@ -44,6 +44,11 @@ interface State {
showYearly: boolean;
useMultidevice: boolean;
requestTimeout: number;
+ // Server configuration
+ cors: string;
+ cors_regex: string;
+ cors_allow_aw_chrome_extension: boolean;
+ cors_allow_all_mozilla_extension: boolean;
// Set to true if settings loaded
_loaded: boolean;
@@ -83,6 +88,10 @@ export const useSettingsStore = defineStore('settings', {
showYearly: false,
useMultidevice: false,
requestTimeout: 30,
+ cors: '',
+ cors_regex: '',
+ cors_allow_aw_chrome_extension: true,
+ cors_allow_all_mozilla_extension: false,
_loaded: false,
}),
diff --git a/src/views/settings/ServerSettings.vue b/src/views/settings/ServerSettings.vue
new file mode 100644
index 00000000..0332e491
--- /dev/null
+++ b/src/views/settings/ServerSettings.vue
@@ -0,0 +1,78 @@
+
+div
+ h4.mb-3 Security & CORS
+
+ b-alert(show variant="info" class="mb-4")
+ h5.alert-heading Require Restart
+ p.mb-0 Changing settings in this section requires stopping and restarting the server for the changes to take effect.
+
+ b-form-group(label="Fixed CORS origins" label-cols-md=4 description="Configure general CORS origins with exact matches (e.g. http://localhost:8080). Comma-separated.")
+ b-input(v-model="cors" type="text")
+
+ b-form-group(label="Regex CORS origins" label-cols-md=4 description="Configure CORS origins with regular expressions. Useful for browser extensions (e.g. chrome-extension://.* or moz-extension://.*). Comma-separated.")
+ b-input(v-model="corsregex" type="text")
+
+ h5.mt-4 Extensions Shortcuts
+ b-form-group(label-cols-md=4)
+ b-form-checkbox(v-model="cors_allow_aw_chrome_extension") Allow ActivityWatch extension (Chrome)
+ template(#description)
+ div Chrome extensions use a stable, persistent ID, so the official extension is reliably supported.
+
+ b-form-group(label-cols-md=4)
+ b-form-checkbox(v-model="cors_allow_all_mozilla_extension") Allow all Firefox extensions (DANGEROUS)
+ template(#description)
+ div Every version of a Mozilla extension has its own ID to avoid fingerprinting. This is why you must either allow all extensions or manually configure your specific ID.
+ div.mt-2.text-danger(v-if="cors_allow_all_mozilla_extension")
+ | ⚠️ DANGEROUS: Not recommended for security. If enabled, any installed extension can access your ActivityWatch data. Use this only if you know what extensions you have and assume full responsibility.
+ div(v-else)
+ | Recommended for security. To allow a specific extension safely:
+ ol.mt-2.mb-1
+ li Go to about:debugging#/runtime/this-firefox in your browser.
+ li Look for your extension and copy the Manifest URL (e.g. moz-extension://4b931c07dededdedff152/manifest.json).
+ li Remove manifest.json from the end (to get moz-extension://4b931c07dededdedff152).
+ li Paste it into the Regex CORS origins field above (use a comma to separate if not empty).
+
+
+
+
+
diff --git a/src/views/settings/Settings.vue b/src/views/settings/Settings.vue
index 0328ad18..14b193ab 100644
--- a/src/views/settings/Settings.vue
+++ b/src/views/settings/Settings.vue
@@ -37,6 +37,10 @@ div
hr
DeveloperSettings
+
+ hr
+
+ ServerSettings